diff --git a/geode-assembly/build.gradle b/geode-assembly/build.gradle index 1ff49ac8a47..02f34a8ae15 100755 --- a/geode-assembly/build.gradle +++ b/geode-assembly/build.gradle @@ -120,6 +120,11 @@ sourceSets { } output.dir(webServersDir, builtBy: 'downloadWebServers') } + // Javadoc-only stubs (Tomcat legacy classes) compiled separately so we can exclude their + // packages from published Javadoc output while still resolving symbols. + javadocStubs { + java.srcDir 'src/javadocStubs/java' + } } task downloadWebServers(type:Copy) { @@ -168,6 +173,16 @@ dependencies { javadocOnly(project(':extensions:geode-modules-tomcat9')) javadocOnly(project(':extensions:geode-modules-tomcat8')) + // Add common external dependencies needed for Javadoc generation + javadocOnly(platform(project(':boms:geode-all-bom'))) + + // Add FindBugs annotations for javadoc compilation + javadocOnly('com.github.stephenc.findbugs:findbugs-annotations') + + // Add Tomcat dependencies for modules javadoc compilation - use newer version for compatibility + javadocOnly('org.apache.tomcat:tomcat-catalina:' + DependencyConstraints.get('tomcat9.version')) + javadocOnly('org.apache.tomcat:tomcat-servlet-api:' + DependencyConstraints.get('tomcat9.version')) + testImplementation(project(':geode-core')) testImplementation(project(':geode-gfsh')) testImplementation(project(':geode-junit')) { @@ -347,15 +362,21 @@ tasks.register('defaultCacheConfig', JavaExec) { } def getDependencyProjectsFor(String configurationName) { - List rval = configurations[configurationName].allDependencies.collect { + List rval = configurations[configurationName].allDependencies.findAll { + it.hasProperty('dependencyProject') && it.dependencyProject != null + }.collect { it.dependencyProject }.collect { def projs = [it] if ((it as Project).pluginManager.hasPlugin('java-library')) { - (it as Project).configurations.api.dependencies.collect { + (it as Project).configurations.api.dependencies.findAll { + it.hasProperty('dependencyProject') && it.dependencyProject != null + }.collect { projs += it.dependencyProject } - (it as Project).configurations.runtimeOnly.dependencies.collect { + (it as Project).configurations.runtimeOnly.dependencies.findAll { + it.hasProperty('dependencyProject') && it.dependencyProject != null + }.collect { projs += it.dependencyProject } } @@ -392,6 +413,26 @@ tasks.register('gfshDepsJar', Jar) { } } +// Extract legacy Tomcat 6 jars needed only to satisfy Javadoc for old session manager classes +// (LifecycleSupport, SerializablePrincipal) without altering runtime dependencies. +def legacyTomcatDir = "$buildDir/legacyTomcat" +tasks.register('extractLegacyTomcatForJavadoc') { + description = 'Extracts legacy Tomcat catalina jars for Javadoc symbol resolution.' + outputs.dir(legacyTomcatDir) + dependsOn configurations.webServerTomcat6 + doLast { + delete legacyTomcatDir + copy { + from { zipTree(configurations.webServerTomcat6.singleFile) } + // Include the full Tomcat 6 lib set so packages like org.apache.catalina.ha.session + // (SerializablePrincipal) and util.LifecycleSupport are present. We keep it scoped + // to Javadoc only via this extracted directory rather than adding runtime deps. + include '**/lib/*.jar' + into legacyTomcatDir + } + } +} + tasks.register('docs', Javadoc) { def docsDir = file("$buildDir/javadocs") // Removed -Xwerror to avoid treating HTML5 compatibility warnings as errors @@ -401,16 +442,51 @@ tasks.register('docs', Javadoc) { title = "${productName} ${project.version}" destinationDir = docsDir - getDependencyProjectsFor('javadocOnly').forEach() { Project proj -> + // Do NOT add the javadocStubs sources directly; we only want them on the classpath, not in output. + + def docProjects = getDependencyProjectsFor('javadocOnly').findAll { proj -> + proj.hasProperty('sourceSets') + } + + // Ensure compilation is done before aggregating docs + dependsOn(docProjects.collect { it.tasks.named('classes') }) + dependsOn(tasks.named('javadocStubsClasses')) + + // Collect source, includes, and excludes from project javadoc tasks + docProjects.forEach { proj -> + source proj.sourceSets.main.allJava + + // Collect includes and excludes from individual project javadoc tasks when available proj.tasks.withType(Javadoc).findAll { it.enabled }.each { javadocTask -> - source += javadocTask.source - classpath += javadocTask.classpath - excludes += javadocTask.excludes includes += javadocTask.includes + excludes += javadocTask.excludes } } + // Common exclude patterns retained (may overlap with per-project excludes) + exclude '**/internal/**' + exclude '**/test/**' + + + // Use javadocOnly configuration with transitive dependencies to get external libraries + // This avoids cross-project configuration resolution while including necessary dependencies + // Include legacy Tomcat jars for symbol resolution of older session manager classes + dependsOn(tasks.named('extractLegacyTomcatForJavadoc')) + // Use a lazy FileCollection for legacy Tomcat jars so extraction runs before it is resolved + // Broaden legacy Tomcat inclusion (Option 2) to all jars in Tomcat6 lib so that + // org.apache.catalina.util.LifecycleSupport and org.apache.catalina.ha.session.SerializablePrincipal + // (present in clustering/ha related jars) are available to Javadoc without excluding sources. + def legacyCatalinaJars = files { fileTree(legacyTomcatDir).matching { include '*.jar' } } + classpath = configurations.javadocOnly + + files(docProjects.collect { proj -> proj.sourceSets.main.output }) + + legacyCatalinaJars + + sourceSets.javadocStubs.output + + options.addStringOption('Xwerror','-quiet') + include 'org/apache/geode/**/' + // Exclude all catalina packages (real or stub) from published Javadoc output + exclude 'org/apache/catalina/**' doLast { rootProject.subprojects.each { project -> diff --git a/geode-assembly/src/javadocStubs/java/org/apache/catalina/LifecycleListener.java b/geode-assembly/src/javadocStubs/java/org/apache/catalina/LifecycleListener.java new file mode 100644 index 00000000000..f7393ad8b14 --- /dev/null +++ b/geode-assembly/src/javadocStubs/java/org/apache/catalina/LifecycleListener.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.catalina; + +/** Minimal placeholder for legacy Tomcat LifecycleListener. */ +public interface LifecycleListener { +} diff --git a/geode-assembly/src/javadocStubs/java/org/apache/catalina/Realm.java b/geode-assembly/src/javadocStubs/java/org/apache/catalina/Realm.java new file mode 100644 index 00000000000..bdce395248f --- /dev/null +++ b/geode-assembly/src/javadocStubs/java/org/apache/catalina/Realm.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.catalina; + +import java.security.Principal; + +/** Minimal placeholder for legacy Tomcat Realm. */ +public interface Realm { + Principal authenticate(String username, String credentials); +} diff --git a/geode-assembly/src/javadocStubs/java/org/apache/catalina/ha/session/SerializablePrincipal.java b/geode-assembly/src/javadocStubs/java/org/apache/catalina/ha/session/SerializablePrincipal.java new file mode 100644 index 00000000000..baeaa80f600 --- /dev/null +++ b/geode-assembly/src/javadocStubs/java/org/apache/catalina/ha/session/SerializablePrincipal.java @@ -0,0 +1,61 @@ +/* + * 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. + * + * Javadoc stub for legacy Tomcat class org.apache.catalina.ha.session.SerializablePrincipal. + * Only the minimal surface required by DeltaSession is implemented. This stub exists + * exclusively for aggregate Javadoc generation and MUST NOT be on any runtime classpath. + */ +package org.apache.catalina.ha.session; + +import java.io.Serializable; +import java.security.Principal; + +import org.apache.catalina.Realm; +import org.apache.catalina.realm.GenericPrincipal; + +@SuppressWarnings({"unused"}) +public class SerializablePrincipal implements Serializable { + private static final long serialVersionUID = 1L; + private final String name; + + public SerializablePrincipal(String name) { + this.name = name; + } + + public static SerializablePrincipal createPrincipal(GenericPrincipal gp) { + return new SerializablePrincipal(gp == null ? null : gp.getName()); + } + + public Principal getPrincipal(Realm realm) { + // Provide a minimal Principal; GenericPrincipal construction not reproduced. + return new Principal() { + @Override + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + }; + } + + @Override + public String toString() { + return name; + } +} diff --git a/geode-assembly/src/javadocStubs/java/org/apache/catalina/realm/GenericPrincipal.java b/geode-assembly/src/javadocStubs/java/org/apache/catalina/realm/GenericPrincipal.java new file mode 100644 index 00000000000..46ee0149cba --- /dev/null +++ b/geode-assembly/src/javadocStubs/java/org/apache/catalina/realm/GenericPrincipal.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.catalina.realm; + +import java.security.Principal; + +/** Minimal placeholder for legacy Tomcat GenericPrincipal used only for name access. */ +public class GenericPrincipal implements Principal { + private final String name; + + public GenericPrincipal(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/geode-assembly/src/javadocStubs/java/org/apache/catalina/util/LifecycleSupport.java b/geode-assembly/src/javadocStubs/java/org/apache/catalina/util/LifecycleSupport.java new file mode 100644 index 00000000000..d11bb311b6a --- /dev/null +++ b/geode-assembly/src/javadocStubs/java/org/apache/catalina/util/LifecycleSupport.java @@ -0,0 +1,54 @@ +/* + * 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. + * + * Javadoc stub for legacy Tomcat 6 class org.apache.catalina.util.LifecycleSupport. + * This is provided solely to satisfy aggregate Javadoc generation for deprecated + * session manager implementations that still reference the Tomcat 6 API. It is NOT + * a functional replacement and MUST NOT be placed on any runtime classpath. + */ +package org.apache.catalina.util; + +import org.apache.catalina.LifecycleListener; + +/** + * Minimal no-op implementation exposing only the methods invoked by Geode's + * deprecated Tomcat6/7 session manager code during Javadoc compilation. + * All operations are no-ops. + */ +@SuppressWarnings({"unused", "deprecation"}) +public class LifecycleSupport { + private final Object source; + + public LifecycleSupport(Object source) { + this.source = source; + } + + public void addLifecycleListener(LifecycleListener listener) { + // no-op + } + + public LifecycleListener[] findLifecycleListeners() { + return new LifecycleListener[0]; + } + + public void fireLifecycleEvent(String type, Object data) { + // no-op + } + + public void removeLifecycleListener(LifecycleListener listener) { + // no-op + } +}