/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // generate javadocs by calling javadoc tool // see https://docs.oracle.com/en/java/javase/11/tools/javadoc.html // utility function to convert project path to document dir // e.g.: ':lucene:analysis:common' => 'analysis/common' def pathToDocdir = { path -> path.split(':').drop(2).join('/') } allprojects { plugins.withType(JavaPlugin) { // We disable the default javadoc task and have our own // javadoc rendering task below. The default javadoc task // will just invoke 'renderJavadoc' (to allow people to call // conventional task name). tasks.matching { it.name == "javadoc" }.all { enabled = false dependsOn "renderJavadoc" } task renderJavadoc { description "Generates Javadoc API documentation for the main source code. This directly invokes javadoc tool." group "documentation" ext { linksource = false linkJUnit = false linkLuceneProjects = [] linkSorlProjects = [] } dependsOn sourceSets.main.compileClasspath inputs.files { sourceSets.main.java.asFileTree } outputs.dir project.javadoc.destinationDir def libName = project.path.startsWith(":lucene") ? "Lucene" : "Solr" def title = "${libName} ${project.version} ${project.name} API".toString() // absolute urls for "-linkoffline" option def javaSEDocUrl = "https://docs.oracle.com/en/java/javase/11/docs/api/" def junitDocUrl = "https://junit.org/junit4/javadoc/4.12/" def luceneDocUrl = "https://lucene.apache.org/core/${project.version.replace(".", "_")}".toString() def solrDocUrl = "https://lucene.apache.org/solr/${project.version.replace(".", "_")}".toString() def javadocCmd = org.gradle.internal.jvm.Jvm.current().getJavadocExecutable() doFirst { def srcDirs = sourceSets.main.java.srcDirs.findAll { dir -> dir.exists() } def optionsFile = file("${getTemporaryDir()}/javadoc-options.txt") def opts = [] opts += [ "-overview ${file("src/java/overview.html").toString()}" ] opts += [ "-sourcepath ${srcDirs.join(' ')}" ] opts += [ "-subpackages ${project.path.startsWith(':lucene') ? 'org.apache.lucene' : 'org.apache.solr'}"] opts += [ "-d ${project.javadoc.destinationDir.toString()}" ] opts += [ "-protected" ] opts += [ "-encoding UTF-8" ] opts += [ "-charset UTF-8" ] opts += [ "-docencoding UTF-8" ] opts += [ "-noindex" ] opts += [ "-author" ] opts += [ "-version" ] if (linksource) { opts += [ "-linksource" ] } opts += [ "-use" ] opts += [ "-locale en_US" ] opts += [ "-windowtitle '${title}'" ] opts += [ "-doctitle '${title}'" ] if (!sourceSets.main.compileClasspath.isEmpty()) { opts += ["-classpath ${sourceSets.main.compileClasspath.asPath}" ] } opts += [ "-bottom 'Copyright © 2000-${buildYear} Apache Software Foundation. All Rights Reserved.'" ] opts += [ "-tag 'lucene.experimental:a:WARNING: This API is experimental and might change in incompatible ways in the next release.'" ] opts += [ "-tag 'lucene.internal:a:NOTE: This API is for internal purposes only and might change in incompatible ways in the next release.'" ] opts += [ "-tag 'lucene.spi:t:SPI Name (case-insensitive: if the name is 'htmlStrip', 'htmlstrip' can be used when looking up the service).'" ] // resolve links to JavaSE and JUnit API opts += [ "-linkoffline ${javaSEDocUrl} ${project(':lucene').file('tools/javadoc/java11/').toString()}" ] if (linkJUnit) { opts += [ "-linkoffline ${junitDocUrl} ${project(':lucene').file('tools/javadoc/junit').toURL()}" ] } // resolve inter-project links linkLuceneProjects.collect { path -> opts += [ "-linkoffline ${luceneDocUrl}/${pathToDocdir(path)} ${file(project(path).javadoc.destinationDir).toString()}" ] } linkSorlProjects.collect { path -> opts += [ "-linkoffline ${solrDocUrl}/${pathToDocdir(path)} ${file(project(path).javadoc.destinationDir).toString()}" ] } opts += [ "--release 11" ] opts += [ "-Xdoclint:all,-missing" ] // Temporary file that holds all javadoc options for the current task. optionsFile.write(opts.join("\n"), "UTF-8") def outputFile = file("${getTemporaryDir()}/javadoc-output.txt") def result outputFile.withOutputStream { output -> result = project.exec { executable javadocCmd standardOutput = output errorOutput = output args += [ "@${optionsFile}" ] // -J flags can't be passed via options file... (an error "javadoc: error - invalid flag: -J-Xmx512m" occurs.) args += [ "-J-Xmx512m" ] // force locale to be "en_US" (fix for: https://bugs.openjdk.java.net/browse/JDK-8222793) args += [ "-J-Duser.language=en -J-Duser.country=US" ] ignoreExitValue true } } if (result.getExitValue() != 0) { // Pipe the output to console. Intentionally skips any encoding conversion // and pumps raw bytes. System.out.write(outputFile.bytes) def cause try { result.rethrowFailure() } catch (ex) { cause = ex } throw new GradleException("Javadoc generation failed for ${project.path},\n Options file at: ${optionsFile}\n Command output at: ${outputFile}", cause) } // append some special table css, prettify css ant.concat(destfile: "${project.javadoc.destinationDir}/stylesheet.css", append: "true", fixlastline: "true", encoding: "UTF-8") { filelist(dir: project(":lucene").file("tools/javadoc"), files: "table_padding.css") filelist(dir: project(":lucene").file("tools/prettify"), files: "prettify.css") } // append prettify to scripts ant.concat(destfile: "${project.javadoc.destinationDir}/script.js", append: "true", fixlastline: "true", encoding: "UTF-8") { filelist(dir: project(':lucene').file("tools/prettify"), files: "prettify.js inject-javadocs.js") } ant.fixcrlf(srcdir: project.javadoc.destinationDir, includes: "stylesheet.css script.js", eol: "lf", fixlast: "true", encoding: "UTF-8") } } } } configure(subprojects.findAll { it.path.startsWith(':lucene') && it.path != ':lucene:core' }) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:core'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } doLast { // fix for Java 11 Javadoc tool that cannot handle split packages between modules correctly (by removing all the packages which are part of lucene-core) // problem description: [https://issues.apache.org/jira/browse/LUCENE-8738?focusedCommentId=16818106&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-16818106] ant.local(name: "element-list-regex") // contains a regex for all package names which are in lucene-core's javadoc ant.loadfile(property: "element-list-regex", srcFile: "${project(':lucene:core').javadoc.destinationDir}/element-list", encoding: "utf-8") { filterchain { tokenfilter(delimoutput: "|") { replacestring(from: ".", to: "\\.") } } } ant.replaceregexp( encoding: "UTF-8", file: "${project.javadoc.destinationDir}/element-list", byline: "true", match: "^(\${element-list-regex})\$", replace: "") } } } } configure(subprojects.findAll { it.path.startsWith(':lucene:analysis') && it.path != ':lucene:analysis:common'}) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:analysis:common'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:benchmark')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:memory', ':lucene:highlighter', ':lucene:analysis:common', ':lucene:queryparser', ':lucene:facet', ':lucene:spatial-extras'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:classification')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:queries', ':lucene:analysis:common', ':lucene:grouping'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:demo')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:analysis:common', ':lucene:queryparser', ':lucene:queries', ':lucene:facet', ':lucene:expressions'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } // we link the example source in the javadocs, as it's ref'ed elsewhere linksource = true } } } configure(project(':lucene:grouping')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:queries'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:highlighter')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:memory'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:monitor')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:memory', ':lucene:analysis:common', ':lucene:queryparser'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:queryparser')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:queries', ':lucene:sandbox'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:replicator')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:facet'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:spatial-extras')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:spatial3d'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:suggest')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:analysis:common'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } configure(project(':lucene:test-framework')) { plugins.withType(JavaPlugin) { renderJavadoc { [':lucene:codecs'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } linkJUnit = true } } } configure(subprojects.findAll { it.path.startsWith(':solr') }) { plugins.withType(JavaPlugin) { def hasJavdocsTask = project.tasks.collect { it.name }.contains('renderJavadoc') if (hasJavdocsTask) { renderJavadoc { [':lucene:core', ':lucene:analysis:common', ':lucene:analysis:icu', ':lucene:analysis:kuromoji', ':lucene:analysis:nori', ':lucene:analysis:morfologik', ':lucene:analysis:phonetic', ':lucene:analysis:smartcn', ':lucene:analysis:stempel', ':lucene:backward-codecs', ':lucene:codecs', ':lucene:expressions', ':lucene:suggest', ':lucene:grouping', ':lucene:join', ':lucene:queries', ':lucene:queryparser', ':lucene:highlighter', ':lucene:memory', ':lucene:misc', ':lucene:classification', ':lucene:spatial-extras'].collect { path -> dependsOn "${path}:renderJavadoc" linkLuceneProjects += [ path ] } } } } } configure(project(':solr:core')) { plugins.withType(JavaPlugin) { // specialized to ONLY depend on solrj renderJavadoc { [':solr:solrj'].collect { path -> dependsOn "${path}:renderJavadoc" linkSorlProjects += [ path ] } } } } configure(subprojects.findAll { it.path.startsWith(':solr:contrib') }) { plugins.withType(JavaPlugin) { renderJavadoc { [':solr:solrj', ':solr:core'].collect { path -> dependsOn "${path}:renderJavadoc" linkSorlProjects += [ path ] } } } } configure(project(':solr:contrib:dataimporthandler-extras')) { plugins.withType(JavaPlugin) { renderJavadoc { [':solr:contrib:dataimporthandler'].collect { path -> dependsOn "${path}:renderJavadoc" linkSorlProjects += [ path ] } } } } configure(project(':solr:test-framework')) { plugins.withType(JavaPlugin) { renderJavadoc { linkJUnit = true } } } configure(subprojects.findAll { it.path in [':solr:solr-ref-guide', ':solr:server', ':solr:webapp']}) { afterEvaluate { project.tasks.findByPath("renderJavadoc").enabled = false } }