From d4a9842375080c1a78404d9353455543d808a60b Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Mon, 2 Dec 2019 15:34:57 +0100 Subject: [PATCH] Initial gradle build layer. --- .gitattributes | 2 + .gitignore | 3 + .travis.yml | 17 + build.gradle | 49 +++ gradle.TODO | 52 +++ gradle.properties | 4 + gradle/ant-compat/artifact-naming.gradle | 15 + gradle/ant-compat/folder-layout.gradle | 26 ++ gradle/ant-compat/misc.gradle | 42 +++ gradle/ant-compat/post-jar.gradle | 34 ++ gradle/ant-compat/resolve.gradle | 210 +++++++++++ .../ant-compat/test-classes-cross-deps.gradle | 53 +++ gradle/buildscan.gradle | 5 + gradle/defaults-idea.gradle | 12 + gradle/defaults-java.gradle | 11 + gradle/defaults-maven.gradle | 121 +++++++ gradle/defaults.gradle | 18 + gradle/help.gradle | 30 ++ gradle/maven-local.gradle | 42 +++ gradle/testing/defaults-tests-solr.gradle | 13 + gradle/testing/defaults-tests.gradle | 51 +++ gradle/testing/per-project-summary.gradle | 20 ++ gradle/testing/randomization.gradle | 72 ++++ gradle/testing/slowest-tests-at-end.gradle | 31 ++ gradle/travis.gradle | 21 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 56177 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 172 +++++++++ gradlew.bat | 84 +++++ help/ant.txt | 49 +++ help/tests.txt | 83 +++++ help/workflow.txt | 33 ++ lucene/analysis/common/build.gradle | 7 + lucene/analysis/icu/build.gradle | 10 + lucene/analysis/kuromoji/build.gradle | 8 + lucene/analysis/morfologik/build.gradle | 13 + lucene/analysis/nori/build.gradle | 8 + lucene/analysis/opennlp/build.gradle | 9 + lucene/analysis/phonetic/build.gradle | 11 + lucene/analysis/smartcn/build.gradle | 8 + lucene/analysis/stempel/build.gradle | 8 + lucene/backward-codecs/build.gradle | 7 + lucene/benchmark/build.gradle | 22 ++ lucene/build.gradle | 3 + lucene/classification/build.gradle | 12 + lucene/codecs/build.gradle | 6 + lucene/core/build.gradle | 7 + lucene/demo/build.gradle | 12 + lucene/expressions/build.gradle | 20 ++ lucene/facet/build.gradle | 12 + lucene/grouping/build.gradle | 10 + lucene/highlighter/build.gradle | 12 + lucene/join/build.gradle | 6 + lucene/luke/build.gradle | 16 + lucene/memory/build.gradle | 9 + lucene/misc/build.gradle | 6 + lucene/monitor/build.gradle | 11 + lucene/queries/build.gradle | 8 + lucene/queryparser/build.gradle | 9 + lucene/replicator/build.gradle | 19 + lucene/sandbox/build.gradle | 6 + lucene/spatial-extras/build.gradle | 14 + lucene/spatial/build.gradle | 6 + lucene/spatial3d/build.gradle | 6 + lucene/suggest/build.gradle | 8 + lucene/test-framework/build.gradle | 11 + settings.gradle | 55 +++ solr/build.gradle | 3 + solr/contrib/analysis-extras/build.gradle | 16 + solr/contrib/analytics/build.gradle | 6 + solr/contrib/clustering/build.gradle | 12 + .../dataimporthandler-extras/build.gradle | 14 + solr/contrib/dataimporthandler/build.gradle | 15 + solr/contrib/extraction/build.gradle | 55 +++ .../jaegertracer-configurator/build.gradle | 12 + solr/contrib/langid/build.gradle | 15 + solr/contrib/ltr/build.gradle | 14 + solr/contrib/prometheus-exporter/build.gradle | 28 ++ solr/contrib/velocity/build.gradle | 14 + solr/core/build.gradle | 129 +++++++ solr/example/build.gradle | 46 +++ solr/packaging/build.gradle | 95 +++++ solr/server/build.gradle | 107 ++++++ solr/solr-ref-guide/build.gradle | 328 ++++++++++++++++++ solr/solrj/build.gradle | 55 +++ solr/test-framework/build.gradle | 15 + solr/webapp/build.gradle | 37 ++ versions.lock | 230 ++++++++++++ versions.props | 111 ++++++ 89 files changed, 3132 insertions(+) create mode 100644 .gitattributes create mode 100644 .travis.yml create mode 100644 build.gradle create mode 100644 gradle.TODO create mode 100644 gradle.properties create mode 100644 gradle/ant-compat/artifact-naming.gradle create mode 100644 gradle/ant-compat/folder-layout.gradle create mode 100644 gradle/ant-compat/misc.gradle create mode 100644 gradle/ant-compat/post-jar.gradle create mode 100644 gradle/ant-compat/resolve.gradle create mode 100644 gradle/ant-compat/test-classes-cross-deps.gradle create mode 100644 gradle/buildscan.gradle create mode 100644 gradle/defaults-idea.gradle create mode 100644 gradle/defaults-java.gradle create mode 100644 gradle/defaults-maven.gradle create mode 100644 gradle/defaults.gradle create mode 100644 gradle/help.gradle create mode 100644 gradle/maven-local.gradle create mode 100644 gradle/testing/defaults-tests-solr.gradle create mode 100644 gradle/testing/defaults-tests.gradle create mode 100644 gradle/testing/per-project-summary.gradle create mode 100644 gradle/testing/randomization.gradle create mode 100644 gradle/testing/slowest-tests-at-end.gradle create mode 100644 gradle/travis.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 help/ant.txt create mode 100644 help/tests.txt create mode 100644 help/workflow.txt create mode 100644 lucene/analysis/common/build.gradle create mode 100644 lucene/analysis/icu/build.gradle create mode 100644 lucene/analysis/kuromoji/build.gradle create mode 100644 lucene/analysis/morfologik/build.gradle create mode 100644 lucene/analysis/nori/build.gradle create mode 100644 lucene/analysis/opennlp/build.gradle create mode 100644 lucene/analysis/phonetic/build.gradle create mode 100644 lucene/analysis/smartcn/build.gradle create mode 100644 lucene/analysis/stempel/build.gradle create mode 100644 lucene/backward-codecs/build.gradle create mode 100644 lucene/benchmark/build.gradle create mode 100644 lucene/build.gradle create mode 100644 lucene/classification/build.gradle create mode 100644 lucene/codecs/build.gradle create mode 100644 lucene/core/build.gradle create mode 100644 lucene/demo/build.gradle create mode 100644 lucene/expressions/build.gradle create mode 100644 lucene/facet/build.gradle create mode 100644 lucene/grouping/build.gradle create mode 100644 lucene/highlighter/build.gradle create mode 100644 lucene/join/build.gradle create mode 100644 lucene/luke/build.gradle create mode 100644 lucene/memory/build.gradle create mode 100644 lucene/misc/build.gradle create mode 100644 lucene/monitor/build.gradle create mode 100644 lucene/queries/build.gradle create mode 100644 lucene/queryparser/build.gradle create mode 100644 lucene/replicator/build.gradle create mode 100644 lucene/sandbox/build.gradle create mode 100644 lucene/spatial-extras/build.gradle create mode 100644 lucene/spatial/build.gradle create mode 100644 lucene/spatial3d/build.gradle create mode 100644 lucene/suggest/build.gradle create mode 100644 lucene/test-framework/build.gradle create mode 100644 settings.gradle create mode 100644 solr/build.gradle create mode 100644 solr/contrib/analysis-extras/build.gradle create mode 100644 solr/contrib/analytics/build.gradle create mode 100644 solr/contrib/clustering/build.gradle create mode 100644 solr/contrib/dataimporthandler-extras/build.gradle create mode 100644 solr/contrib/dataimporthandler/build.gradle create mode 100644 solr/contrib/extraction/build.gradle create mode 100644 solr/contrib/jaegertracer-configurator/build.gradle create mode 100644 solr/contrib/langid/build.gradle create mode 100644 solr/contrib/ltr/build.gradle create mode 100644 solr/contrib/prometheus-exporter/build.gradle create mode 100644 solr/contrib/velocity/build.gradle create mode 100644 solr/core/build.gradle create mode 100644 solr/example/build.gradle create mode 100644 solr/packaging/build.gradle create mode 100644 solr/server/build.gradle create mode 100644 solr/solr-ref-guide/build.gradle create mode 100644 solr/solrj/build.gradle create mode 100644 solr/test-framework/build.gradle create mode 100644 solr/webapp/build.gradle create mode 100644 versions.lock create mode 100644 versions.props diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..e37d866ca89 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Ignore all differences in line endings for the lock file. +versions.lock text eol=lf diff --git a/.gitignore b/.gitignore index d0f0adedeb3..023c82798d6 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ __pycache__ /dev-tools/scripts/scripts.iml .DS_Store +build/ +.gradle/ +.idea/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..6cab06fbe26 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: java + +jdk: + - openjdk11 + +before_cache: + - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock + - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ + +cache: + directories: + - $HOME/.gradle/caches/ + - $HOME/.gradle/wrapper/ + +script: + - ./gradlew assemble --scan --stacktrace -Ptravis + diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000000..04c83cf1ebc --- /dev/null +++ b/build.gradle @@ -0,0 +1,49 @@ +plugins { + id "base" + id "com.palantir.consistent-versions" version "1.12.4" + id "com.gradle.build-scan" version "3.0" +} + +// Project version and main properties. Applies to all projects. +allprojects { + version = "9.0.0-SNAPSHOT" +} + +// Include smaller chunks configuring dedicated build areas. +// Some of these intersect or add additional functionality. +// The order of inclusion of these files shouldn't matter (but may +// if the build file is incorrectly written and evaluates something +// eagerly). + +// CI systems. +apply from: file('gradle/buildscan.gradle') +apply from: file('gradle/travis.gradle') + +// Set up defaults and configure aspects for certain modules or functionality +// (java, tests) +apply from: file('gradle/defaults.gradle') +apply from: file('gradle/defaults-java.gradle') +apply from: file('gradle/testing/defaults-tests.gradle') +apply from: file('gradle/testing/defaults-tests-solr.gradle') +apply from: file('gradle/testing/randomization.gradle') +apply from: file('gradle/defaults-maven.gradle') + +// IDE settings and specials. +apply from: file('gradle/defaults-idea.gradle') + +// Additional development aids. +apply from: file('gradle/maven-local.gradle') +apply from: file('gradle/testing/per-project-summary.gradle') +apply from: file('gradle/testing/slowest-tests-at-end.gradle') +apply from: file('gradle/help.gradle') + +// Ant-compatibility layer. ALL OF THESE SHOULD BE GONE at some point. They are +// here so that we can coexist with current ant build but they are indicative +// of potential problems with the build conventions, dependencies, etc. +apply from: file('gradle/ant-compat/folder-layout.gradle') +apply from: file('gradle/ant-compat/misc.gradle') +apply from: file('gradle/ant-compat/resolve.gradle') +apply from: file('gradle/ant-compat/post-jar.gradle') +apply from: file('gradle/ant-compat/test-classes-cross-deps.gradle') +apply from: file('gradle/ant-compat/artifact-naming.gradle') + diff --git a/gradle.TODO b/gradle.TODO new file mode 100644 index 00000000000..4dffe42658e --- /dev/null +++ b/gradle.TODO @@ -0,0 +1,52 @@ + +The gradle build is currently missing or could use some love in the following areas: + +- Apply forbiddenAPIs + +- configure security policy/ sandboxing for tests (!). + +- add test 'beasting' (rerunning the same suite multiple times). I'm afraid it'll be difficult + to run it sensibly because gradle doesn't offer cwd separation for the forked test runners (?) + +- jar checksums, jar checksum computation and validation. + this should be done without intermediate folders (directly + on dependency sets). + +- add a :helpDeps explanation to how the dependency system works (palantir plugin, lockfile) and + how to retrieve structured information about current dependencies of a given module + (in a tree-like output). + +- identify and list precommit tasks so that they can be ported one by one. + +- identify and port any other "check" utilities that may be called from ant. + +- identify and port various "regenerate" tasks from ant builds (javacc, precompiled automata, etc.) + +- add rendering of javadocs (gradlew javadoc) and attaching them to maven publications. + +- fill in POM details in gradle/defaults-maven.gradle so that they reflect the previous content better + (dependencies aside). + +- Add any IDE integration layers that should be added (I use IntelliJ and it imports the project + out of the box, without the need for any special tuning). + +- Clean up dependencies, especially for Solr: any { transitive = false } should just explicitly + exclude whatever they don't need (and their dependencies currently declared explicitly + should be folded). Figure out which scope to import a dependency to. + +- add Solr packaging for docs/* (see TODO in packaging/build.gradle; currently XSLT...) + +- I didn't bother adding Solr dist/test-framework to packaging (who'd use it from a binary + distribution?) + +Intentional differences: + +- the back-compatibility target 'resolve' is added to gradle but it's really for informational purposes + and debugging. Packaging should be done from subcomponent configurations and dependencies, + not from source folders... "gradlew -p packaging assemble" puts together the entire Solr distribution + under packaging/build where it doesn't interfere with sources. + + 'resolve' for Lucene also does *not* copy test dependencies under lib/ (like ant version does). + +- transitive export of certain core libraries from solr-core/ solrj (guava, etc.). + diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000000..928cfe44815 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,4 @@ +systemProp.file.encoding=UTF-8 + +org.gradle.parallel=true +org.gradle.priority=low diff --git a/gradle/ant-compat/artifact-naming.gradle b/gradle/ant-compat/artifact-naming.gradle new file mode 100644 index 00000000000..9fe4f391aa1 --- /dev/null +++ b/gradle/ant-compat/artifact-naming.gradle @@ -0,0 +1,15 @@ +// Stick to previous artifact names (not identical to path/ folders). +configure(subprojects.findAll { it.path.contains(':solr:contrib:') }) { + project.archivesBaseName = project.archivesBaseName.replace("-contrib-", "-") +} + +// This project has a different artifact name (solr-contrib-cell). Don't know why. +configure(project(":solr:contrib:extraction")) { + archivesBaseName = "solr-cell" +} + +configure(subprojects.findAll { it.path.contains(':lucene:analysis:') }) { + project.archivesBaseName = project.archivesBaseName.replace("-analysis-", "-analyzers-") +} + + diff --git a/gradle/ant-compat/folder-layout.gradle b/gradle/ant-compat/folder-layout.gradle new file mode 100644 index 00000000000..d6410a91e0c --- /dev/null +++ b/gradle/ant-compat/folder-layout.gradle @@ -0,0 +1,26 @@ +// Adapt to custom folder convention. +allprojects { + plugins.withType(JavaPlugin) { + sourceSets { + main.java.srcDirs = ['src/java'] + main.resources.srcDirs = ['src/resources'] + test.java.srcDirs = ['src/test'] + test.resources.srcDirs = ['src/test-files'] + } + + task copyTestResources(type: Copy) { + from('src/test') { + exclude '**/*.java' + } + into sourceSets.test.java.outputDir + } + processTestResources.dependsOn copyTestResources + } +} + +// Adapt to custom 'web' folder location. +configure(project(":solr:webapp")) { + plugins.withType(WarPlugin) { + webAppDirName = "web" + } +} diff --git a/gradle/ant-compat/misc.gradle b/gradle/ant-compat/misc.gradle new file mode 100644 index 00000000000..7ffadb2be0f --- /dev/null +++ b/gradle/ant-compat/misc.gradle @@ -0,0 +1,42 @@ + +// Exclude inner classes from testing. +allprojects { + tasks.withType(Test) { task -> + exclude '**/*$*' + } +} + +// Exclude test classes that are not actually stand-alone tests (they're executed from other stuff). +configure(project(":lucene:replicator")) { + plugins.withType(JavaPlugin) { + test { + exclude "**/SimpleServer*" + } + } +} + + +// Resources from top-level project folder are looked up via getClass(). Strange. +configure(project(":lucene:benchmark")) { + plugins.withType(JavaPlugin) { + task syncConf(type: Sync) { + from('conf') + into file("${sourceSets.test.java.outputDir}/conf") + } + processTestResources.dependsOn syncConf + } +} + +// lucene:replicator has httpclient dependency with transitive commons-logging:1.2 but currently +// requires 1.1.2. This commons-logging should be removed entirely and replaced with slf4j-to-* +// redirector. +configure(project(":lucene:replicator")) { + plugins.withType(JavaPlugin) { + configurations.all { + resolutionStrategy { + force 'commons-logging:commons-logging:1.1.3' + } + } + } +} + diff --git a/gradle/ant-compat/post-jar.gradle b/gradle/ant-compat/post-jar.gradle new file mode 100644 index 00000000000..991a979bf36 --- /dev/null +++ b/gradle/ant-compat/post-jar.gradle @@ -0,0 +1,34 @@ +// This adds a configuration and artifact to solr-core which exports "post.jar" tool. +// this should be a separate project instead (it is self-contained and classes are reused +// in many places). + +configure(project(":solr:core")) { + plugins.withType(JavaPlugin) { + configurations { + postJar + } + + task assemblePostJar(type: Jar) { + dependsOn classes + + archiveFileName = "post.jar" + destinationDirectory = file("${buildDir}/postJar") + + from(sourceSets.main.output, { + include "org/apache/solr/util/CLIO.class" + include "org/apache/solr/util/SimplePostTool*.class" + include "org/apache/solr/util/RTimer*.class" + }) + + manifest { + attributes("Main-Class": "org.apache.solr.util.SimplePostTool") + } + } + + artifacts { + postJar assemblePostJar + } + + assemble.dependsOn assemblePostJar + } +} \ No newline at end of file diff --git a/gradle/ant-compat/resolve.gradle b/gradle/ant-compat/resolve.gradle new file mode 100644 index 00000000000..051bdff81b7 --- /dev/null +++ b/gradle/ant-compat/resolve.gradle @@ -0,0 +1,210 @@ + +// For Lucene, a 'resolve' task that copies any (non-project) dependencies +// under lib/ folder. +configure(allprojects.findAll {project -> project.path.startsWith(":lucene") }) { + plugins.withType(JavaPlugin) { + configurations { + runtimeLibs { + extendsFrom runtimeElements + extendsFrom testRuntimeClasspath + } + } + + task resolve(type: Sync) { + from({ + return configurations.runtimeLibs.copyRecursive { dep -> + !(dep instanceof org.gradle.api.artifacts.ProjectDependency) + } + }) + + into 'lib' + } + } +} + +// For Solr, a 'resolve' task is much more complex. There are three folders: +// lib/ +// test-lib/ +// lucene-libs/ +// +// There doesn't seem to be one ideal set of rules on how these should be created, but +// I tried to imitate the current (master) logic present in ivy and ant files in this way: +// +// The "solr platform" set of dependencies is a union of all deps for (core, solrj, server). +// +// Then: +// lib - these are module's "own" dependencies, excluding Lucene's that are not present in the +// solr platform. +// lucene-libs - these are lucene modules declared as module's dependencies and not +// present in solr platform. +// test-lib/ - libs not present in solr platform and not included in solr:test-framework. +// +// None of these are really needed with gradle... they should be collected just in the distribution +// package, not at each project's level. +// +// Unfortunately this "resolution" process is also related to how the final Solr packaging is assembled. +// I don't know how to untie these two cleanly. +// + +configure(allprojects.findAll {project -> project.path.startsWith(":solr:contrib") }) { + plugins.withType(JavaPlugin) { + ext { + packagingDir = file("${buildDir}/packaging") + deps = file("${packagingDir}/${project.name}") + } + + configurations { + solrPlatformLibs + solrTestPlatformLibs + runtimeLibs { + extendsFrom runtimeElements + } + packaging + } + + dependencies { + solrPlatformLibs project(":solr:core") + solrPlatformLibs project(":solr:solrj") + solrPlatformLibs project(":solr:server") + + solrTestPlatformLibs project(":solr:test-framework") + } + + // An aggregate that configures lib, lucene-libs and test-lib in a temporary location. + task assemblePackaging(type: Sync) { + from "README.txt" + + from ({ + def externalLibs = configurations.runtimeLibs.copyRecursive { dep -> + if (dep instanceof org.gradle.api.artifacts.ProjectDependency) { + return !dep.dependencyProject.path.startsWith(":solr") + } else { + return true + } + } + return externalLibs - configurations.solrPlatformLibs + }, { + exclude "lucene-*" + into "lib" + }) + + from ({ + def projectLibs = configurations.runtimeLibs.copyRecursive { dep -> + (dep instanceof org.gradle.api.artifacts.ProjectDependency) + } + return projectLibs - configurations.solrPlatformLibs + }, { + include "lucene-*" + into "lucene-libs" + }) + + into deps + } + + task syncLib(type: Sync) { + dependsOn assemblePackaging + + from(file("${deps}/lib"), { + include "**" + }) + into file("${projectDir}/lib") + } + + task syncTestLib(type: Sync) { + // From test runtime classpath exclude: + // 1) project dependencies (and their dependencies) + // 2) runtime dependencies + // What remains is this module's "own" test dependency. + from({ + def testRuntimeLibs = configurations.testRuntimeClasspath.copyRecursive { dep -> + !(dep instanceof org.gradle.api.artifacts.ProjectDependency) + } + + return testRuntimeLibs - configurations.runtimeLibs - configurations.solrTestPlatformLibs + }) + + into file("${projectDir}/test-lib") + } + + task resolve() { + dependsOn syncLib, syncTestLib + } + + // Contrib packaging currently depends on internal resolve. + artifacts { + packaging packagingDir, { + builtBy assemblePackaging + } + } + } +} + +configure(project(":solr:example")) { + evaluationDependsOn(":solr:example") // explicitly wait for other configs to be applied + + task resolve(type: Copy) { + from(configurations.postJar, { + into "exampledocs/" + }) + + from(configurations.dih, { + into "example-DIH/solr/db/lib" + }) + + into projectDir + } +} + +configure(project(":solr:server")) { + evaluationDependsOn(":solr:server") + + task resolve(type: Copy) { + dependsOn assemblePackaging + + from({ packagingDir }, { + include "**/*.jar" + include "solr-webapp/webapp/**" + includeEmptyDirs false + }) + + into projectDir + } +} + +configure(project(":solr:core")) { + evaluationDependsOn(":solr:core") + + configurations { + runtimeLibs { + extendsFrom runtimeElements + } + } + + task resolve(type: Sync) { + from({ + def ownDeps = configurations.runtimeLibs.copyRecursive { dep -> + if (dep instanceof org.gradle.api.artifacts.ProjectDependency) { + return !dep.dependencyProject.path.startsWith(":solr") + } else { + return true + } + } + return ownDeps + }, { + exclude "lucene-*" + }) + + into "lib" + } +} + +configure(project(":solr:solrj")) { + evaluationDependsOn(":solr:solrj") + + task resolve(type: Sync) { + from({ configurations.runtimeClasspath }, { + }) + + into "lib" + } +} \ No newline at end of file diff --git a/gradle/ant-compat/test-classes-cross-deps.gradle b/gradle/ant-compat/test-classes-cross-deps.gradle new file mode 100644 index 00000000000..02057ac0071 --- /dev/null +++ b/gradle/ant-compat/test-classes-cross-deps.gradle @@ -0,0 +1,53 @@ +// Set up cross-project dependency on test classes. This should be resolved by pulling reused classes into +// a separate regular module. Exporting test classes is sort of weird. +configure([project(":lucene:spatial3d"), + project(":lucene:analysis:common"), + project(":lucene:backward-codecs"), + project(":lucene:queryparser"), + project(":solr:contrib:dataimporthandler")]) { + plugins.withType(JavaPlugin) { + configurations { + testClassesExported + } + + artifacts { + testClassesExported sourceSets.test.java.outputDir, { + builtBy testClasses + } + } + } +} + +configure(project(":lucene:spatial-extras")) { + plugins.withType(JavaPlugin) { + dependencies { + testImplementation project(path: ':lucene:spatial3d', configuration: 'testClassesExported') + } + } +} + +configure(project(":solr:core")) { + plugins.withType(JavaPlugin) { + dependencies { + testImplementation project(path: ':lucene:backward-codecs', configuration: 'testClassesExported') + testImplementation project(path: ':lucene:queryparser', configuration: 'testClassesExported') + } + } +} + +configure(project(":solr:contrib:analysis-extras")) { + plugins.withType(JavaPlugin) { + dependencies { + testImplementation project(path: ':lucene:analysis:common', configuration: 'testClassesExported') + testImplementation project(path: ':solr:contrib:dataimporthandler', configuration: 'testClassesExported') + } + } +} + +configure(project(":solr:contrib:dataimporthandler-extras")) { + plugins.withType(JavaPlugin) { + dependencies { + testImplementation project(path: ':solr:contrib:dataimporthandler', configuration: 'testClassesExported') + } + } +} diff --git a/gradle/buildscan.gradle b/gradle/buildscan.gradle new file mode 100644 index 00000000000..83d0b711265 --- /dev/null +++ b/gradle/buildscan.gradle @@ -0,0 +1,5 @@ + +buildScan { + termsOfServiceUrl = "https://gradle.com/terms-of-service" + termsOfServiceAgree = "yes" +} diff --git a/gradle/defaults-idea.gradle b/gradle/defaults-idea.gradle new file mode 100644 index 00000000000..b832324cb8c --- /dev/null +++ b/gradle/defaults-idea.gradle @@ -0,0 +1,12 @@ +allprojects { + apply plugin: 'idea' + + idea { + module { + outputDir file('build/idea/classes/main') + testOutputDir file('build/idea/classes/test') + downloadSources = true + } + } +} + diff --git a/gradle/defaults-java.gradle b/gradle/defaults-java.gradle new file mode 100644 index 00000000000..896b8bb233b --- /dev/null +++ b/gradle/defaults-java.gradle @@ -0,0 +1,11 @@ +// Configure Java project defaults. + +allprojects { + plugins.withType(JavaPlugin) { + sourceCompatibility = "11" + targetCompatibility = "11" + + compileJava.options.encoding = "UTF-8" + compileTestJava.options.encoding = "UTF-8" + } +} diff --git a/gradle/defaults-maven.gradle b/gradle/defaults-maven.gradle new file mode 100644 index 00000000000..35dcab35c79 --- /dev/null +++ b/gradle/defaults-maven.gradle @@ -0,0 +1,121 @@ + +// Maven publications and configuration. +// +// the 'published' list contains an explicit list of all projects +// which should be published to Maven repositories. + +configure(rootProject) { + ext { + published = [ + ":lucene:analysis:common", + ":lucene:analysis:icu", + ":lucene:analysis:kuromoji", + ":lucene:analysis:morfologik", + ":lucene:analysis:nori", + ":lucene:analysis:opennlp", + ":lucene:analysis:phonetic", + ":lucene:analysis:smartcn", + ":lucene:analysis:stempel", + ":lucene:backward-codecs", + ":lucene:benchmark", + ":lucene:classification", + ":lucene:codecs", + ":lucene:core", + ":lucene:demo", + ":lucene:expressions", + ":lucene:facet", + ":lucene:grouping", + ":lucene:highlighter", + ":lucene:join", + ":lucene:luke", + ":lucene:memory", + ":lucene:misc", + ":lucene:monitor", + ":lucene:queries", + ":lucene:queryparser", + ":lucene:replicator", + ":lucene:sandbox", + ":lucene:spatial", + ":lucene:spatial-extras", + ":lucene:spatial3d", + ":lucene:suggest", + ":lucene:test-framework", + + ":solr:core", + ":solr:solrj", + ":solr:contrib:analysis-extras", + ":solr:contrib:dataimporthandler", + ":solr:contrib:dataimporthandler-extras", + ":solr:contrib:analytics", + ":solr:contrib:clustering", + ":solr:contrib:extraction", + ":solr:contrib:langid", + ":solr:contrib:jaegertracer-configurator", + ":solr:contrib:prometheus-exporter", + ":solr:contrib:velocity", + ":solr:test-framework", + ] + } + + configure(subprojects.findAll { it.path in rootProject.published }) { + apply plugin: 'maven-publish' + apply plugin: 'signing' + + publishing { + // TODO: Add publishing repository details. + } + + plugins.withType(JavaPlugin) { + task sourcesJar(type: Jar, dependsOn: classes) { + archiveClassifier = 'sources' + from sourceSets.main.allJava + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + archiveClassifier = 'javadoc' + from javadoc.destinationDir + } + + publishing { + def configurePom = { + name = "Apache Solr/Lucene (${project.name})" + licenses { + license { + name = 'Apache 2' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + } + + publications { + // JARS and sources, no javadocs (for local inspection only). + jars(MavenPublication) { + from components.java + groupId = project.group + artifactId = project.archivesBaseName + + artifact sourcesJar + + pom(configurePom) + } + + // Full set of signed artifacts. + signed(MavenPublication) { + from components.java + groupId = project.group + artifactId = project.archivesBaseName + + artifact sourcesJar + artifact javadocJar + + pom(configurePom) + } + } + } + + signing { + sign publishing.publications.signed + } + } + } +} diff --git a/gradle/defaults.gradle b/gradle/defaults.gradle new file mode 100644 index 00000000000..474826eca9d --- /dev/null +++ b/gradle/defaults.gradle @@ -0,0 +1,18 @@ +allprojects { + apply plugin: 'base' + + group "org.apache" + + // Repositories to fetch dependencies from. + repositories { + mavenCentral() + + maven { + url "https://maven.restlet.com" + } + } + + // Artifacts will have names after full gradle project path + // so :solr:core will have solr-core.jar, etc. + project.archivesBaseName = project.path.replaceAll("^:", "").replace(':', '-') +} diff --git a/gradle/help.gradle b/gradle/help.gradle new file mode 100644 index 00000000000..01fce34b00d --- /dev/null +++ b/gradle/help.gradle @@ -0,0 +1,30 @@ +// Add "help" tasks which display plain text files under 'help' folder. + +configure(rootProject) { + def helpFiles = [ + ["Workflow", "help/workflow.txt", "Typical workflow commands."], + ["Ant", "help/ant-gradle.txt", "Ant-gradle migration help."], + ["Tests", "help/tests.txt", "Tests, filtering, beasting, etc."], + ] + + helpFiles.each { section, path, sectionInfo -> + task "help${section}" { + group = 'Help (developer guides and hints)' + description = sectionInfo + doFirst { + println "\n" + rootProject.file(path).getText("UTF-8") + } + } + } + + help { + doLast { + println "" + println "This is an experimental Lucene/Solr gradle build. See some" + println "guidelines, ant-equivalent commands etc. under help/*; or type:" + helpFiles.each { entry -> + println " gradlew :help${entry[0]} # ${entry[2]}" + } + } + } +} diff --git a/gradle/maven-local.gradle b/gradle/maven-local.gradle new file mode 100644 index 00000000000..25a4746773d --- /dev/null +++ b/gradle/maven-local.gradle @@ -0,0 +1,42 @@ + +// This adds a root project task to install all artifacts to a build-local +// Maven repository (so that pom files can be manually reviewed). + +configure(rootProject) { + ext { + mavenLocalDir = file("${buildDir}/maven-local") + } + + task mavenLocal() { + group "Publishing" + description "Publish Maven JARs and POMs locally to " + mavenLocalDir + + doLast { + logger.lifecycle "Local maven artifacts (poms, jars) created at: ${mavenLocalDir}" + } + } + + task mavenLocalClean(type: Delete) { + delete mavenLocalDir + } + + configure(subprojects.findAll { it.path in rootProject.published }) { + plugins.withType(PublishingPlugin) { + publishing { + repositories { + maven { + name = 'build' + url = mavenLocalDir + } + } + } + + tasks.matching { it.name == "publishJarsPublicationToBuildRepository" }.all { task -> + // Clean prior to republishing to local build repository. + task.dependsOn mavenLocalClean + // Attach to root project's mavenLocal task. + mavenLocal.dependsOn task + } + } + } +} \ No newline at end of file diff --git a/gradle/testing/defaults-tests-solr.gradle b/gradle/testing/defaults-tests-solr.gradle new file mode 100644 index 00000000000..be84a59f6e4 --- /dev/null +++ b/gradle/testing/defaults-tests-solr.gradle @@ -0,0 +1,13 @@ +import org.apache.tools.ant.taskdefs.condition.Os + +// Solr-specific test configs. + +configure(allprojects.findAll {project -> project.path.startsWith(":solr") }) { + plugins.withType(JavaPlugin) { + test { + systemProperty 'tests.disableHdfs', Os.isFamily(Os.FAMILY_WINDOWS) ? 'true' : 'false' + systemProperty 'jetty.testMode', '1' + systemProperty 'jetty.insecurerandom', '1' + } + } +} diff --git a/gradle/testing/defaults-tests.gradle b/gradle/testing/defaults-tests.gradle new file mode 100644 index 00000000000..668cb84f02d --- /dev/null +++ b/gradle/testing/defaults-tests.gradle @@ -0,0 +1,51 @@ +import org.apache.tools.ant.taskdefs.condition.Os +import org.gradle.api.tasks.testing.logging.* + +allprojects { + plugins.withType(JavaPlugin) { + project.ext { + testsWorkDir = file("${buildDir}/tmp/tests-cwd") + testsTmpDir = file("${buildDir}/tmp/tests-tmp") + } + + test { + workingDir testsWorkDir + + useJUnit() + + // Set up default parallel execution limits. + maxParallelForks = (int) Math.max(1, Math.min(Runtime.runtime.availableProcessors() / 2.0, 3.0)) + + minHeapSize = "256m" + maxHeapSize = "512m" + + systemProperty 'java.awt.headless', 'true' + systemProperty 'jdk.map.althashing.threshold', '0' + + if (!Os.isFamily(Os.FAMILY_WINDOWS)) { + systemProperty 'java.security.egd', 'file:/dev/./urandom' + } + + // Set up cwd and temp locations. + systemProperty("java.io.tmpdir", testsTmpDir) + doFirst { + testsWorkDir.mkdirs() + testsTmpDir.mkdirs() + } + + // Set up logging. + testLogging { + events TestLogEvent.FAILED + exceptionFormat TestExceptionFormat.FULL + showExceptions true + showCauses true + showStackTraces true + } + + doFirst { + // Print some diagnostics about locations used. + logger.info("Test folders for {}: cwd={}, tmp={}", project.path, testsWorkDir, testsTmpDir) + } + } + } +} diff --git a/gradle/testing/per-project-summary.gradle b/gradle/testing/per-project-summary.gradle new file mode 100644 index 00000000000..ec5281e87ea --- /dev/null +++ b/gradle/testing/per-project-summary.gradle @@ -0,0 +1,20 @@ + +// Per-project test summary. + +allprojects { + tasks.withType(Test) { task -> + afterSuite { desc, result -> + if (!desc.parent) { + if (result.testCount > 0) { + def components = [ + "test(s)" : result.testCount, + "failure(s)": result.failedTestCount, + "skipped" : result.skippedTestCount + ].findAll { k, v -> v > 0 }.collect { k, v -> "$v $k" }.join(", ") + + logger.lifecycle("${task.path} (${result.resultType}): ${components}") + } + } + } + } +} diff --git a/gradle/testing/randomization.gradle b/gradle/testing/randomization.gradle new file mode 100644 index 00000000000..8024264cabe --- /dev/null +++ b/gradle/testing/randomization.gradle @@ -0,0 +1,72 @@ + +// Configure test randomization seeds and derived test properties. + +allprojects { + ext { + // Support passing overrides via -P or -D. + propertyOrDefault = { propName, defValue -> + def result + if (project.hasProperty(propName)) { + result = project.getProperty(propName) + } else if (System.properties.containsKey(propName)) { + result = System.properties.get(propName) + } else { + result = defValue + } + return result + } + } +} + +// Pick the "root" seed from which everything else is derived. +configure(rootProject) { + ext { + rootSeed = propertyOrDefault('tests.seed', String.format("%08X", new Random().nextLong())) + } + + task randomizationInfo() { + doFirst { + logger.lifecycle("Running tests with randomization seed: tests.seed=${rootSeed}") + } + } +} + +// Any test task will trigger display of randomization settings. +allprojects { + tasks.withType(Test) { task -> + task.dependsOn rootProject.randomizationInfo + } +} + +// Append randomization properties to tests, allow overriding these properties with -Pkey=value. +allprojects { + tasks.withType(Test) { task -> + [ + 'tests.seed': rootSeed, + 'tests.multiplier': '1', + 'tests.codec': 'random', + 'tests.postingsformat': 'random', + 'tests.docvaluesformat': 'random', + 'tests.locale': 'random', + 'tests.timezone': 'random', + 'tests.directory': 'random', + 'tests.nightly': 'false', + 'tests.weekly': 'false', + 'tests.monster': 'false', + 'tests.slow': 'true', + 'tests.verbose': 'false', + 'tests.filterstacks': 'true', + 'tests.asserts': 'true', + 'tests.iters': null, + 'tests.filter': null, + 'tests.linedocsfile': 'europarl.lines.txt.gz', + 'tests.cleanthreads.sysprop': 'perMethod' + ].each { propName, defValue -> + def value = propertyOrDefault(propName, defValue) + if (value != null) { + systemProperty propName, value + } + } + } +} + diff --git a/gradle/testing/slowest-tests-at-end.gradle b/gradle/testing/slowest-tests-at-end.gradle new file mode 100644 index 00000000000..2e339173dc6 --- /dev/null +++ b/gradle/testing/slowest-tests-at-end.gradle @@ -0,0 +1,31 @@ +// Add test duration summary at the end of the build. + +def allTests = [] + +allprojects { + tasks.withType(Test) { task -> + afterTest { desc, result -> + def duration = (result.getEndTime() - result.getStartTime()) + + allTests << [ + name : "${desc.className.replaceAll('.+\\.', "")}.${desc.name} (${project.name})", + duration: duration + ] + } + } +} + +gradle.buildFinished { + if (allTests) { + def slowest = allTests + .sort { a, b -> b.duration.compareTo(a.duration) } + .take(10) + .findAll { e -> e.duration >= 500 } + .collect { e -> String.format(Locale.ROOT, "%5.2fs %s", e.duration / 1000d, e.name) } + + if (slowest) { + logger.lifecycle("The slowest tests (exceeding 500 ms) during this run:\n " + + slowest.join("\n ")) + } + } +} diff --git a/gradle/travis.gradle b/gradle/travis.gradle new file mode 100644 index 00000000000..45d3bb23ebe --- /dev/null +++ b/gradle/travis.gradle @@ -0,0 +1,21 @@ +// Emit more periodic info for travis builds (otherwise they timeout due to +// no input on the console). + +import org.gradle.api.tasks.testing.logging.* + +if (hasProperty("travis")) { + allprojects { + tasks.withType(Test) { task -> + maxParallelForks = 2 + + afterSuite { desc, result -> + if (desc.className) { + def tc = result.testCount + def tcs = (tc == 1 ? 'test' : 'tests') + + logger.lifecycle("Completed: ${desc.className} (${tc} ${tcs})") + } + } + } + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..29953ea141f55e3b8fc691d31b5ca8816d89fa87 GIT binary patch literal 56177 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 i;x|p)^~-yfPOPa3(|vBayXKz \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000000..e95643d6a2c --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/help/ant.txt b/help/ant.txt new file mode 100644 index 00000000000..b201c7ec26c --- /dev/null +++ b/help/ant.txt @@ -0,0 +1,49 @@ +Gradle for Ant users +==================== + +This shows some common ant targets and their equivalent Gradle commands. +Examples below assume cwd is at the top of the checkout (gradlew +script available from ./). Quoted [string] gives a better or more +conventional and commonly used task alternative. + +Gradle tasks apply to all modules that contain a given task name. Use +"-p" switch with a directory or a colon-notation to specify a particular +task or module. For example these two are equivalent: + +gradlew -p lucene/core check +gradlew :lucene:core:check + +List of common dev task equivalents +----------------------------------- + +ant clean => gradlew clean +ant jar => gradlew jar [better: gradlew assemble] + +ant compile => gradlew classes [better: gradlew assemble] + gradlew testClasses [better: gradlew assemble] + +ant validate => gradlew check +ant test => gradlew test + +ant jar-checksums => TODO +ant clean-jars => NO REPLACEMENT + +ant precommit => gradlew check -x test + +ant get-maven-poms => gradlew mavenLocal + +Solr-specific targets +--------------------- + +Assemble Solr distribution at solr/packaging/build/... + +ant create-package => gradlew -p solr/packaging assemble + +"Resolve" libraries by copying them to lib/ and other source +locations. This task should *not* be used anymore. It is added +for backward compatibility with ant (and for debugging) +but it mixes sources with output locations and this workflow +should be discouraged. Instead run assemble on packaging (above). + +ant resolve => gradlew -p solr resolve + diff --git a/help/tests.txt b/help/tests.txt new file mode 100644 index 00000000000..6f5938a72d3 --- /dev/null +++ b/help/tests.txt @@ -0,0 +1,83 @@ +Testing +======= + +Examples below assume cwd at the gradlew script in the top directory of +the project's checkout. + + +Generic test/ checkup commands +------------------------------ + +Run all unit tests: + +gradlew test + +Run all verification tasks, including tests: + +gradlew check + +Run all verification tasks, excluding tests (-x is gradle's generic task +exclusion mechanism): + +gradlew check -x test + +Run verification for a selected module only: + +gradlew :lucene:core:check # By full gradle project path +gradlew -p lucene/core check # By folder designation + task + + +Randomization +------------- + +Run tests with the given starting seed: + +gradlew :lucene:misc:test -Ptests.seed=DEADBEEF + + +Filtering +--------- + +Run tests of lucene-core module: + +gradlew -p lucene/core test + +Run a single test case (from a single module). Uses gradle's built-in filtering +(https://docs.gradle.org/current/userguide/java_testing.html#test_filtering): + +gradlew -p lucene/core test --tests TestDemo + +Run all tests in a package: + +gradlew -p lucene/core test --tests "org.apache.lucene.document.*" + +Run all test classes/ methods that match this pattern: + +gradlew -p lucene/core test --tests "*testFeatureMissing*" + + +Test groups +----------- + +Tests can be filtered by an annotation they're marked with. +Some test group annotations include: @AwaitsFix, @Nightly, @Slow + +This uses filtering infrastructure on the *runner* (randomizedtesting), +not gradle's built-in mechanisms (but it can be combined with "--tests"). +For example, run all lucene-core tests annotated as @Slow: + +gradlew -p lucene/core test -Ptests.filter=@Slow + +Test group filters can be combined into Boolean expressions: + +gradlew -p lucene/core test "default and not(@awaitsfix or @slow)" + + +Reiteration ("beasting") +------------------------ + +Multiply each test case N times (this works by repeating the same test +within the same JVM; it also works in IDEs): + +gradlew -p lucene/core test --tests TestDemo -Ptests.iters=5 + diff --git a/help/workflow.txt b/help/workflow.txt new file mode 100644 index 00000000000..f929a52168c --- /dev/null +++ b/help/workflow.txt @@ -0,0 +1,33 @@ +Typical workflow and tasks +========================== + +This shows some typical workflow gradle commands. + +Run tests on a module: +gradlew -p lucene/core test + +Run test of a single-class (run "gradlew :helpTests" for more): +gradlew -p lucene/core test --tests "*Demo*" + +Run all tests and validation checks on a module: +gradlew -p lucene/core check + +Run all tests and validation checks on everything: +gradlew check + +Run all validation checks but skip all tests: +gradlew check -x test + +Assemble a single module's JAR (here for lucene-core): +gradlew -p lucene/core assemble +ls lucene/core/build/libs + +Create all distributable packages, POMs, etc. and create a +local maven repository for inspection: +gradlew mavenLocal +ls -R build/maven-local/ + +Put together Solr distribution: +gradlew -p solr/packaging assemble +ls solr/packaging/build/solr-* + diff --git a/lucene/analysis/common/build.gradle b/lucene/analysis/common/build.gradle new file mode 100644 index 00000000000..2c68c0dddeb --- /dev/null +++ b/lucene/analysis/common/build.gradle @@ -0,0 +1,7 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + testImplementation project(':lucene:test-framework') +} + diff --git a/lucene/analysis/icu/build.gradle b/lucene/analysis/icu/build.gradle new file mode 100644 index 00000000000..d114f529e96 --- /dev/null +++ b/lucene/analysis/icu/build.gradle @@ -0,0 +1,10 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + + api 'com.ibm.icu:icu4j' + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/analysis/kuromoji/build.gradle b/lucene/analysis/kuromoji/build.gradle new file mode 100644 index 00000000000..1e0a9e3bb2b --- /dev/null +++ b/lucene/analysis/kuromoji/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/analysis/morfologik/build.gradle b/lucene/analysis/morfologik/build.gradle new file mode 100644 index 00000000000..ddbef7a8354 --- /dev/null +++ b/lucene/analysis/morfologik/build.gradle @@ -0,0 +1,13 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + + api 'org.carrot2:morfologik-stemming' + + implementation 'org.carrot2:morfologik-polish' + implementation 'ua.net.nlp:morfologik-ukrainian-search' + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/analysis/nori/build.gradle b/lucene/analysis/nori/build.gradle new file mode 100644 index 00000000000..f31a53e398d --- /dev/null +++ b/lucene/analysis/nori/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/analysis/opennlp/build.gradle b/lucene/analysis/opennlp/build.gradle new file mode 100644 index 00000000000..65e45ca745b --- /dev/null +++ b/lucene/analysis/opennlp/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + api 'org.apache.opennlp:opennlp-tools' + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/analysis/phonetic/build.gradle b/lucene/analysis/phonetic/build.gradle new file mode 100644 index 00000000000..d0d08bde635 --- /dev/null +++ b/lucene/analysis/phonetic/build.gradle @@ -0,0 +1,11 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + + implementation 'commons-codec:commons-codec' + + testImplementation project(':lucene:test-framework') +} + diff --git a/lucene/analysis/smartcn/build.gradle b/lucene/analysis/smartcn/build.gradle new file mode 100644 index 00000000000..d4d34df3b5d --- /dev/null +++ b/lucene/analysis/smartcn/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/analysis/stempel/build.gradle b/lucene/analysis/stempel/build.gradle new file mode 100644 index 00000000000..1e0a9e3bb2b --- /dev/null +++ b/lucene/analysis/stempel/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/backward-codecs/build.gradle b/lucene/backward-codecs/build.gradle new file mode 100644 index 00000000000..b92dea07729 --- /dev/null +++ b/lucene/backward-codecs/build.gradle @@ -0,0 +1,7 @@ + +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/benchmark/build.gradle b/lucene/benchmark/build.gradle new file mode 100644 index 00000000000..32daeb7f3a8 --- /dev/null +++ b/lucene/benchmark/build.gradle @@ -0,0 +1,22 @@ + +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + implementation project(':lucene:analysis:common') + implementation project(':lucene:facet') + implementation project(':lucene:highlighter') + implementation project(':lucene:queries') + implementation project(':lucene:spatial-extras') + implementation project(':lucene:queryparser') + + implementation "org.apache.commons:commons-compress" + implementation "com.ibm.icu:icu4j" + implementation "org.locationtech.spatial4j:spatial4j" + implementation("net.sourceforge.nekohtml:nekohtml", { + exclude module: "xml-apis" + }) + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/build.gradle b/lucene/build.gradle new file mode 100644 index 00000000000..26082a21ac6 --- /dev/null +++ b/lucene/build.gradle @@ -0,0 +1,3 @@ +subprojects { + group "org.apache.lucene" +} \ No newline at end of file diff --git a/lucene/classification/build.gradle b/lucene/classification/build.gradle new file mode 100644 index 00000000000..835cd330020 --- /dev/null +++ b/lucene/classification/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + implementation project(':lucene:queries') + implementation project(':lucene:grouping') + + testImplementation project(':lucene:test-framework') + testImplementation project(':lucene:analysis:common') + testImplementation project(':lucene:codecs') +} diff --git a/lucene/codecs/build.gradle b/lucene/codecs/build.gradle new file mode 100644 index 00000000000..50a833a2a49 --- /dev/null +++ b/lucene/codecs/build.gradle @@ -0,0 +1,6 @@ +apply plugin: 'java-library' + +dependencies { + implementation project(':lucene:core') + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/core/build.gradle b/lucene/core/build.gradle new file mode 100644 index 00000000000..8be3b6eacb5 --- /dev/null +++ b/lucene/core/build.gradle @@ -0,0 +1,7 @@ + +apply plugin: 'java-library' + +dependencies { + testImplementation project(':lucene:codecs') + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/demo/build.gradle b/lucene/demo/build.gradle new file mode 100644 index 00000000000..015f4c1dbac --- /dev/null +++ b/lucene/demo/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java-library' + +dependencies { + implementation project(':lucene:core') + implementation project(':lucene:facet') + implementation project(':lucene:queries') + implementation project(':lucene:analysis:common') + implementation project(':lucene:queryparser') + implementation project(':lucene:expressions') + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/expressions/build.gradle b/lucene/expressions/build.gradle new file mode 100644 index 00000000000..9222bf0dc2b --- /dev/null +++ b/lucene/expressions/build.gradle @@ -0,0 +1,20 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + implementation project(':lucene:codecs') + + implementation 'org.antlr:antlr4-runtime' + + // It is awkward that we force-omit the intermediate dependency here... + // The dependency chain is: + // asm-commons -> asm-tree -> asm + // Should we really go through these hoops? + implementation 'org.ow2.asm:asm' + implementation('org.ow2.asm:asm-commons', { + exclude group: "org.ow2.asm", module: "asm-tree" + }) + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/facet/build.gradle b/lucene/facet/build.gradle new file mode 100644 index 00000000000..246371e1015 --- /dev/null +++ b/lucene/facet/build.gradle @@ -0,0 +1,12 @@ + +apply plugin: 'java-library' + + +dependencies { + api project(':lucene:core') + + implementation 'com.carrotsearch:hppc' + + testImplementation project(':lucene:test-framework') + testImplementation project(':lucene:queries') +} diff --git a/lucene/grouping/build.gradle b/lucene/grouping/build.gradle new file mode 100644 index 00000000000..ab0e8914773 --- /dev/null +++ b/lucene/grouping/build.gradle @@ -0,0 +1,10 @@ + +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + implementation project(':lucene:queries') + + testImplementation project(':lucene:test-framework') +} \ No newline at end of file diff --git a/lucene/highlighter/build.gradle b/lucene/highlighter/build.gradle new file mode 100644 index 00000000000..c46636d56c1 --- /dev/null +++ b/lucene/highlighter/build.gradle @@ -0,0 +1,12 @@ + +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + implementation project(':lucene:queries') + implementation project(':lucene:memory') + + testImplementation project(':lucene:test-framework') + testImplementation project(':lucene:analysis:common') +} diff --git a/lucene/join/build.gradle b/lucene/join/build.gradle new file mode 100644 index 00000000000..fa8aca9af6d --- /dev/null +++ b/lucene/join/build.gradle @@ -0,0 +1,6 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + testImplementation project(':lucene:test-framework') +} \ No newline at end of file diff --git a/lucene/luke/build.gradle b/lucene/luke/build.gradle new file mode 100644 index 00000000000..4e9fc424d71 --- /dev/null +++ b/lucene/luke/build.gradle @@ -0,0 +1,16 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + implementation project(':lucene:codecs') + implementation project(':lucene:backward-codecs') + implementation project(':lucene:analysis:common') + implementation project(':lucene:queries') + implementation project(':lucene:queryparser') + implementation project(':lucene:misc') + + implementation 'org.apache.logging.log4j:log4j-core' + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/memory/build.gradle b/lucene/memory/build.gradle new file mode 100644 index 00000000000..92b4c5b88ba --- /dev/null +++ b/lucene/memory/build.gradle @@ -0,0 +1,9 @@ + +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + testImplementation project(':lucene:test-framework') + testImplementation project(':lucene:queryparser') +} \ No newline at end of file diff --git a/lucene/misc/build.gradle b/lucene/misc/build.gradle new file mode 100644 index 00000000000..fa8aca9af6d --- /dev/null +++ b/lucene/misc/build.gradle @@ -0,0 +1,6 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + testImplementation project(':lucene:test-framework') +} \ No newline at end of file diff --git a/lucene/monitor/build.gradle b/lucene/monitor/build.gradle new file mode 100644 index 00000000000..fc9583acf2b --- /dev/null +++ b/lucene/monitor/build.gradle @@ -0,0 +1,11 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + implementation project(':lucene:memory') + implementation project(':lucene:analysis:common') + + testImplementation project(':lucene:queryparser') + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/queries/build.gradle b/lucene/queries/build.gradle new file mode 100644 index 00000000000..6212520dfc5 --- /dev/null +++ b/lucene/queries/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + testImplementation project(':lucene:test-framework') + testImplementation project(':lucene:expressions') +} \ No newline at end of file diff --git a/lucene/queryparser/build.gradle b/lucene/queryparser/build.gradle new file mode 100644 index 00000000000..1a562c43d41 --- /dev/null +++ b/lucene/queryparser/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:queries') + api project(':lucene:sandbox') + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/replicator/build.gradle b/lucene/replicator/build.gradle new file mode 100644 index 00000000000..f924533abb7 --- /dev/null +++ b/lucene/replicator/build.gradle @@ -0,0 +1,19 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + implementation project(':lucene:facet') + + implementation('org.apache.httpcomponents:httpclient', { + exclude group: "commons-codec", module: "commons-codec" + }) + + implementation 'org.eclipse.jetty:jetty-server' + implementation('org.eclipse.jetty:jetty-servlet', { + exclude group: "org.eclipse.jetty", module: "jetty-security" + }) + implementation 'org.eclipse.jetty:jetty-continuation' + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/sandbox/build.gradle b/lucene/sandbox/build.gradle new file mode 100644 index 00000000000..f59fd2c7690 --- /dev/null +++ b/lucene/sandbox/build.gradle @@ -0,0 +1,6 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/spatial-extras/build.gradle b/lucene/spatial-extras/build.gradle new file mode 100644 index 00000000000..444148f7d3c --- /dev/null +++ b/lucene/spatial-extras/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:spatial3d') + + api 'org.locationtech.spatial4j:spatial4j' + api 'io.sgr:s2-geometry-library-java' + + testImplementation project(':lucene:test-framework') + + testImplementation 'org.locationtech.jts:jts-core' + testImplementation 'org.locationtech.spatial4j:spatial4j::tests' +} diff --git a/lucene/spatial/build.gradle b/lucene/spatial/build.gradle new file mode 100644 index 00000000000..fa8aca9af6d --- /dev/null +++ b/lucene/spatial/build.gradle @@ -0,0 +1,6 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + testImplementation project(':lucene:test-framework') +} \ No newline at end of file diff --git a/lucene/spatial3d/build.gradle b/lucene/spatial3d/build.gradle new file mode 100644 index 00000000000..fa8aca9af6d --- /dev/null +++ b/lucene/spatial3d/build.gradle @@ -0,0 +1,6 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + testImplementation project(':lucene:test-framework') +} \ No newline at end of file diff --git a/lucene/suggest/build.gradle b/lucene/suggest/build.gradle new file mode 100644 index 00000000000..f31a53e398d --- /dev/null +++ b/lucene/suggest/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + + testImplementation project(':lucene:test-framework') +} diff --git a/lucene/test-framework/build.gradle b/lucene/test-framework/build.gradle new file mode 100644 index 00000000000..c0b7615bae2 --- /dev/null +++ b/lucene/test-framework/build.gradle @@ -0,0 +1,11 @@ +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + + api ("com.carrotsearch.randomizedtesting:randomizedtesting-runner") + api ('org.hamcrest:hamcrest-core') + api ("junit:junit") + + implementation project(':lucene:codecs') +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000000..a04620d168b --- /dev/null +++ b/settings.gradle @@ -0,0 +1,55 @@ + +include "lucene:analysis:common" +include "lucene:analysis:icu" +include "lucene:analysis:kuromoji" +include "lucene:analysis:morfologik" +include "lucene:analysis:nori" +include "lucene:analysis:opennlp" +include "lucene:analysis:phonetic" +include "lucene:analysis:smartcn" +include "lucene:analysis:stempel" +include "lucene:backward-codecs" +include "lucene:benchmark" +include "lucene:classification" +include "lucene:codecs" +include "lucene:core" +include "lucene:demo" +include "lucene:expressions" +include "lucene:facet" +include "lucene:grouping" +include "lucene:highlighter" +include "lucene:join" +include "lucene:luke" +include "lucene:memory" +include "lucene:misc" +include "lucene:monitor" +include "lucene:queries" +include "lucene:queryparser" +include "lucene:replicator" +include "lucene:sandbox" +include "lucene:spatial" +include "lucene:spatial-extras" +include "lucene:spatial3d" +include "lucene:suggest" +include "lucene:test-framework" + +include "solr:solrj" +include "solr:core" +include "solr:server" +include "solr:contrib:analysis-extras" +include "solr:contrib:dataimporthandler" +include "solr:contrib:dataimporthandler-extras" +include "solr:contrib:analytics" +include "solr:contrib:clustering" +include "solr:contrib:extraction" +include "solr:contrib:langid" +include "solr:contrib:jaegertracer-configurator" +include "solr:contrib:prometheus-exporter" +include "solr:contrib:velocity" +include "solr:contrib:ltr" +include "solr:webapp" +include "solr:test-framework" +include "solr:solr-ref-guide" +include "solr:example" + +include "solr:packaging" diff --git a/solr/build.gradle b/solr/build.gradle new file mode 100644 index 00000000000..e48b30f073d --- /dev/null +++ b/solr/build.gradle @@ -0,0 +1,3 @@ +subprojects { + group "org.apache.solr" +} \ No newline at end of file diff --git a/solr/contrib/analysis-extras/build.gradle b/solr/contrib/analysis-extras/build.gradle new file mode 100644 index 00000000000..8e6ab06c91d --- /dev/null +++ b/solr/contrib/analysis-extras/build.gradle @@ -0,0 +1,16 @@ + +apply plugin: 'java-library' + +dependencies { + api project(':solr:core') + + implementation project(':lucene:analysis:icu') + implementation project(':lucene:analysis:smartcn') + implementation project(':lucene:analysis:morfologik') + implementation project(':lucene:analysis:opennlp') + implementation project(':lucene:analysis:smartcn') + implementation project(':lucene:analysis:stempel') + + testImplementation project(':solr:test-framework') +} + diff --git a/solr/contrib/analytics/build.gradle b/solr/contrib/analytics/build.gradle new file mode 100644 index 00000000000..de21ff64b20 --- /dev/null +++ b/solr/contrib/analytics/build.gradle @@ -0,0 +1,6 @@ +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + testImplementation project(':solr:test-framework') +} diff --git a/solr/contrib/clustering/build.gradle b/solr/contrib/clustering/build.gradle new file mode 100644 index 00000000000..860a645e3e2 --- /dev/null +++ b/solr/contrib/clustering/build.gradle @@ -0,0 +1,12 @@ + +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + implementation project(':lucene:analysis:common') + implementation('org.carrot2:carrot2-mini', { + exclude group: "org.simpleframework", module: "simple-xml" + }) + + testImplementation project(':solr:test-framework') +} diff --git a/solr/contrib/dataimporthandler-extras/build.gradle b/solr/contrib/dataimporthandler-extras/build.gradle new file mode 100644 index 00000000000..bbf4c6918fc --- /dev/null +++ b/solr/contrib/dataimporthandler-extras/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + + implementation project(':solr:contrib:dataimporthandler') + implementation project(':solr:contrib:extraction') + + implementation ('javax.activation:activation') + implementation ('com.sun.mail:javax.mail') + implementation ('com.sun.mail:gimap') + + testImplementation project(':solr:test-framework') +} diff --git a/solr/contrib/dataimporthandler/build.gradle b/solr/contrib/dataimporthandler/build.gradle new file mode 100644 index 00000000000..d34b9dd05f8 --- /dev/null +++ b/solr/contrib/dataimporthandler/build.gradle @@ -0,0 +1,15 @@ + +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + + testImplementation project(':solr:test-framework') + + testImplementation('org.mockito:mockito-core', { + exclude group: "net.bytebuddy", module: "byte-buddy-agent" + }) + testImplementation ('org.hsqldb:hsqldb') + testImplementation ('org.apache.derby:derby') + testImplementation ('org.objenesis:objenesis') +} diff --git a/solr/contrib/extraction/build.gradle b/solr/contrib/extraction/build.gradle new file mode 100644 index 00000000000..7875efce660 --- /dev/null +++ b/solr/contrib/extraction/build.gradle @@ -0,0 +1,55 @@ +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + + // We export tika because other contribs depend on it (and its submodules) + // and we don't want to duplicate the dependency across different contribs. + api ('org.apache.tika:tika-core') { transitive = false } + api ('org.apache.tika:tika-parsers') { transitive = false } + + runtimeOnly ('org.apache.james:apache-mime4j-core') { transitive = false } + runtimeOnly ('org.apache.james:apache-mime4j-dom') { transitive = false } + runtimeOnly ('org.apache.tika:tika-java7') { transitive = false } + runtimeOnly ('org.apache.tika:tika-xmp') { transitive = false } + + implementation ('com.healthmarketscience.jackcess:jackcess') { transitive = false } + implementation ('com.healthmarketscience.jackcess:jackcess-encrypt') { transitive = false } + implementation ('org.gagravarr:vorbis-java-tika') { transitive = false } + implementation ('org.gagravarr:vorbis-java-core') { transitive = false } + implementation ('org.apache.commons:commons-compress') { transitive = false } + implementation ('org.apache.pdfbox:pdfbox') { transitive = false } + implementation ('org.apache.pdfbox:pdfbox-tools') { transitive = false } + implementation ('org.apache.pdfbox:fontbox') { transitive = false } + implementation ('org.apache.pdfbox:jempbox') { transitive = false } + implementation ('org.bouncycastle:bcmail-jdk15on') { transitive = false } + implementation ('org.bouncycastle:bcpkix-jdk15on') { transitive = false } + implementation ('org.bouncycastle:bcprov-jdk15on') { transitive = false } + implementation ('org.apache.poi:poi') { transitive = false } + implementation ('org.apache.poi:poi-scratchpad') { transitive = false } + implementation ('org.apache.poi:poi-ooxml') { transitive = false } + implementation ('org.apache.poi:poi-ooxml-schemas') { transitive = false } + implementation ('org.apache.xmlbeans:xmlbeans') { transitive = false } + implementation ('org.apache.commons:commons-collections4') { transitive = false } + implementation ('com.github.virtuald:curvesapi') { transitive = false } + implementation ('org.ccil.cowan.tagsoup:tagsoup') { transitive = false } + implementation ('com.googlecode.mp4parser:isoparser') { transitive = false } + implementation ('org.aspectj:aspectjrt') { transitive = false } + implementation ('com.drewnoakes:metadata-extractor') { transitive = false } + implementation ('de.l3s.boilerpipe:boilerpipe') { transitive = false } + implementation ('com.rometools:rome') { transitive = false } + implementation ('com.rometools:rome-utils') { transitive = false } + implementation ('org.jdom:jdom2') { transitive = false } + implementation ('com.googlecode.juniversalchardet:juniversalchardet') { transitive = false } + implementation ('org.tukaani:xz') { transitive = false } + implementation ('com.adobe.xmp:xmpcore') { transitive = false } + implementation ('com.pff:java-libpst') { transitive = false } + implementation ('org.tallison:jmatio') { transitive = false } + implementation ('com.epam:parso') { transitive = false } + implementation ('org.brotli:dec') { transitive = false } + implementation ('xerces:xercesImpl') { transitive = false } + + implementation ('com.ibm.icu:icu4j') + + testImplementation project(':solr:test-framework') +} diff --git a/solr/contrib/jaegertracer-configurator/build.gradle b/solr/contrib/jaegertracer-configurator/build.gradle new file mode 100644 index 00000000000..f8e13a8aab3 --- /dev/null +++ b/solr/contrib/jaegertracer-configurator/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + + implementation ("io.jaegertracing:jaeger-thrift", { + exclude group: "com.squareup.okhttp3", module: "okhttp" + exclude group: "com.google.code.gson", module: "gson" + }) + + testImplementation project(':solr:test-framework') +} \ No newline at end of file diff --git a/solr/contrib/langid/build.gradle b/solr/contrib/langid/build.gradle new file mode 100644 index 00000000000..6621dd0042f --- /dev/null +++ b/solr/contrib/langid/build.gradle @@ -0,0 +1,15 @@ + +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + + implementation ('org.apache.tika:tika-core') { transitive = false } + + implementation 'com.cybozu.labs:langdetect' + implementation 'net.arnx:jsonic' + implementation 'org.apache.opennlp:opennlp-tools' + + + testImplementation project(':solr:test-framework') +} diff --git a/solr/contrib/ltr/build.gradle b/solr/contrib/ltr/build.gradle new file mode 100644 index 00000000000..638ca381400 --- /dev/null +++ b/solr/contrib/ltr/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + implementation project(':lucene:analysis:common') + + testImplementation('org.mockito:mockito-core', { + exclude group: "net.bytebuddy", module: "byte-buddy-agent" + }) + testImplementation ('org.objenesis:objenesis') + testImplementation ('org.restlet.jee:org.restlet.ext.servlet') + + testImplementation project(':solr:test-framework') +} diff --git a/solr/contrib/prometheus-exporter/build.gradle b/solr/contrib/prometheus-exporter/build.gradle new file mode 100644 index 00000000000..e01b42b4ef8 --- /dev/null +++ b/solr/contrib/prometheus-exporter/build.gradle @@ -0,0 +1,28 @@ + +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + implementation project(':lucene:analysis:common') + + implementation ('io.prometheus:simpleclient') + implementation ('io.prometheus:simpleclient_common') + implementation ('io.prometheus:simpleclient_httpserver') + implementation ('net.thisptr:jackson-jq', { + exclude group: "org.jruby.joni", module: "joni" + }) + implementation ('net.sourceforge.argparse4j:argparse4j') + + testImplementation ('org.apache.httpcomponents:httpcore') + testImplementation ('org.eclipse.jetty:jetty-servlet') + + testImplementation project(':solr:test-framework') +} + +// Add two folders to default packaging. +assemblePackaging { + from(projectDir, { + include "bin/**" + include "conf/**" + }) +} \ No newline at end of file diff --git a/solr/contrib/velocity/build.gradle b/solr/contrib/velocity/build.gradle new file mode 100644 index 00000000000..2163614d33c --- /dev/null +++ b/solr/contrib/velocity/build.gradle @@ -0,0 +1,14 @@ + +apply plugin: 'java-library' + +dependencies { + implementation project(':solr:core') + + implementation('org.apache.velocity.tools:velocity-tools-view-jsp', { + exclude group: "commons-beanutils", module: "commons-beanutils" + exclude group: "org.apache.commons", module: "commons-digester3" + exclude group: "com.github.cliftonlabs", module: "json-simple" + }) + + testImplementation project(':solr:test-framework') +} diff --git a/solr/core/build.gradle b/solr/core/build.gradle new file mode 100644 index 00000000000..0f0a4d0fd1b --- /dev/null +++ b/solr/core/build.gradle @@ -0,0 +1,129 @@ + +apply plugin: 'java-library' + +dependencies { + api project(':lucene:core') + api project(':lucene:analysis:common') + api project(':lucene:analysis:kuromoji') + api project(':lucene:analysis:nori') + api project(':lucene:analysis:phonetic') + api project(':lucene:backward-codecs') + api project(':lucene:classification') + api project(':lucene:codecs') + api project(':lucene:expressions') + api project(':lucene:grouping') + api project(':lucene:highlighter') + api project(':lucene:join') + api project(':lucene:misc') + api project(':lucene:queries') + api project(':lucene:queryparser') + api project(':lucene:sandbox') + api project(':lucene:spatial-extras') + api project(':lucene:suggest') + + // Export these dependencies so that they're imported transitively by + // other modules. + api ('com.google.guava:guava', { + exclude group: "org.codehaus.mojo", module: "animal-sniffer-annotations" + exclude group: "com.google.j2objc", module: "j2objc-annotations" + exclude group: "com.google.errorprone", module: "error_prone_annotations" + exclude group: "org.checkerframework", module: "checker-qual" + exclude group: "com.google.code.findbugs", module: "jsr305" + }) + + api project(':solr:solrj') + api project(':solr:server') + + api 'org.apache.commons:commons-lang3' + api 'com.carrotsearch:hppc' + api 'com.fasterxml.jackson.core:jackson-databind' + api 'commons-cli:commons-cli' + api 'commons-codec:commons-codec' + api 'commons-collections:commons-collections' + + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-smile' + + implementation('com.github.ben-manes.caffeine:caffeine', { + exclude group: "org.checkerframework", module: "checker-qual" + exclude group: "com.google.errorprone", module: "error_prone_annotations" + }) + + implementation 'com.github.zafarkhaja:java-semver' + implementation 'com.google.re2j:re2j' + + implementation('com.jayway.jsonpath:json-path', { + exclude group: "net.minidev", module: "json-smart" + }) + + implementation 'com.tdunning:t-digest' + implementation 'commons-fileupload:commons-fileupload' + + implementation 'io.opentracing:opentracing-api' + implementation 'io.opentracing:opentracing-noop' + implementation 'io.opentracing:opentracing-util' + implementation 'org.apache.commons:commons-exec' + implementation 'org.apache.commons:commons-text' + implementation("org.apache.commons:commons-configuration2", { + exclude group: "commons-logging", module: "commons-logging" + }) + implementation 'org.apache.htrace:htrace-core4' + + implementation 'org.apache.logging.log4j:log4j-api' + implementation 'org.apache.logging.log4j:log4j-core' + implementation 'org.apache.logging.log4j:log4j-slf4j-impl' + + api 'org.bitbucket.b_c:jose4j' + implementation 'org.codehaus.janino:commons-compiler' + implementation 'org.codehaus.janino:janino' + + api 'org.restlet.jee:org.restlet' + implementation 'org.rrd4j:rrd4j' + implementation 'org.restlet.jee:org.restlet.ext.servlet' + + implementation ('org.apache.calcite.avatica:avatica-core') { transitive = false } + implementation ('org.apache.calcite:calcite-core') { transitive = false } + implementation ('org.apache.calcite:calcite-linq4j') { transitive = false } + implementation ('org.apache.curator:curator-client') { transitive = false } + implementation ('org.apache.curator:curator-framework') { transitive = false } + implementation ('org.apache.hadoop:hadoop-annotations') { transitive = false } + implementation ('org.apache.hadoop:hadoop-auth') { transitive = false } + implementation ('org.apache.hadoop:hadoop-common') { transitive = false } + implementation ('org.apache.hadoop:hadoop-hdfs-client') { transitive = false } + + implementation ('net.hydromatic:eigenbase-properties') { transitive = false } + + runtimeOnly ('org.apache.curator:curator-recipes') { transitive = false } + runtimeOnly ('org.apache.kerby:kerb-core') + runtimeOnly ('org.apache.kerby:kerb-util') + runtimeOnly ('org.apache.kerby:kerby-asn1') + runtimeOnly ('org.apache.kerby:kerby-pkix') + runtimeOnly ('com.google.protobuf:protobuf-java') + + testImplementation project(':lucene:analysis:icu') + testImplementation project(':solr:contrib:analysis-extras') + testImplementation project(':solr:test-framework') + + testImplementation ('org.apache.hadoop:hadoop-common::tests') { transitive = false } + testImplementation ('org.apache.hadoop:hadoop-hdfs') { transitive = false } + testImplementation ('org.apache.hadoop:hadoop-hdfs::tests') { transitive = false } + testImplementation ('org.apache.hadoop:hadoop-minikdc') { transitive = false } + + testImplementation ('org.apache.kerby:kerb-client') { transitive = false } + testImplementation ('org.apache.kerby:kerb-common') { transitive = false } + testImplementation ('org.apache.kerby:kerb-identity') { transitive = false } + testImplementation ('org.apache.kerby:kerb-server') { transitive = false } + testImplementation ('org.apache.kerby:kerb-simplekdc') { transitive = false } + testImplementation ('org.apache.kerby:kerb-admin') { transitive = false } + testImplementation ('org.apache.kerby:kerby-kdc') { transitive = false } + + testImplementation ('com.sun.jersey:jersey-servlet:1.19.4') { transitive = false } + + testImplementation 'com.google.protobuf:protobuf-java' + testImplementation 'commons-logging:commons-logging' + testImplementation('org.mockito:mockito-core', { + exclude group: "net.bytebuddy", module: "byte-buddy-agent" + }) + + testRuntimeOnly 'org.slf4j:log4j-over-slf4j' +} + diff --git a/solr/example/build.gradle b/solr/example/build.gradle new file mode 100644 index 00000000000..e1a53144226 --- /dev/null +++ b/solr/example/build.gradle @@ -0,0 +1,46 @@ + +// I am not convinced packaging of examples should be a separate project... Seems more logical to +// move it to just the packaging project (?). Let's leave it for now though. + +configurations { + packaging + postJar + dih +} + +dependencies { + postJar project(path: ":solr:core", configuration: "postJar") + dih 'org.hsqldb:hsqldb' + dih 'org.apache.derby:derby' +} + +ext { + packagingDir = file("${buildDir}/packaging") +} + +task assemblePackaging(type: Sync) { + from(projectDir, { + include "example-DIH/**" + include "exampledocs/**" + include "files/**" + include "films/**" + include "README.txt" + exclude "**/*.jar" + }) + + from(configurations.postJar, { + into "exampledocs/" + }) + + from(configurations.dih, { + into "example-DIH/solr/db/lib" + }) + + into packagingDir +} + +artifacts { + packaging packagingDir, { + builtBy assemblePackaging + } +} diff --git a/solr/packaging/build.gradle b/solr/packaging/build.gradle new file mode 100644 index 00000000000..57b1572bfd5 --- /dev/null +++ b/solr/packaging/build.gradle @@ -0,0 +1,95 @@ + +// This project puts together a "distribution", assembling dependencies from +// various other projects. + +plugins { + id 'base' +} + +ext { + distDir = file("$buildDir/solr-${version}") +} + +configurations { + distSolr { + transitive = false + } + distSolrj + contrib + example + server +} + +dependencies { + distSolrj project(":solr:solrj") + + [":solr:contrib:analysis-extras", + ":solr:contrib:analytics", + ":solr:contrib:extraction", + ":solr:contrib:clustering", + ":solr:contrib:dataimporthandler", + ":solr:contrib:dataimporthandler-extras", + ":solr:contrib:jaegertracer-configurator", + ":solr:contrib:langid", + ":solr:contrib:ltr", + ":solr:contrib:prometheus-exporter", + ":solr:contrib:velocity", + ].each { contribName -> + distSolr project(contribName) + contrib project(path: contribName, configuration: "packaging") + } + + distSolr project(":solr:core") + distSolr project(":solr:solrj") + distSolr project(":solr:test-framework") + + example project(path: ":solr:example", configuration: "packaging") + server project(path: ":solr:server", configuration: "packaging") +} + +task toDir(type: Sync) { + from(project(":solr").projectDir, { + include "bin/**" + include "licenses/**" + include "CHANGES.txt" + include "LICENSE.txt" + include "NOTICE.txt" + include "README.txt" + }) + + from(project(":lucene").projectDir, { + include "CHANGES.txt" + rename { file -> 'LUCENE_CHANGES.txt' } + }) + + from(configurations.contrib, { + into "contrib" + }) + + from(configurations.distSolr, { + into "dist" + }) + + from(configurations.distSolrj - configurations.distSolr, { + into "dist/solrj-lib" + }) + + from(configurations.example, { + into "example" + }) + + from(configurations.server, { + into "server" + }) + + // docs/ - TODO: this is assembled via XSLT... leaving out for now. + + into distDir + + doLast { + logger.lifecycle "Solr distribution assembled under: ${distDir}" + } +} + +assemble.dependsOn toDir + diff --git a/solr/server/build.gradle b/solr/server/build.gradle new file mode 100644 index 00000000000..fd0e880f297 --- /dev/null +++ b/solr/server/build.gradle @@ -0,0 +1,107 @@ +apply plugin: 'java-library' + +configurations { + api { + exclude group: "org.slf4j" + } + startJar + libExt + webapp + packaging +} + +dependencies { + api('org.eclipse.jetty:jetty-alpn-java-server', { + exclude group: "org.eclipse.jetty.alpn", module: "alpn-api" + }) + + api('io.dropwizard.metrics:metrics-core', { + exclude group: "com.rabbitmq", module: "amqp-client" + }) + api('io.dropwizard.metrics:metrics-graphite', { + exclude group: "com.rabbitmq", module: "amqp-client" + }) + api 'io.dropwizard.metrics:metrics-jetty9' + api 'io.dropwizard.metrics:metrics-jvm' + api 'io.dropwizard.metrics:metrics-jmx' + + api 'org.eclipse.jetty:jetty-continuation' + api 'org.eclipse.jetty:jetty-deploy' + api 'org.eclipse.jetty:jetty-http' + api 'org.eclipse.jetty:jetty-io' + api 'org.eclipse.jetty:jetty-jmx' + api 'org.eclipse.jetty:jetty-rewrite' + api 'org.eclipse.jetty:jetty-security' + api 'org.eclipse.jetty:jetty-server' + api 'org.eclipse.jetty:jetty-servlet' + api 'org.eclipse.jetty:jetty-servlets' + api 'org.eclipse.jetty:jetty-util' + api 'org.eclipse.jetty:jetty-webapp' + api 'org.eclipse.jetty:jetty-xml' + api 'org.eclipse.jetty:jetty-alpn-server' + + api 'org.eclipse.jetty.http2:http2-server' + api 'org.eclipse.jetty.http2:http2-common' + api 'org.eclipse.jetty.http2:http2-hpack' + + api 'javax.servlet:javax.servlet-api' + + libExt 'com.lmax:disruptor' + libExt 'org.slf4j:jcl-over-slf4j' + libExt 'org.slf4j:jul-to-slf4j' + libExt 'org.slf4j:slf4j-api' + libExt 'org.apache.logging.log4j:log4j-1.2-api' + libExt 'org.apache.logging.log4j:log4j-api' + libExt 'org.apache.logging.log4j:log4j-core' + libExt 'org.apache.logging.log4j:log4j-slf4j-impl' + libExt 'org.apache.logging.log4j:log4j-web' + + webapp project(path: ":solr:webapp", configuration: "war") + + startJar('org.eclipse.jetty:jetty-start::shaded', { + transitive false + }) +} + +ext { + packagingDir = file("${buildDir}/packaging") +} + +task assemblePackaging(type: Sync) { + from(projectDir, { + include "contexts/**" + include "etc/**" + include "modules/**" + include "resources/**" + include "scripts/**" + include "solr/**" + include "README.txt" + }) + + from(configurations.compileClasspath, { + into "lib/" + }) + + from(configurations.libExt, { + into "lib/ext" + }) + + from { project.configurations.startJar.singleFile } { + rename { file -> 'start.jar' } + } + + dependsOn configurations.webapp + from( { zipTree(configurations.webapp.asPath) }, { + into "solr-webapp/webapp" + }) + + into packagingDir +} + +artifacts { + packaging packagingDir, { + builtBy assemblePackaging + } +} + +assemble.dependsOn assemblePackaging diff --git a/solr/solr-ref-guide/build.gradle b/solr/solr-ref-guide/build.gradle new file mode 100644 index 00000000000..74f3d07f24a --- /dev/null +++ b/solr/solr-ref-guide/build.gradle @@ -0,0 +1,328 @@ +// TODO 1: the separation of sources between tools and refGuide is awkward; it'd be +// better to separate the refGuideTools as a plain Java module and then depend on +// it as a project dependency. This would enable this module to *not* be a java module at all +// and inherit from base, adding just refGuide-related tasks. +// OR (better) one could rewrite those tools in Groovy (or Kotlin) and use them directly, without +// an additional compilation phase. + +// TODO 2: property expansion via ant properties is awkward in gradle. We can do cleaner than going +// through ant -- we could use gradle's expand when copying or at least use some more humane +// property names. + +// TODO 3: task names currently roughly correspond to ant tasks. Simpler aliases (such as 'html') +// would be much clearer. + +// TODO 4: currently buildscript dependencies are hardcoded (asciidoctor) because they can't be resolved +// using Palantir's plugin. This is another reason to switch to gradle-based tools -- then +// only the build script dependencies would be needed and asciidoctorj would be removed from version +// properties entirely (it is only used locally in this build file). + +import java.time.* +import java.time.format.* +import java.nio.file.* +import org.asciidoctor.* + +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath "org.asciidoctor:asciidoctorj:1.6.2" + } +} + +plugins { + id 'java' + id 'com.github.jruby-gradle.base' version '1.6.0' +} + +configurations { + depVer + refGuide +} + +dependencies { + // Dependencies to compile internal tools. + implementation('org.asciidoctor:asciidoctorj') + implementation('com.vaadin.external.google:android-json') + implementation('org.jsoup:jsoup') + implementation('org.slf4j:jcl-over-slf4j') + implementation('org.slf4j:slf4j-simple') + implementation('org.apache.logging.log4j:log4j-core') + implementation('com.google.guava:guava') + implementation('commons-codec:commons-codec') + + // Dependencies referenced in the guide. + depVer('commons-codec:commons-codec') + depVer('io.dropwizard.metrics:metrics-core') + depVer('org.apache.logging.log4j:log4j-core') + depVer('org.apache.opennlp:opennlp-tools') + depVer('org.apache.tika:tika-core') + depVer('org.apache.velocity.tools:velocity-tools-generic') + depVer('org.apache.zookeeper:zookeeper') + + // jekyll dependencies + jrubyExec 'rubygems:jekyll:3.5.2' + jrubyExec 'rubygems:jekyll-asciidoc:3.0.0' + + // don't know why we have to explicitly add these deps but it doesn't resolve them + // automatically. + jrubyExec 'rubygems:tilt:2.0.10' + jrubyExec 'rubygems:slim:4.0.1' + jrubyExec 'rubygems:concurrent-ruby:1.0.5' +} + +sourceSets { + refGuide { + java { + srcDirs = ['src'] + } + } + + main { + java { + srcDirs = ['tools'] + exclude "**/CustomizedAsciidoctorAntTask.java" + exclude "**/asciidoctor-antlib.xml" + } + } +} + +ext { + buildContentDir = file("${buildDir}/content") + mainPage = "index" + + solrDocsVersion = "${version}".replaceAll(/^(\d+\.\d+)(|\..*)$/, "\$1") + solrDocsVersionPath = "${solrDocsVersion}".replaceAll(/^(\d+)\.(\d+)$/, "\$1_\$2_0") + + if (!project.hasProperty("solrGuideVersion")) { + solrGuideVersion = "${solrDocsVersion}-DRAFT" + } + + solrRootPath = '../../../../solr/' + solrGuideDraftStatus = solrGuideVersion.matches(/^\d+\.\d+(|\.\d+)$/) ? "" : "DRAFT" + solrGuideVersionPath = solrGuideVersion.replaceAll(/^(\d+)\.(\d+)(-DRAFT)?.*/, "\$1_\$2\$3") + + javadocLink = "https://docs.oracle.com/en/java/javase/11/docs/api/" + + if (project.hasProperty("local.javadocs")) { + htmlSolrJavadocs = "link:../../docs/" + htmlLuceneJavadocs = "link:../../../../lucene/build/docs/" + } else { + htmlSolrJavadocs = "https://lucene.apache.org/solr/${solrDocsVersionPath}/" + htmlLuceneJavadocs = "https://lucene.apache.org/core/${solrDocsVersionPath}/" + } + + bareBonesDir = file("${buildDir}/bare-bones-html") + + def tstamp = ZonedDateTime.now() + buildDate = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(tstamp) + buildTime = DateTimeFormatter.ofPattern("HH:mm:ss").format(tstamp) + buildYear = DateTimeFormatter.ofPattern("yyyy").format(tstamp) + + // Some additional version properties are lazily computed + // in setupProps (because they need to be computed after evalution is complete). + props = [ + "solr-root-path" : solrRootPath, + "solr-guide-draft-status": solrGuideDraftStatus, + "solr-guide-version" : solrGuideVersion, + "solr-guide-version-path": solrGuideVersionPath, + "solr-docs-version" : solrDocsVersion, + "javadoc.link" : javadocLink, + "java-javadocs" : javadocLink, + "solr-javadocs" : htmlSolrJavadocs, + "html-solr-javadocs" : htmlSolrJavadocs, + "lucene-javadocs" : htmlLuceneJavadocs, + "html-lucene-javadocs" : htmlLuceneJavadocs, + "build-date" : buildDate, + "DSTAMP" : buildDate, + "build-year" : buildYear, + "current.year" : buildYear + ] + + asciiDocAttrs = [ + 'common': [ + 'attribute-missing' : 'warn', + 'section-toc' : '', + 'icons' : 'font', + 'icon-set' : 'fa', + 'figure-caption!' : '', + 'idprefix' : '', + 'idseparator' : '-', + 'source-highlighter': 'coderay', + 'solr-root-path' : solrRootPath, + ], + 'html' : [ + 'imagesdir': buildContentDir.toString() + ] + ] +} + +// Tasks modeled after ant file until we have a working build. + +task setupProps { + doFirst { + // These properties have to be resolved after configuration phase (palantir's constraint) + // so we can't use them as input for caches. + [ + ["ivyversions./commons-codec/commons-codec", "commons-codec", "commons-codec"], + ["ivyversions.io.dropwizard.metrics.version", "io.dropwizard.metrics", "metrics-core"], + ["ivyversions.org.apache.logging.log4j.version", "org.apache.logging.log4j", "log4j-core"], + ["ivyversions./org.apache.opennlp/opennlp-tools", "org.apache.opennlp", "opennlp-tools"], + ["ivyversions.org.apache.tika.version", "org.apache.tika", "tika-core"], + ["ivyversions.org.apache.velocity.tools.version", "org.apache.velocity.tools", "velocity-tools-generic"], + ["ivyversions./org.apache.zookeeper/zookeeper", "org.apache.zookeeper", "zookeeper"], + + ["ivy-zookeeper-version", "org.apache.zookeeper", "zookeeper"], + ["ivy-log4j-version", "org.apache.logging.log4j", "log4j-core"], + ["ivy-tika-version", "org.apache.tika", "tika-core"], + ["ivy-opennlp-version", "org.apache.opennlp", "opennlp-tools"], + ["ivy-commons-codec-version", "commons-codec", "commons-codec"], + ["ivy-velocity-tools-version", "org.apache.velocity.tools", "velocity-tools-generic"], + ["ivy-dropwizard-version", "io.dropwizard.metrics", "metrics-core"] + ].each { antProp, depGroup, depId -> + props[antProp] = getVersion(depGroup, depId, configurations.depVer) + } + + // Emit info about properties for clarity. + logger.warn("Building ref guide with:\n" + props.collect({ k, v -> " ${k} -> ${v}" }).join('\n')) + } +} + +task buildInit(type: Sync) { + dependsOn setupProps + + def dummyAntProject = new org.apache.tools.ant.Project() + + // If replaceable properties change, we have to rerun. + inputs.properties props + + from(file("src"), { + exclude '**/*.template' + }) + + from(file("src"), { + include '**/*.template' + rename '(.+)\\.template', '$1' + filteringCharset = 'UTF-8' + filter(org.apache.tools.ant.filters.ExpandProperties, project: dummyAntProject) + }) + + doFirst { + props.each { k, v -> + dummyAntProject.setProperty(k, v) + } + } + + into buildContentDir +} + +task buildNavDataFiles(type: JavaExec) { + dependsOn buildInit, classes + classpath = sourceSets.main.runtimeClasspath + + main = 'BuildNavDataFiles' + workingDir = buildContentDir + + args([ + "${buildContentDir}", + "${mainPage}" + ]) + + doFirst { + // Remove previously generated files first. + [ + "scrollnav.json", + "sidebar.json" + ].each { name -> + project.delete(file("${buildContentDir}/_data/${name}")) + } + } +} + +task bareBonesAsciiDoctor { + dependsOn buildNavDataFiles + + doLast { + // Regenerate fully. + project.delete(bareBonesDir) + bareBonesDir.mkdirs() + + // Convert each file separately so that folders are preserved. + Path source = buildContentDir.toPath().toAbsolutePath().normalize() + Path target = bareBonesDir.toPath().toAbsolutePath().normalize() + + Asciidoctor adoc = Asciidoctor.Factory.create() + fileTree(source, { + include "**/*.adoc" + exclude "**/_*" + }).each { file -> + Path relative = source.relativize(file.toPath()) + Path targetDir = target.resolve(relative).getParent() + + def opts = OptionsBuilder.options() + .backend('html5') + .docType("book") + .headerFooter(false) + .safe(SafeMode.UNSAFE) + .baseDir(source.toFile()) + .toDir(targetDir.toFile()) + .destinationDir(targetDir.toFile()) + .mkDirs(true) + .attributes(asciiDocAttrs.common + asciiDocAttrs.html + props) + + adoc.convertFile(file, opts) + } + } +} + +task bareBonesHtmlValidation(type: JavaExec) { + dependsOn bareBonesAsciiDoctor + description("Builds (w/o Jekyll) a very simple html version of the guide and runs link/anchor validation on it") + + classpath = sourceSets.main.runtimeClasspath + main = 'CheckLinksAndAnchors' + workingDir = buildContentDir + + args([ + "${bareBonesDir}", + "-bare-bones" + ]) + + if (project.hasProperty("local.javadocs")) { + args += "-check-all-relative-links" + } +} + +task buildSiteJekyll(type: com.github.jrubygradle.JRubyExec) { + dependsOn buildNavDataFiles + + inputs.dir buildContentDir + outputs.dir file("${buildDir}/html-site") + + script 'jekyll' + scriptArgs 'build' //, '--verbose' + workingDir buildContentDir +} + +task buildSite(type: JavaExec) { + group "Documentation" + description "Builds an HTML Site w/Jekyll and verifies the anchors+links are valid" + + dependsOn buildSiteJekyll + + classpath = sourceSets.main.runtimeClasspath + main = 'CheckLinksAndAnchors' + workingDir = buildContentDir + + args([ + file("${buildDir}/html-site"), + ]) + + if (project.hasProperty("local.javadocs")) { + args += "-check-all-relative-links" + } +} + +check.dependsOn bareBonesHtmlValidation diff --git a/solr/solrj/build.gradle b/solr/solrj/build.gradle new file mode 100644 index 00000000000..c77d2dcc7fb --- /dev/null +++ b/solr/solrj/build.gradle @@ -0,0 +1,55 @@ + +apply plugin: 'java-library' + +dependencies { + api 'org.slf4j:slf4j-api' + implementation 'org.slf4j:jcl-over-slf4j' + + api 'commons-io:commons-io' + api 'org.apache.commons:commons-math3' + + api 'org.eclipse.jetty.http2:http2-client' + api 'org.eclipse.jetty.http2:http2-http-client-transport' + api 'org.eclipse.jetty:jetty-util' + api 'org.eclipse.jetty:jetty-http' + api 'org.eclipse.jetty:jetty-alpn-java-client' + api 'org.eclipse.jetty:jetty-alpn-client' + + api('org.apache.httpcomponents:httpmime', { + exclude group: "commons-codec", module: "commons-codec" + exclude group: "commons-logging", module: "commons-logging" + }) + + api 'io.netty:netty-buffer' + api 'io.netty:netty-codec' + api 'io.netty:netty-common' + api 'io.netty:netty-handler' + api 'io.netty:netty-resolver' + api 'io.netty:netty-transport' + api 'io.netty:netty-transport-native-epoll' + api 'io.netty:netty-transport-native-unix-common' + + api('org.apache.zookeeper:zookeeper', { + exclude group: "org.apache.yetus", module: "audience-annotations" + exclude group: "io.netty", module: "netty-all" + exclude group: "log4j", module: "log4j" + exclude group: "org.slf4j", module: "slf4j-log4j12" + }) + + api('org.codehaus.woodstox:woodstox-core-asl', { + exclude group: "javax.xml.stream", module: "stax-api" + }) + + testImplementation project(':solr:test-framework') + testImplementation 'org.eclipse.jetty:jetty-webapp' + testImplementation 'org.eclipse.jetty:jetty-alpn-java-server' + testImplementation 'org.restlet.jee:org.restlet.ext.servlet' + testImplementation 'org.objenesis:objenesis' + testImplementation('org.mockito:mockito-core', { + exclude group: "net.bytebuddy", module: "byte-buddy-agent" + }) + testImplementation("org.apache.logging.log4j:log4j-slf4j-impl", { + exclude group: "org.apache.logging.log4j", module: "log4j-api" + }) + testImplementation "org.hsqldb:hsqldb" +} diff --git a/solr/test-framework/build.gradle b/solr/test-framework/build.gradle new file mode 100644 index 00000000000..6b6eca9b2c4 --- /dev/null +++ b/solr/test-framework/build.gradle @@ -0,0 +1,15 @@ + +apply plugin: 'java-library' + +dependencies { + api project(':solr:core') + api project(':solr:solrj') + api project(':lucene:test-framework') + api project(':lucene:analysis:common') + + api 'org.apache.logging.log4j:log4j-core' + api 'io.opentracing:opentracing-mock' + + implementation 'io.dropwizard.metrics:metrics-jetty9' + implementation 'com.lmax:disruptor' +} diff --git a/solr/webapp/build.gradle b/solr/webapp/build.gradle new file mode 100644 index 00000000000..f915c93c660 --- /dev/null +++ b/solr/webapp/build.gradle @@ -0,0 +1,37 @@ +plugins { + id 'java' + id 'war' +} + +configurations { + war {} +} + +dependencies { + implementation(project(":solr:core"), { + exclude module: "server" + + // Exclude additional deps from core and logging deps to sync up with ant. + // This is suspicious that we have to do it though. + exclude group: "org.apache.kerby", module: "kerby-config" + exclude group: "org.apache.kerby", module: "kerby-util" + exclude group: "org.apache.kerby", module: "kerb-crypto" + exclude group: "org.slf4j" + exclude group: "org.apache.logging.log4j" + }) +} + +war { + // Why are they in the source code at all if they're excluded from the distribution? + exclude "libs/angular-cookies.js" + exclude "libs/angular-route.js" + exclude "libs/angular-sanitize.js" + exclude "libs/angular-utf8-base.js" + exclude "libs/angular.js" + exclude "libs/chosen.jquery.js" +} + +// Expose 'war' archive as an artifact so that it can be packaged in the distribution. +artifacts { + war tasks.war +} \ No newline at end of file diff --git a/versions.lock b/versions.lock new file mode 100644 index 00000000000..d02ff02a2db --- /dev/null +++ b/versions.lock @@ -0,0 +1,230 @@ +# Run ./gradlew --write-locks to regenerate this file +com.adobe.xmp:xmpcore:5.1.3 (1 constraints: 0b050a36) +com.beust:jcommander:1.35 (1 constraints: b50c1901) +com.carrotsearch:hppc:0.8.1 (2 constraints: af0fd8a6) +com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.7.2 (1 constraints: 0d050c36) +com.carrotsearch.thirdparty:simple-xml-safe:2.7.1 (1 constraints: a60a82ca) +com.cybozu.labs:langdetect:1.1-20120112 (1 constraints: 5c066d5e) +com.drewnoakes:metadata-extractor:2.11.0 (1 constraints: 3605323b) +com.epam:parso:2.0.9 (1 constraints: 0d05fe35) +com.fasterxml.jackson.core:jackson-annotations:2.9.9 (2 constraints: 0a1d1637) +com.fasterxml.jackson.core:jackson-core:2.9.9 (3 constraints: 23350c6a) +com.fasterxml.jackson.core:jackson-databind:2.9.9.3 (3 constraints: 741a6389) +com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.9.9 (1 constraints: 16051936) +com.github.ben-manes.caffeine:caffeine:2.8.0 (1 constraints: 0c050d36) +com.github.jnr:jffi:1.2.18 (1 constraints: b20902ab) +com.github.jnr:jnr-constants:0.9.12 (4 constraints: ed2c9d5d) +com.github.jnr:jnr-enxio:0.19 (2 constraints: 2a167d08) +com.github.jnr:jnr-netdb:1.1.6 (1 constraints: 7e0952a1) +com.github.jnr:jnr-posix:3.0.49 (2 constraints: f0161b5b) +com.github.jnr:jnr-unixsocket:0.20 (1 constraints: 4a09d497) +com.github.virtuald:curvesapi:1.04 (1 constraints: d904f330) +com.github.zafarkhaja:java-semver:0.9.0 (1 constraints: 0b050636) +com.google.code.findbugs:jsr305:3.0.2 (1 constraints: 170aecb4) +com.google.errorprone:error_prone_annotations:2.1.3 (1 constraints: 180aebb4) +com.google.guava:guava:25.1-jre (1 constraints: 4a06b047) +com.google.j2objc:j2objc-annotations:1.1 (1 constraints: b609eba0) +com.google.protobuf:protobuf-java:3.7.1 (1 constraints: 0d051036) +com.google.re2j:re2j:1.2 (1 constraints: a7041c2c) +com.googlecode.juniversalchardet:juniversalchardet:1.0.3 (1 constraints: 0605f335) +com.googlecode.mp4parser:isoparser:1.1.22 (1 constraints: 38052d3b) +com.headius:backport9:1.1 (1 constraints: 1a098c8e) +com.headius:invokebinder:1.11 (1 constraints: 4b09d797) +com.headius:modulator:1.0 (1 constraints: 19098b8e) +com.headius:options:1.4 (1 constraints: 1d098f8e) +com.healthmarketscience.jackcess:jackcess:2.1.12 (1 constraints: 3805313b) +com.healthmarketscience.jackcess:jackcess-encrypt:2.1.4 (1 constraints: 0905fc35) +com.ibm.icu:icu4j:62.1 (1 constraints: dd040c31) +com.jayway.jsonpath:json-path:2.4.0 (1 constraints: 08050136) +com.jcraft:jzlib:1.1.3 (1 constraints: 7b094fa1) +com.lmax:disruptor:3.4.2 (1 constraints: 0b050836) +com.martiansoftware:nailgun-server:0.9.1 (1 constraints: 800960a1) +com.pff:java-libpst:0.8.1 (1 constraints: 0b050436) +com.rometools:rome:1.5.1 (1 constraints: 09050036) +com.rometools:rome-utils:1.5.1 (1 constraints: 09050036) +com.sun.mail:gimap:1.5.1 (1 constraints: 09050036) +com.sun.mail:javax.mail:1.5.1 (2 constraints: 830d2844) +com.tdunning:t-digest:3.1 (1 constraints: a804212c) +com.vaadin.external.google:android-json:0.0.20131108.vaadin1 (1 constraints: 34092a9e) +commons-cli:commons-cli:1.2 (1 constraints: a7041c2c) +commons-codec:commons-codec:1.11 (1 constraints: d704f230) +commons-collections:commons-collections:3.2.2 (1 constraints: 09050236) +commons-fileupload:commons-fileupload:1.3.3 (1 constraints: 0905fc35) +commons-io:commons-io:2.5 (2 constraints: be142680) +commons-logging:commons-logging:1.2 (2 constraints: c8149e7f) +de.l3s.boilerpipe:boilerpipe:1.1.0 (1 constraints: 0405f335) +io.dropwizard.metrics:metrics-core:4.0.5 (5 constraints: 204326bf) +io.dropwizard.metrics:metrics-graphite:4.0.5 (1 constraints: 0b050436) +io.dropwizard.metrics:metrics-jetty9:4.0.5 (1 constraints: 0b050436) +io.dropwizard.metrics:metrics-jmx:4.0.5 (1 constraints: 0b050436) +io.dropwizard.metrics:metrics-jvm:4.0.5 (1 constraints: 0b050436) +io.jaegertracing:jaeger-core:0.35.5 (1 constraints: 970d1034) +io.jaegertracing:jaeger-thrift:0.35.5 (1 constraints: 3f053f3b) +io.netty:netty-buffer:4.1.29.Final (4 constraints: 5b3421e8) +io.netty:netty-codec:4.1.29.Final (2 constraints: fc135782) +io.netty:netty-common:4.1.29.Final (5 constraints: 88482df2) +io.netty:netty-handler:4.1.29.Final (1 constraints: 5a076061) +io.netty:netty-resolver:4.1.29.Final (2 constraints: 0b15d4b5) +io.netty:netty-transport:4.1.29.Final (5 constraints: 7847682a) +io.netty:netty-transport-native-epoll:4.1.29.Final (1 constraints: 5a076061) +io.netty:netty-transport-native-unix-common:4.1.29.Final (2 constraints: 081ace05) +io.opentracing:opentracing-api:0.33.0 (5 constraints: 4c3c8052) +io.opentracing:opentracing-mock:0.33.0 (1 constraints: 3805343b) +io.opentracing:opentracing-noop:0.33.0 (3 constraints: 7c2142bd) +io.opentracing:opentracing-util:0.33.0 (3 constraints: f61f583b) +io.prometheus:simpleclient:0.2.0 (3 constraints: fe242db8) +io.prometheus:simpleclient_common:0.2.0 (2 constraints: e8159ecb) +io.prometheus:simpleclient_httpserver:0.2.0 (1 constraints: 0405f135) +io.sgr:s2-geometry-library-java:1.0.0 (1 constraints: 0305f035) +javax.activation:activation:1.1.1 (3 constraints: 1017445c) +javax.servlet:javax.servlet-api:3.1.0 (3 constraints: 75209943) +joda-time:joda-time:2.9.9 (1 constraints: 8a0972a1) +junit:junit:4.12 (2 constraints: 3e1e6104) +net.arnx:jsonic:1.2.7 (2 constraints: db10d4d1) +net.hydromatic:eigenbase-properties:1.1.5 (1 constraints: 0905f835) +net.sourceforge.argparse4j:argparse4j:0.8.1 (1 constraints: 0b050436) +net.sourceforge.nekohtml:nekohtml:1.9.17 (1 constraints: 4405503b) +net.thisptr:jackson-jq:0.0.8 (1 constraints: 0a05f335) +org.antlr:antlr4-runtime:4.5.1-1 (1 constraints: 6a05b240) +org.apache.calcite:calcite-core:1.18.0 (1 constraints: 3c05413b) +org.apache.calcite:calcite-linq4j:1.18.0 (1 constraints: 3c05413b) +org.apache.calcite.avatica:avatica-core:1.13.0 (1 constraints: 3705323b) +org.apache.commons:commons-collections4:4.2 (1 constraints: aa04252c) +org.apache.commons:commons-compress:1.18 (1 constraints: de04f930) +org.apache.commons:commons-configuration2:2.1.1 (1 constraints: 0605f935) +org.apache.commons:commons-exec:1.3 (1 constraints: a8041d2c) +org.apache.commons:commons-lang3:3.8.1 (7 constraints: 33673f05) +org.apache.commons:commons-math3:3.6.1 (1 constraints: 0c050d36) +org.apache.commons:commons-text:1.6 (1 constraints: ab04202c) +org.apache.curator:curator-client:2.13.0 (1 constraints: 3805383b) +org.apache.curator:curator-framework:2.13.0 (1 constraints: 3805383b) +org.apache.curator:curator-recipes:2.13.0 (1 constraints: 3805383b) +org.apache.hadoop:hadoop-annotations:3.2.0 (1 constraints: 07050036) +org.apache.hadoop:hadoop-auth:3.2.0 (1 constraints: 07050036) +org.apache.hadoop:hadoop-common:3.2.0 (1 constraints: 07050036) +org.apache.hadoop:hadoop-hdfs-client:3.2.0 (1 constraints: 07050036) +org.apache.htrace:htrace-core4:4.1.0-incubating (1 constraints: 58090086) +org.apache.httpcomponents:httpclient:4.5.6 (2 constraints: 6514987d) +org.apache.httpcomponents:httpcore:4.4.10 (2 constraints: 9015d5cd) +org.apache.httpcomponents:httpmime:4.5.6 (1 constraints: 11051436) +org.apache.james:apache-mime4j-core:0.8.2 (1 constraints: 0c050536) +org.apache.james:apache-mime4j-dom:0.8.2 (1 constraints: 0c050536) +org.apache.kerby:kerb-core:1.0.1 (3 constraints: f11c583a) +org.apache.kerby:kerb-crypto:1.0.1 (1 constraints: 860b05e6) +org.apache.kerby:kerb-util:1.0.1 (1 constraints: 0405f135) +org.apache.kerby:kerby-asn1:1.0.1 (2 constraints: 001155df) +org.apache.kerby:kerby-config:1.0.1 (1 constraints: 860b05e6) +org.apache.kerby:kerby-pkix:1.0.1 (2 constraints: 741065ca) +org.apache.kerby:kerby-util:1.0.1 (2 constraints: 6518bdb6) +org.apache.logging.log4j:log4j-api:2.11.2 (3 constraints: c124e473) +org.apache.logging.log4j:log4j-core:2.11.2 (2 constraints: 09164024) +org.apache.logging.log4j:log4j-slf4j-impl:2.11.2 (1 constraints: 3805343b) +org.apache.opennlp:opennlp-tools:1.9.1 (1 constraints: 0d050c36) +org.apache.pdfbox:fontbox:2.0.12 (1 constraints: 37052d3b) +org.apache.pdfbox:jempbox:1.8.16 (1 constraints: 42054b3b) +org.apache.pdfbox:pdfbox:2.0.12 (1 constraints: 37052d3b) +org.apache.pdfbox:pdfbox-tools:2.0.12 (1 constraints: 37052d3b) +org.apache.poi:poi:4.0.0 (1 constraints: 0605ff35) +org.apache.poi:poi-ooxml:4.0.0 (1 constraints: 0605ff35) +org.apache.poi:poi-ooxml-schemas:4.0.0 (1 constraints: 0605ff35) +org.apache.poi:poi-scratchpad:4.0.0 (1 constraints: 0605ff35) +org.apache.thrift:libthrift:0.12.0 (1 constraints: 8d0dfa33) +org.apache.tika:tika-core:1.19.1 (1 constraints: 3e05453b) +org.apache.tika:tika-java7:1.19.1 (1 constraints: 3e05453b) +org.apache.tika:tika-parsers:1.19.1 (1 constraints: 3e05453b) +org.apache.tika:tika-xmp:1.19.1 (1 constraints: 3e05453b) +org.apache.velocity:velocity-engine-core:2.0 (3 constraints: 973bcd79) +org.apache.velocity.tools:velocity-tools-generic:3.0 (1 constraints: 00136415) +org.apache.velocity.tools:velocity-tools-view:3.0 (1 constraints: 7a14126a) +org.apache.velocity.tools:velocity-tools-view-jsp:3.0 (1 constraints: a704202c) +org.apache.xmlbeans:xmlbeans:3.0.1 (1 constraints: 0605fb35) +org.apache.zookeeper:zookeeper:3.5.5 (1 constraints: 0f050e36) +org.apache.zookeeper:zookeeper-jute:3.5.5 (1 constraints: 8d0d3928) +org.asciidoctor:asciidoctorj:1.6.2 (1 constraints: 0b050436) +org.asciidoctor:asciidoctorj-api:1.6.2 (1 constraints: e30cfb0d) +org.aspectj:aspectjrt:1.8.0 (1 constraints: 0b050836) +org.bitbucket.b_c:jose4j:0.6.5 (1 constraints: 0d050236) +org.bouncycastle:bcmail-jdk15on:1.60 (1 constraints: db04fb30) +org.bouncycastle:bcpkix-jdk15on:1.60 (1 constraints: db04fb30) +org.bouncycastle:bcprov-jdk15on:1.60 (1 constraints: db04fb30) +org.brotli:dec:0.1.2 (1 constraints: 0505f035) +org.carrot2:carrot2-mini:3.16.2 (1 constraints: 3e05493b) +org.carrot2:morfologik-fsa:2.1.5 (1 constraints: d70d9836) +org.carrot2:morfologik-polish:2.1.5 (1 constraints: 0a05fd35) +org.carrot2:morfologik-stemming:2.1.5 (2 constraints: 0b12640c) +org.carrot2.attributes:attributes-binder:1.3.3 (1 constraints: a30a73ca) +org.carrot2.shaded:carrot2-guava:18.0 (2 constraints: b31b3b7b) +org.ccil.cowan.tagsoup:tagsoup:1.2.1 (1 constraints: 0605f735) +org.checkerframework:checker-qual:2.0.0 (1 constraints: 140ae5b4) +org.codehaus.janino:commons-compiler:3.0.9 (2 constraints: d910f7d1) +org.codehaus.janino:janino:3.0.9 (1 constraints: 0e050336) +org.codehaus.mojo:animal-sniffer-annotations:1.14 (1 constraints: ea09d5aa) +org.codehaus.woodstox:stax2-api:3.1.4 (2 constraints: 241635f1) +org.codehaus.woodstox:woodstox-core-asl:4.4.1 (1 constraints: 0b050c36) +org.eclipse.jetty:jetty-alpn-client:9.4.19.v20190610 (3 constraints: d12c8400) +org.eclipse.jetty:jetty-alpn-java-client:9.4.19.v20190610 (1 constraints: 8007517d) +org.eclipse.jetty:jetty-alpn-java-server:9.4.19.v20190610 (1 constraints: 8007517d) +org.eclipse.jetty:jetty-alpn-server:9.4.19.v20190610 (2 constraints: 231beedd) +org.eclipse.jetty:jetty-client:9.4.19.v20190610 (1 constraints: ce1741ae) +org.eclipse.jetty:jetty-continuation:9.4.19.v20190610 (2 constraints: 5d186efb) +org.eclipse.jetty:jetty-deploy:9.4.19.v20190610 (1 constraints: 8007517d) +org.eclipse.jetty:jetty-http:9.4.19.v20190610 (5 constraints: 8b497e4f) +org.eclipse.jetty:jetty-io:9.4.19.v20190610 (8 constraints: 0f7eb132) +org.eclipse.jetty:jetty-jmx:9.4.19.v20190610 (1 constraints: 8007517d) +org.eclipse.jetty:jetty-rewrite:9.4.19.v20190610 (1 constraints: 8007517d) +org.eclipse.jetty:jetty-security:9.4.19.v20190610 (2 constraints: ea172ade) +org.eclipse.jetty:jetty-server:9.4.19.v20190610 (6 constraints: bd5e38f5) +org.eclipse.jetty:jetty-servlet:9.4.19.v20190610 (2 constraints: 641789bf) +org.eclipse.jetty:jetty-servlets:9.4.19.v20190610 (1 constraints: 8007517d) +org.eclipse.jetty:jetty-util:9.4.19.v20190610 (7 constraints: 77648009) +org.eclipse.jetty:jetty-webapp:9.4.19.v20190610 (2 constraints: 72178fc0) +org.eclipse.jetty:jetty-xml:9.4.19.v20190610 (3 constraints: 56274720) +org.eclipse.jetty.alpn:alpn-api:1.1.3.v20160715 (1 constraints: 6513848a) +org.eclipse.jetty.http2:http2-client:9.4.19.v20190610 (2 constraints: 4d1ff83f) +org.eclipse.jetty.http2:http2-common:9.4.19.v20190610 (3 constraints: 242bc31f) +org.eclipse.jetty.http2:http2-hpack:9.4.19.v20190610 (2 constraints: 50198f5c) +org.eclipse.jetty.http2:http2-http-client-transport:9.4.19.v20190610 (1 constraints: 8007517d) +org.eclipse.jetty.http2:http2-server:9.4.19.v20190610 (1 constraints: 8007517d) +org.gagravarr:vorbis-java-core:0.8 (1 constraints: ac041f2c) +org.gagravarr:vorbis-java-tika:0.8 (1 constraints: ac041f2c) +org.hamcrest:hamcrest-core:1.3 (2 constraints: 730ad9bf) +org.jdom:jdom2:2.0.6 (1 constraints: 0a05fb35) +org.jruby:dirgra:0.3 (1 constraints: 1b098b8e) +org.jruby:jruby:9.2.6.0 (1 constraints: 490d7d28) +org.jruby:jruby-core:9.2.6.0 (1 constraints: 0f08b57d) +org.jruby:jruby-stdlib:9.2.6.0 (1 constraints: 0f08b57d) +org.jruby.jcodings:jcodings:1.0.41 (2 constraints: e3124361) +org.jruby.joni:joni:2.1.25 (1 constraints: b00903ab) +org.jsoup:jsoup:1.11.3 (1 constraints: 38052f3b) +org.locationtech.spatial4j:spatial4j:0.7 (1 constraints: ab041e2c) +org.ow2.asm:asm:5.1 (1 constraints: aa04272c) +org.ow2.asm:asm-commons:5.1 (1 constraints: aa04272c) +org.restlet.jee:org.restlet:2.3.0 (2 constraints: e3159ee6) +org.restlet.jee:org.restlet.ext.servlet:2.3.0 (1 constraints: 0705fe35) +org.rrd4j:rrd4j:3.5 (1 constraints: ac04252c) +org.slf4j:jcl-over-slf4j:1.7.25 (1 constraints: 4005473b) +org.slf4j:slf4j-api:1.7.25 (19 constraints: aaff8c21) +org.slf4j:slf4j-simple:1.7.25 (1 constraints: 4005473b) +org.tallison:jmatio:1.5 (1 constraints: aa041f2c) +org.tukaani:xz:1.8 (1 constraints: ad04222c) +ua.net.nlp:morfologik-ukrainian-search:3.9.0 (1 constraints: 0e051536) +xerces:xercesImpl:2.9.1 (2 constraints: f613d869) + +[Test dependencies] +com.sun.jersey:jersey-servlet:1.19.4 (1 constraints: 4105483b) +net.bytebuddy:byte-buddy:1.9.3 (2 constraints: 2510faaf) +org.apache.derby:derby:10.9.1.0 (1 constraints: 9b054946) +org.apache.hadoop:hadoop-hdfs:3.2.0 (1 constraints: 07050036) +org.apache.hadoop:hadoop-minikdc:3.2.0 (1 constraints: 07050036) +org.apache.kerby:kerb-admin:1.0.1 (1 constraints: 0405f135) +org.apache.kerby:kerb-client:1.0.1 (1 constraints: 0405f135) +org.apache.kerby:kerb-common:1.0.1 (1 constraints: 0405f135) +org.apache.kerby:kerb-identity:1.0.1 (1 constraints: 0405f135) +org.apache.kerby:kerb-server:1.0.1 (1 constraints: 0405f135) +org.apache.kerby:kerb-simplekdc:1.0.1 (1 constraints: 0405f135) +org.apache.kerby:kerby-kdc:1.0.1 (1 constraints: 0405f135) +org.hsqldb:hsqldb:2.4.0 (1 constraints: 08050136) +org.locationtech.jts:jts-core:1.15.0 (1 constraints: 3905383b) +org.mockito:mockito-core:2.23.4 (1 constraints: 3d05403b) +org.objenesis:objenesis:2.6 (2 constraints: 5f0ffb79) +org.slf4j:log4j-over-slf4j:1.7.25 (1 constraints: 4005473b) diff --git a/versions.props b/versions.props new file mode 100644 index 00000000000..bbca163336f --- /dev/null +++ b/versions.props @@ -0,0 +1,111 @@ +com.adobe.xmp:xmpcore=5.1.3 +com.carrotsearch.randomizedtesting:*=2.7.2 +com.carrotsearch:hppc=0.8.1 +com.cybozu.labs:langdetect=1.1-20120112 +com.drewnoakes:metadata-extractor=2.11.0 +com.epam:parso=2.0.9 +com.fasterxml.jackson*:*=2.9.9 +com.fasterxml.woodstox:*=4.4.1 +com.github.ben-manes.caffeine:caffeine=2.8.0 +com.github.virtuald:curvesapi=1.04 +com.github.zafarkhaja:java-semver=0.9.0 +com.google.guava:guava=25.1-jre +com.google.protobuf:protobuf-java=3.7.1 +com.google.re2j:re2j=1.2 +com.googlecode.juniversalchardet:juniversalchardet=1.0.3 +com.googlecode.mp4parser:isoparser=1.1.22 +com.healthmarketscience.jackcess:jackcess-encrypt=2.1.4 +com.healthmarketscience.jackcess:jackcess=2.1.12 +com.ibm.icu:icu4j=62.1 +com.jayway.jsonpath:json-path=2.4.0 +com.lmax:disruptor=3.4.2 +com.pff:java-libpst=0.8.1 +com.rometools:*=1.5.1 +com.sun.jersey:*=1.19 +com.sun.jersey:jersey-json=1.19.4 +com.sun.mail:*=1.5.1 +com.tdunning:t-digest=3.1 +com.vaadin.external.google:android-json=0.0.20131108.vaadin1 +commons-beanutils:commons-beanutils=1.9.3 +commons-cli:commons-cli=1.2 +commons-codec:commons-codec=1.11 +commons-collections:commons-collections=3.2.2 +commons-fileupload:commons-fileupload=1.3.3 +commons-io:commons-io=2.5 +commons-logging:commons-logging=1.1.3 +de.l3s.boilerpipe:boilerpipe=1.1.0 +info.ganglia.gmetric4j:gmetric4j=1.0.7 +io.dropwizard.metrics:*=4.0.5 +io.netty:*=4.1.29.Final +io.opentracing:*=0.33.0 +io.prometheus:*=0.2.0 +io.sgr:s2-geometry-library-java=1.0.0 +javax.activation:activation=1.1.1 +javax.servlet:javax.servlet-api=3.1.0 +junit:junit=4.12 +net.arnx:jsonic=1.2.7 +net.bytebuddy:byte-buddy=1.9.3 +net.hydromatic:eigenbase-properties=1.1.5 +net.sourceforge.argparse4j:argparse4j=0.8.1 +net.sourceforge.nekohtml:nekohtml=1.9.17 +net.thisptr:jackson-jq=0.0.8 +org.antlr:antlr4-runtime=4.5.1-1 +org.apache.calcite.avatica:avatica-core=1.13.0 +org.apache.calcite:*=1.18.0 +org.apache.commons:commons-collections4:4.2 +org.apache.commons:commons-compress=1.18 +org.apache.commons:commons-configuration2=2.1.1 +org.apache.commons:commons-exec=1.3 +org.apache.commons:commons-lang3=3.6 +org.apache.commons:commons-math3=3.6.1 +org.apache.commons:commons-text=1.6 +org.apache.curator:*=2.13.0 +org.apache.derby:derby=10.9.1.0 +org.apache.hadoop:*=3.2.0 +org.apache.htrace:htrace-core4=4.1.0-incubating +org.apache.httpcomponents:httpclient=4.5.6 +org.apache.httpcomponents:httpcore=4.4.10 +org.apache.httpcomponents:httpmime=4.5.6 +org.apache.james:*=0.8.2 +org.apache.kerby:*=1.0.1 +org.apache.logging.log4j:*=2.11.2 +org.apache.opennlp:opennlp-tools=1.9.1 +org.apache.pdfbox:*=2.0.12 +org.apache.pdfbox:jbig2-imageio=3.0.2 +org.apache.pdfbox:jempbox=1.8.16 +org.apache.poi:*=4.0.0 +org.apache.tika:*=1.19.1 +org.apache.velocity.tools:*=3.0 +org.apache.xmlbeans:xmlbeans=3.0.1 +org.apache.zookeeper:*=3.5.5 +org.asciidoctor:asciidoctorj=1.6.2 +org.aspectj:aspectjrt=1.8.0 +org.bitbucket.b_c:jose4j=0.6.5 +org.bouncycastle:*=1.60 +org.brotli:dec=0.1.2 +org.carrot2:carrot2-mini=3.16.2 +org.carrot2:morfologik-*=2.1.5 +org.ccil.cowan.tagsoup:tagsoup=1.2.1 +org.codehaus.janino:*=3.0.9 +org.codehaus.woodstox:stax2-api=3.1.4 +org.codehaus.woodstox:woodstox-core-asl=4.4.1 +org.eclipse.jetty.http2:*=9.4.19.v20190610 +org.eclipse.jetty:*=9.4.19.v20190610 +org.gagravarr:*=0.8 +org.hamcrest:*=1.3 +org.hsqldb:hsqldb=2.4.0 +org.jdom:jdom2=2.0.6 +org.jsoup:jsoup=1.11.3 +org.locationtech.jts:jts-core=1.15.0 +org.locationtech.spatial4j:*=0.7 +org.mockito:mockito-core=2.23.4 +org.objenesis:objenesis=2.6 +org.ow2.asm:*=5.1 +org.restlet.jee:*=2.3.0 +org.rrd4j:rrd4j=3.5 +org.slf4j:*=1.7.24 +org.tallison:jmatio=1.5 +org.tukaani:xz=1.8 +ua.net.nlp:morfologik-ukrainian-search=3.9.0 +xerces:xercesImpl=2.9.1 +io.jaegertracing:*=0.35.5 \ No newline at end of file