This is an automated email from the ASF dual-hosted git repository.

slfan1989 pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/trunk by this push:
     new df9e73822e1 HADOOP-19402. [JDK11] JDiff Support JDK11. (#8038) 
Contributed by Hualong Zhang.
df9e73822e1 is described below

commit df9e73822e1e2c299a25401fc1576c681954ab91
Author: hualong <[email protected]>
AuthorDate: Mon Dec 29 22:33:25 2025 +0800

    HADOOP-19402. [JDK11] JDiff Support JDK11. (#8038) Contributed by Hualong 
Zhang.
    
    * HADOOP-19402. [JDK11] JDiff Support JDK11.
    
    Reviewed-by: Chris Nauroth <[email protected]>
    Signed-off-by: Shilun Fan <[email protected]>
---
 hadoop-common-project/hadoop-annotations/pom.xml   |  56 +---
 .../ExcludePrivateAnnotationsJDiffDoclet.java      |  59 +++-
 .../ExcludePrivateAnnotationsStandardDoclet.java   | 203 ++++++++++++
 .../tools/IncludePublicAnnotationsJDiffDoclet.java | 198 +++++++++++
 .../IncludePublicAnnotationsStandardDoclet.java    | 198 +++++++++++
 .../classification/tools/RootDocProcessor.java     | 369 +++++++++++++++++++++
 .../classification/tools/StabilityOptions.java     | 100 +++++-
 .../ExcludePrivateAnnotationsStandardDoclet.java   |  62 ----
 .../tools/IncludePublicAnnotationsJDiffDoclet.java |  64 ----
 .../IncludePublicAnnotationsStandardDoclet.java    |  63 ----
 .../classification/tools/RootDocProcessor.java     | 251 --------------
 .../hadoop-mapreduce-client/pom.xml                |   2 +-
 hadoop-project-dist/pom.xml                        |  27 +-
 hadoop-project/pom.xml                             |   4 +-
 hadoop-yarn-project/hadoop-yarn/pom.xml            |   2 +-
 15 files changed, 1144 insertions(+), 514 deletions(-)

diff --git a/hadoop-common-project/hadoop-annotations/pom.xml 
b/hadoop-common-project/hadoop-annotations/pom.xml
index bc7a2ef60b6..86bc5d92379 100644
--- a/hadoop-common-project/hadoop-annotations/pom.xml
+++ b/hadoop-common-project/hadoop-annotations/pom.xml
@@ -31,50 +31,24 @@
 
   <dependencies>
     <dependency>
-      <groupId>jdiff</groupId>
+      <groupId>io.github.zhtttylz</groupId>
       <artifactId>jdiff</artifactId>
       <scope>provided</scope>
     </dependency>
   </dependencies>
 
-  <profiles>
-    <profile>
-      <id>jdk1.8</id>
-      <activation>
-        <jdk>1.8</jdk>
-      </activation>
-      <dependencies>
-        <dependency>
-          <groupId>jdk.tools</groupId>
-          <artifactId>jdk.tools</artifactId>
-          <version>1.8</version>
-          <scope>system</scope>
-          <systemPath>${java.home}/../lib/tools.jar</systemPath>
-        </dependency>
-      </dependencies>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.codehaus.mojo</groupId>
-            <artifactId>build-helper-maven-plugin</artifactId>
-            <executions>
-              <execution>
-                <id>add-source</id>
-                <phase>generate-sources</phase>
-                <goals>
-                  <goal>add-source</goal>
-                </goals>
-                <configuration>
-                  <sources>
-                    <source>${basedir}/src/main/java8</source>
-                  </sources>
-                </configuration>
-              </execution>
-            </executions>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-  </profiles>
-
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <compilerArgs>
+            <arg>--add-modules</arg>
+            <arg>jdk.javadoc</arg>
+          </compilerArgs>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
 </project>
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsJDiffDoclet.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsJDiffDoclet.java
similarity index 56%
rename from 
hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsJDiffDoclet.java
rename to 
hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsJDiffDoclet.java
index 5cc422f5893..ab55d758edb 100644
--- 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsJDiffDoclet.java
+++ 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsJDiffDoclet.java
@@ -17,31 +17,55 @@
  */
 package org.apache.hadoop.classification.tools;
 
-import com.sun.javadoc.DocErrorReporter;
-import com.sun.javadoc.LanguageVersion;
-import com.sun.javadoc.RootDoc;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Reporter;
+import javax.lang.model.SourceVersion;
 
 import jdiff.JDiff;
 
 /**
- * A <a 
href="http://java.sun.com/javase/6/docs/jdk/api/javadoc/doclet/";>Doclet</a>
- * for excluding elements that are annotated with
+ * <a href=
+ * 
"https://docs.oracle.com/en/java/javase/17/docs/api/jdk.javadoc/jdk/javadoc/doclet/Doclet.html";>
+ * Doclet</a> for excluding elements that are annotated with
  * {@link org.apache.hadoop.classification.InterfaceAudience.Private} or
  * {@link org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate}.
  * It delegates to the JDiff Doclet, and takes the same options.
  */
-public class ExcludePrivateAnnotationsJDiffDoclet {
-  
-  public static LanguageVersion languageVersion() {
-    return LanguageVersion.JAVA_1_5;
+public final class ExcludePrivateAnnotationsJDiffDoclet {
+
+  /**
+   * Returns the source version used by this doclet.
+   *
+   * @return the supported source version
+   */
+  public static SourceVersion languageVersion() {
+    return SourceVersion.RELEASE_17;
   }
-  
-  public static boolean start(RootDoc root) {
+
+  /**
+   * Legacy doclet entry point used by JDiff/Javadoc.
+   *
+   * @param root the doclet environment
+   * @return true if the doclet completed successfully
+   */
+  public static boolean start(DocletEnvironment root) {
     System.out.println(
         ExcludePrivateAnnotationsJDiffDoclet.class.getSimpleName());
     return JDiff.start(RootDocProcessor.process(root));
   }
-  
+
+  /**
+   * Utility class: provides only static entry points for JDiff.
+   */
+  private ExcludePrivateAnnotationsJDiffDoclet() {
+  }
+
+  /**
+   * Returns the length of a supported option.
+   *
+   * @param option the option name
+   * @return the number of arguments including the option itself
+   */
   public static int optionLength(String option) {
     Integer length = StabilityOptions.optionLength(option);
     if (length != null) {
@@ -49,9 +73,16 @@ public static int optionLength(String option) {
     }
     return JDiff.optionLength(option);
   }
-  
+
+  /**
+   * Validates options before running the doclet.
+   *
+   * @param options  the options to validate
+   * @param reporter the reporter to use for diagnostics
+   * @return true if the options are valid
+   */
   public static boolean validOptions(String[][] options,
-      DocErrorReporter reporter) {
+      Reporter reporter) {
     StabilityOptions.validOptions(options, reporter);
     String[][] filteredOptions = StabilityOptions.filterOptions(options);
     return JDiff.validOptions(filteredOptions, reporter);
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsStandardDoclet.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsStandardDoclet.java
new file mode 100644
index 00000000000..31fa2fd7c79
--- /dev/null
+++ 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsStandardDoclet.java
@@ -0,0 +1,203 @@
+/*
+ * 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.hadoop.classification.tools;
+
+import jdk.javadoc.doclet.Doclet;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Reporter;
+import javax.lang.model.SourceVersion;
+
+import jdk.javadoc.doclet.StandardDoclet;
+
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * <a href=
+ * 
"https://docs.oracle.com/en/java/javase/17/docs/api/jdk.javadoc/jdk/javadoc/doclet/Doclet.html";>
+ * Doclet</a> for excluding elements that are
+ * annotated with {@link 
org.apache.hadoop.classification.InterfaceAudience.Private}
+ * or {@link 
org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate}.
+ * It delegates to the Standard Doclet, and takes the same options.
+ */
+public class ExcludePrivateAnnotationsStandardDoclet implements Doclet {
+
+  private final StandardDoclet delegate = new StandardDoclet();
+  private Reporter reporter;
+  private Locale locale;
+
+  /**
+   * Public no-arg constructor required by the Javadoc tool.
+   */
+  public ExcludePrivateAnnotationsStandardDoclet() {
+  }
+
+  /**
+   * Returns the source version used by this doclet.
+   *
+   * @return the supported source version
+   */
+  public static SourceVersion languageVersion() {
+    return SourceVersion.RELEASE_17;
+  }
+
+  /**
+   * Legacy doclet entry point used by Javadoc.
+   *
+   * @param root the doclet environment
+   * @return true if the doclet completed successfully
+   */
+  public static boolean start(DocletEnvironment root) {
+    
System.out.println(ExcludePrivateAnnotationsStandardDoclet.class.getSimpleName());
+    if (root.getSpecifiedElements().isEmpty()) {
+      return true;
+    }
+    return new StandardDoclet().run(root);
+  }
+
+  /**
+   * Returns the length of a supported option.
+   *
+   * @param option the option name
+   * @return the number of arguments including the option itself
+   */
+  public static int optionLength(String option) {
+    Integer length = StabilityOptions.optionLength(option);
+    if (length != null) {
+      return length;
+    }
+    for (Doclet.Option o : new StandardDoclet().getSupportedOptions()) {
+      for (String name : o.getNames()) {
+        if (name.equals(option)) {
+          return o.getArgumentCount() + 1;
+        }
+      }
+    }
+    return 0;
+  }
+
+  /**
+   * Validates options before running the doclet.
+   *
+   * @param options  the options to validate
+   * @param reporter the reporter to use for diagnostics
+   * @return true if the options are valid
+   */
+  public static boolean validOptions(String[][] options, Reporter reporter) {
+    StabilityOptions.validOptions(options, reporter);
+    return true;
+  }
+
+  @Override
+  public void init(Locale initLocale, Reporter initReporter) {
+    this.locale = initLocale;
+    this.reporter = initReporter;
+    delegate.init(locale, reporter);
+  }
+
+  @Override
+  public String getName() {
+    return getClass().getSimpleName();
+  }
+
+  @Override
+  public Set<Option> getSupportedOptions() {
+    Set<Option> s = new java.util.HashSet<>(delegate.getSupportedOptions());
+    s.add(new Option() {
+      @Override
+      public int getArgumentCount() {
+        return 0;
+      }
+
+      @Override
+      public String getDescription() {
+        return "";
+      }
+
+      @Override
+      public Kind getKind() {
+        return Kind.OTHER;
+      }
+
+      @Override
+      public java.util.List<String> getNames() {
+        return java.util.Collections.singletonList("-unstable");
+      }
+
+      @Override
+      public String getParameters() {
+        return "";
+      }
+
+      @Override
+      public boolean process(String opt, java.util.List<String> args) {
+        StabilityOptions.setLevel(StabilityOptions.Level.UNSTABLE);
+        return true;
+      }
+    });
+    s.add(new Option() {
+      @Override
+      public int getArgumentCount() {
+        return 0;
+      }
+
+      @Override
+      public String getDescription() {
+        return "";
+      }
+
+      @Override
+      public Kind getKind() {
+        return Kind.OTHER;
+      }
+
+      @Override
+      public java.util.List<String> getNames() {
+        return java.util.Collections.singletonList("-evolving");
+      }
+
+      @Override
+      public String getParameters() {
+        return "";
+      }
+
+      @Override
+      public boolean process(String opt, java.util.List<String> args) {
+        StabilityOptions.setLevel(StabilityOptions.Level.EVOLVING);
+        return true;
+      }
+    });
+    return s;
+  }
+
+  @Override
+  public SourceVersion getSupportedSourceVersion() {
+    return SourceVersion.RELEASE_17;
+  }
+
+  @Override
+  public boolean run(DocletEnvironment environment) {
+    StabilityOptions.applyToRootProcessor();
+    RootDocProcessor.process(environment);
+
+    if (environment.getIncludedElements().isEmpty()) {
+      return true;
+    }
+    return delegate.run(environment);
+  }
+}
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/IncludePublicAnnotationsJDiffDoclet.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/IncludePublicAnnotationsJDiffDoclet.java
new file mode 100644
index 00000000000..374519336a2
--- /dev/null
+++ 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/IncludePublicAnnotationsJDiffDoclet.java
@@ -0,0 +1,198 @@
+/*
+ * 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.hadoop.classification.tools;
+
+import jdk.javadoc.doclet.Doclet;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Reporter;
+
+import javax.lang.model.SourceVersion;
+
+import jdiff.JDiff;
+
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * <a href=
+ * 
"https://docs.oracle.com/en/java/javase/17/docs/api/jdk.javadoc/jdk/javadoc/doclet/Doclet.html";>
+ * Doclet</a> that only includes class-level elements that are annotated
+ * with {@link org.apache.hadoop.classification.InterfaceAudience.Public}.
+ * Class-level elements with no annotation are excluded.
+ * In addition, all elements that are annotated with
+ * {@link org.apache.hadoop.classification.InterfaceAudience.Private}
+ * or {@link org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate}
+ * are also excluded.
+ * It delegates to the JDiff Doclet, and takes the same options.
+ */
+public class IncludePublicAnnotationsJDiffDoclet implements Doclet {
+
+  private final JDiff delegate = new JDiff();
+  private Reporter reporter;
+  private Locale locale;
+
+  @Override
+  public void init(Locale newLocale, Reporter newReporter) {
+    this.locale = newLocale;
+    this.reporter = newReporter;
+    delegate.init(newLocale, newReporter);
+  }
+
+  @Override
+  public String getName() {
+    return getClass().getSimpleName();
+  }
+
+  @Override
+  public Set<Option> getSupportedOptions() {
+    Set<Option> s = new java.util.HashSet<>(delegate.getSupportedOptions());
+    s.add(new Option() {
+      @Override
+      public int getArgumentCount() {
+        return 0;
+      }
+
+      @Override
+      public String getDescription() {
+        return "";
+      }
+
+      @Override
+      public Kind getKind() {
+        return Kind.OTHER;
+      }
+
+      @Override
+      public java.util.List<String> getNames() {
+        return java.util.Collections.singletonList("-unstable");
+      }
+
+      @Override
+      public String getParameters() {
+        return "";
+      }
+
+      @Override
+      public boolean process(String opt, java.util.List<String> args) {
+        StabilityOptions.setLevel(StabilityOptions.Level.UNSTABLE);
+        return true;
+      }
+    });
+    s.add(new Option() {
+      @Override
+      public int getArgumentCount() {
+        return 0;
+      }
+
+      @Override
+      public String getDescription() {
+        return "";
+      }
+
+      @Override
+      public Kind getKind() {
+        return Kind.OTHER;
+      }
+
+      @Override
+      public java.util.List<String> getNames() {
+        return java.util.Collections.singletonList("-evolving");
+      }
+
+      @Override
+      public String getParameters() {
+        return "";
+      }
+
+      @Override
+      public boolean process(String opt, java.util.List<String> args) {
+        StabilityOptions.setLevel(StabilityOptions.Level.EVOLVING);
+        return true;
+      }
+    });
+    return s;
+  }
+
+  @Override
+  public SourceVersion getSupportedSourceVersion() {
+    return SourceVersion.RELEASE_17;
+  }
+
+  @Override
+  public boolean run(DocletEnvironment root) {
+    
System.out.println(IncludePublicAnnotationsJDiffDoclet.class.getSimpleName());
+    RootDocProcessor.setTreatUnannotatedClassesAsPrivate(true);
+    StabilityOptions.applyToRootProcessor();
+    return delegate.run(RootDocProcessor.process(root));
+  }
+
+  /**
+   * Returns the source version used by this doclet.
+   *
+   * @return the supported source version
+   */
+  public static SourceVersion languageVersion() {
+    return SourceVersion.RELEASE_17;
+  }
+
+  /**
+   * Public no-arg constructor required by the Javadoc tool.
+   */
+  public IncludePublicAnnotationsJDiffDoclet() {
+  }
+
+  /**
+   * Legacy doclet entry point used by JDiff/Javadoc.
+   *
+   * @param root the doclet environment
+   * @return true if the doclet completed successfully
+   */
+  public static boolean start(DocletEnvironment root) {
+    System.out.println(
+        IncludePublicAnnotationsJDiffDoclet.class.getSimpleName());
+    RootDocProcessor.setTreatUnannotatedClassesAsPrivate(true);
+    return JDiff.start(RootDocProcessor.process(root));
+  }
+
+  /**
+   * Returns the length of a supported option.
+   *
+   * @param option the option name
+   * @return the number of arguments including the option itself
+   */
+  public static int optionLength(String option) {
+    Integer length = StabilityOptions.optionLength(option);
+    if (length != null) {
+      return length;
+    }
+    return JDiff.optionLength(option);
+  }
+
+  /**
+   * Validates options before running the doclet.
+   *
+   * @param options  the options to validate
+   * @param reporter the reporter to use for diagnostics
+   * @return true if the options are valid
+   */
+  public static boolean validOptions(String[][] options, Reporter reporter) {
+    StabilityOptions.validOptions(options, reporter);
+    String[][] filteredOptions = StabilityOptions.filterOptions(options);
+    return JDiff.validOptions(filteredOptions, reporter);
+  }
+}
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/IncludePublicAnnotationsStandardDoclet.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/IncludePublicAnnotationsStandardDoclet.java
new file mode 100644
index 00000000000..634a99b57fc
--- /dev/null
+++ 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/IncludePublicAnnotationsStandardDoclet.java
@@ -0,0 +1,198 @@
+/*
+ * 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.hadoop.classification.tools;
+
+import jdk.javadoc.doclet.Doclet;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Reporter;
+import javax.lang.model.SourceVersion;
+
+import jdk.javadoc.doclet.StandardDoclet;
+
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * <a href=
+ * 
"https://docs.oracle.com/en/java/javase/17/docs/api/jdk.javadoc/jdk/javadoc/doclet/Doclet.html";>
+ * Doclet</a> that only includes class-level elements that are annotated
+ * with {@link org.apache.hadoop.classification.InterfaceAudience.Public}.
+ * Class-level elements with no annotation are excluded.
+ * In addition, all elements that are annotated with
+ * {@link org.apache.hadoop.classification.InterfaceAudience.Private}
+ * or {@link org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate}
+ * are also excluded.
+ * It delegates to the Standard Doclet, and takes the same options.
+ */
+public class IncludePublicAnnotationsStandardDoclet implements Doclet {
+
+  /**
+   * Returns the source version used by this doclet.
+   *
+   * @return the supported source version
+   */
+  public static SourceVersion languageVersion() {
+    return SourceVersion.RELEASE_17;
+  }
+
+  /**
+   * Public no-arg constructor required by the Javadoc tool.
+   */
+  public IncludePublicAnnotationsStandardDoclet() {
+  }
+
+  private final StandardDoclet delegate = new StandardDoclet();
+
+  @Override
+  public void init(Locale locale, Reporter reporter) {
+    delegate.init(locale, reporter);
+  }
+
+  @Override
+  public String getName() {
+    return IncludePublicAnnotationsStandardDoclet.class.getSimpleName();
+  }
+
+  @Override
+  public Set<Option> getSupportedOptions() {
+    Set<Option> s = new java.util.HashSet<>(delegate.getSupportedOptions());
+    s.add(new Option() {
+      @Override
+      public int getArgumentCount() {
+        return 0;
+      }
+
+      @Override
+      public String getDescription() {
+        return "";
+      }
+
+      @Override
+      public Kind getKind() {
+        return Kind.OTHER;
+      }
+
+      @Override
+      public java.util.List<String> getNames() {
+        return java.util.Collections.singletonList("-unstable");
+      }
+
+      @Override
+      public String getParameters() {
+        return "";
+      }
+
+      @Override
+      public boolean process(String opt, java.util.List<String> args) {
+        StabilityOptions.setLevel(StabilityOptions.Level.UNSTABLE);
+        return true;
+      }
+    });
+    s.add(new Option() {
+      @Override
+      public int getArgumentCount() {
+        return 0;
+      }
+
+      @Override
+      public String getDescription() {
+        return "";
+      }
+
+      @Override
+      public Kind getKind() {
+        return Kind.OTHER;
+      }
+
+      @Override
+      public java.util.List<String> getNames() {
+        return java.util.Collections.singletonList("-evolving");
+      }
+
+      @Override
+      public String getParameters() {
+        return "";
+      }
+
+      @Override
+      public boolean process(String opt, java.util.List<String> args) {
+        StabilityOptions.setLevel(StabilityOptions.Level.UNSTABLE);
+        return true;
+      }
+    });
+    return s;
+  }
+
+  @Override
+  public SourceVersion getSupportedSourceVersion() {
+    return delegate.getSupportedSourceVersion();
+  }
+
+  @Override
+  public boolean run(DocletEnvironment env) {
+    System.out.println(getName());
+    RootDocProcessor.setTreatUnannotatedClassesAsPrivate(true);
+    StabilityOptions.applyToRootProcessor();
+    DocletEnvironment filtered = RootDocProcessor.process(env);
+    return delegate.run(filtered);
+  }
+
+  /**
+   * Legacy doclet entry point used by Javadoc.
+   *
+   * @param env the doclet environment
+   * @return true if the doclet completed successfully
+   */
+  public static boolean start(DocletEnvironment env) {
+    return new IncludePublicAnnotationsStandardDoclet().run(env);
+  }
+
+  /**
+   * Returns the length of a supported option.
+   *
+   * @param option the option name
+   * @return the number of arguments including the option itself
+   */
+  public static int optionLength(String option) {
+    Integer length = StabilityOptions.optionLength(option);
+    if (length != null) {
+      return length;
+    }
+    for (jdk.javadoc.doclet.Doclet.Option o :
+        new StandardDoclet().getSupportedOptions()) {
+      for (String name : o.getNames()) {
+        if (name.equals(option)) {
+          return o.getArgumentCount() + 1;
+        }
+      }
+    }
+    return 0;
+  }
+
+  /**
+   * Validates options before running the doclet.
+   *
+   * @param options  the options to validate
+   * @param reporter the reporter to use for diagnostics
+   * @return true if the options are valid
+   */
+  public static boolean validOptions(String[][] options, Reporter reporter) {
+    StabilityOptions.validOptions(options, reporter);
+    return true;
+  }
+}
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java
new file mode 100644
index 00000000000..741a1c7d068
--- /dev/null
+++ 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java
@@ -0,0 +1,369 @@
+/*
+ * 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.hadoop.classification.tools;
+
+import jdk.javadoc.doclet.DocletEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.stream.Collectors;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * Process the {@link DocletEnvironment} by substituting with (nested) proxy 
objects that
+ * exclude elements with Private or LimitedPrivate annotations.
+ * <p>
+ * Based on code from 
http://www.sixlegs.com/blog/java/exclude-javadoc-tag.html.
+ */
+final class RootDocProcessor {
+
+  private static String stability = StabilityOptions.UNSTABLE_OPTION;
+  private static boolean treatUnannotatedClassesAsPrivate = false;
+
+  static void setStability(String value) {
+    stability = value;
+  }
+
+  private RootDocProcessor() {
+    // no instances
+  }
+
+
+  static String getStability() {
+    return stability;
+  }
+
+  static void setTreatUnannotatedClassesAsPrivate(boolean value) {
+    treatUnannotatedClassesAsPrivate = value;
+  }
+
+  static boolean isTreatUnannotatedClassesAsPrivate() {
+    return treatUnannotatedClassesAsPrivate;
+  }
+
+  public static DocletEnvironment process(DocletEnvironment root) {
+    return (DocletEnvironment) wrap(root, DocletEnvironment.class);
+  }
+
+  private static final Map<Object, Object> PROXIES = new WeakHashMap<>();
+
+  private static Object wrap(Object obj, Class<?> expectedType) {
+    if (obj == null) {
+      return null;
+    }
+
+    if (obj instanceof DocletEnvironment) {
+      return getProxy(obj, new Class<?>[]{DocletEnvironment.class},
+          new EnvHandler((DocletEnvironment) obj));
+    }
+
+    if (obj instanceof Element) {
+      return getElementProxy((Element) obj);
+    }
+
+    if (obj instanceof Set) {
+      return filterAndWrapIterable((Iterable<?>) obj, true);
+    }
+    if (obj instanceof Collection) {
+      return filterAndWrapIterable((Iterable<?>) obj, false);
+    }
+    if (obj instanceof Iterable) {
+      return filterAndWrapIterable((Iterable<?>) obj, false);
+    }
+
+    if (obj.getClass().isArray()) {
+      int len = Array.getLength(obj);
+      Object[] res = new Object[len];
+      for (int i = 0; i < len; i++) {
+        Object v = Array.get(obj, i);
+        res[i] = wrap(v, v != null ? v.getClass() : Object.class);
+      }
+      return res;
+    }
+
+    return obj;
+  }
+
+  private static Object getElementProxy(Element el) {
+    Object cached = PROXIES.get(el);
+    if (cached != null) {
+      return cached;
+    }
+
+    Set<Class<?>> ifaces = new LinkedHashSet<>();
+    Collections.addAll(ifaces, el.getClass().getInterfaces());
+    ifaces.add(Element.class);
+    if (el instanceof TypeElement) {
+      ifaces.add(TypeElement.class);
+    }
+    if (el instanceof PackageElement) {
+      ifaces.add(PackageElement.class);
+    }
+    if (el instanceof ExecutableElement) {
+      ifaces.add(ExecutableElement.class);
+    }
+    if (el instanceof VariableElement) {
+      ifaces.add(VariableElement.class);
+    }
+
+    Object proxy = getProxy(el, ifaces.toArray(new Class<?>[0]), new 
ElementHandler(el));
+    PROXIES.put(el, proxy);
+    return proxy;
+  }
+
+  private static Object getProxy(Object target, Class<?>[] ifaces, 
InvocationHandler h) {
+    Object cached = PROXIES.get(target);
+    if (cached != null) {
+      return cached;
+    }
+    Object p = Proxy.newProxyInstance(target.getClass().getClassLoader(), 
ifaces, h);
+    PROXIES.put(target, p);
+    return p;
+  }
+
+  @SuppressWarnings("unchecked")
+  private static Object filterAndWrapIterable(Iterable<?> iterable, boolean 
preserveSet) {
+    if (iterable == null) {
+      return null;
+    }
+    if (preserveSet) {
+      Set<Object> out = new LinkedHashSet<>();
+      for (Object o : iterable) {
+        if (o instanceof Element) {
+          Element el = (Element) o;
+          if (!exclude(el)) {
+            out.add(getElementProxy(el));
+          }
+        } else {
+          out.add(wrap(o, o != null ? o.getClass() : Object.class));
+        }
+      }
+      return out;
+    } else {
+      List<Object> out = new ArrayList<>();
+      for (Object o : iterable) {
+        if (o instanceof Element) {
+          Element el = (Element) o;
+          if (!exclude(el)) {
+            out.add(getElementProxy(el));
+          }
+        } else {
+          out.add(wrap(o, o != null ? o.getClass() : Object.class));
+        }
+      }
+      return out;
+    }
+  }
+
+  private static Object unwrap(Object maybeProxy) {
+    if (!(maybeProxy instanceof Proxy)) {
+      return maybeProxy;
+    }
+    InvocationHandler ih = Proxy.getInvocationHandler(maybeProxy);
+    if (ih instanceof BaseHandler) {
+      return ((BaseHandler) ih).target;
+    }
+    return maybeProxy;
+  }
+
+  private static boolean exclude(Element el) {
+    boolean sawPublic = false;
+
+    for (AnnotationMirror am : el.getAnnotationMirrors()) {
+      final String qname = am.getAnnotationType().toString();
+
+      if (qname.equals(InterfaceAudience.Private.class.getCanonicalName())
+          || 
qname.equals(InterfaceAudience.LimitedPrivate.class.getCanonicalName())) {
+        return true;
+      }
+
+      if (stability.equals(StabilityOptions.EVOLVING_OPTION)) {
+        if 
(qname.equals(InterfaceStability.Unstable.class.getCanonicalName())) {
+          return true;
+        }
+      }
+      if (stability.equals(StabilityOptions.STABLE_OPTION)) {
+        if (qname.equals(InterfaceStability.Unstable.class.getCanonicalName())
+            || 
qname.equals(InterfaceStability.Evolving.class.getCanonicalName())) {
+          return true;
+        }
+      }
+
+      if (qname.equals(InterfaceAudience.Public.class.getCanonicalName())) {
+        sawPublic = true;
+      }
+    }
+
+    if (sawPublic) {
+      return false;
+    }
+
+    if (isTreatUnannotatedClassesAsPrivate()) {
+      ElementKind k = el.getKind();
+      if (k == ElementKind.CLASS || k == ElementKind.INTERFACE ||
+          k == ElementKind.ANNOTATION_TYPE) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  private static abstract class BaseHandler implements InvocationHandler {
+    private final Object target;
+
+    BaseHandler(Object target) {
+      this.target = target;
+    }
+
+    protected Object getTarget() {
+      return target;
+    }
+
+    Object wrapReturn(Object ret) {
+      if (ret == null) {
+        return null;
+      }
+      if (ret instanceof DocletEnvironment) {
+        return wrap(ret, DocletEnvironment.class);
+      }
+      if (ret instanceof Element) {
+        return getElementProxy((Element) ret);
+      }
+      if (ret instanceof Set) {
+        return filterAndWrapIterable((Set<?>) ret, true);
+      }
+      if (ret instanceof Collection) {
+        return filterAndWrapIterable((Collection<?>) ret, false);
+      }
+      if (ret instanceof Iterable) {
+        return filterAndWrapIterable((Iterable<?>) ret, false);
+      }
+      if (ret.getClass().isArray()) {
+        return wrap(ret, ret.getClass());
+      }
+      return ret;
+    }
+
+    Object[] unwrapArgs(Object[] args) {
+      if (args == null) {
+        return null;
+      }
+      Object[] r = new Object[args.length];
+      for (int i = 0; i < args.length; i++) {
+        r[i] = unwrap(args[i]);
+      }
+      return r;
+    }
+  }
+
+  private static final class EnvHandler extends BaseHandler {
+    private final DocletEnvironment env;
+
+    EnvHandler(DocletEnvironment env) {
+      super(env);
+      this.env = env;
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws 
Throwable {
+      String name = method.getName();
+      Object[] uargs = unwrapArgs(args);
+
+      if ("getDocTrees".equals(name)) {
+        return env.getDocTrees();
+      } else if ("isIncluded".equals(name)) {
+        Element e = (Element) uargs[0];
+        boolean base = env.isIncluded(e);
+        return base && !exclude(e);
+      } else if ("getIncludedElements".equals(name)) {
+        Set<? extends Element> base = env.getIncludedElements();
+        return base.stream()
+            .filter(e -> !exclude(e))
+            .collect(Collectors.toCollection(LinkedHashSet::new));
+      } else if ("getSpecifiedElements".equals(name)) {
+        Set<? extends Element> base = env.getSpecifiedElements();
+        return base.stream()
+            .filter(e -> !exclude(e))
+            .collect(Collectors.toCollection(LinkedHashSet::new));
+      }
+
+      Object ret = method.invoke(getTarget(), uargs);
+      return wrapReturn(ret);
+    }
+  }
+
+  private static final class ElementHandler extends BaseHandler {
+    private final Element element;
+
+    ElementHandler(Element element) {
+      super(element);
+      this.element = element;
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws 
Throwable {
+      String name = method.getName();
+      Object[] uargs = unwrapArgs(args);
+
+      if ("equals".equals(name) && uargs != null && uargs.length == 1) {
+        return Objects.equals(element, unwrap(uargs[0]));
+      }
+      if ("hashCode".equals(name) && (uargs == null || uargs.length == 0)) {
+        return element.hashCode();
+      }
+      if ("toString".equals(name) && (uargs == null || uargs.length == 0)) {
+        return element.toString();
+      }
+
+      if ("getEnclosedElements".equals(name) && (uargs == null || uargs.length 
== 0)) {
+        List<? extends Element> enclosed = element.getEnclosedElements();
+        List<Element> filtered = new ArrayList<>();
+        for (Element e : enclosed) {
+          if (!exclude(e)) {
+            filtered.add(e);
+          }
+        }
+        return filtered;
+      }
+
+      Object ret = method.invoke(getTarget(), uargs);
+      return wrapReturn(ret);
+    }
+  }
+}
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/StabilityOptions.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/StabilityOptions.java
similarity index 50%
rename from 
hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/StabilityOptions.java
rename to 
hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/StabilityOptions.java
index 5b2d70ded3f..c9d23ab472b 100644
--- 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/StabilityOptions.java
+++ 
b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/StabilityOptions.java
@@ -17,39 +17,111 @@
  */
 package org.apache.hadoop.classification.tools;
 
-import com.sun.javadoc.DocErrorReporter;
+import jdk.javadoc.doclet.Reporter;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 
-class StabilityOptions {
+/**
+ * Doclet option helpers for API stability filtering.
+ */
+public final class StabilityOptions {
+
+  /** Option flag: {@code -stable}. */
   public static final String STABLE_OPTION = "-stable";
+
+  /** Option flag: {@code -evolving}. */
   public static final String EVOLVING_OPTION = "-evolving";
+
+  /** Option flag: {@code -unstable}. */
   public static final String UNSTABLE_OPTION = "-unstable";
 
+  enum Level { STABLE, EVOLVING, UNSTABLE }
+  private static volatile Level level = Level.STABLE;
+
+  static void setLevel(Level l) {
+    if (l != null) {
+      level = l;
+    }
+  }
+
+  private StabilityOptions() {
+  }
+
+  /**
+   * Return option length for a supported stability option.
+   *
+   * @param option option name
+   * @return {@code 1} if supported; otherwise {@code null}
+   */
   public static Integer optionLength(String option) {
     String opt = option.toLowerCase(Locale.ENGLISH);
-    if (opt.equals(UNSTABLE_OPTION)) return 1;
-    if (opt.equals(EVOLVING_OPTION)) return 1;
-    if (opt.equals(STABLE_OPTION)) return 1;
+    if (opt.equals(UNSTABLE_OPTION)) {
+      return 1;
+    }
+    if (opt.equals(EVOLVING_OPTION)) {
+      return 1;
+    }
+    if (opt.equals(STABLE_OPTION)) {
+      return 1;
+    }
     return null;
   }
 
+  static void setFromOptionName(String optName) {
+    String opt = optName.toLowerCase(Locale.ENGLISH);
+    Level next = null;
+    if (opt.equals(UNSTABLE_OPTION)) {
+      next = Level.UNSTABLE;
+    } else if (opt.equals(EVOLVING_OPTION)) {
+      next = Level.EVOLVING;
+    } else if (opt.equals(STABLE_OPTION)) {
+      next = Level.STABLE;
+    }
+    if (next != null && next.ordinal() > level.ordinal()) {
+      level = next;
+    }
+  }
+
+  static Level getLevel() {
+    return level;
+  }
+
+  static void applyToRootProcessor() {
+    switch (level) {
+    case UNSTABLE:
+      RootDocProcessor.setStability(UNSTABLE_OPTION);
+      break;
+    case EVOLVING:
+      RootDocProcessor.setStability(EVOLVING_OPTION);
+      break;
+    default:
+      RootDocProcessor.setStability(STABLE_OPTION);
+    }
+  }
+
+  /**
+   * Validate and apply stability options.
+   *
+   * @param options  doclet options
+   * @param reporter reporter
+   */
   public static void validOptions(String[][] options,
-      DocErrorReporter reporter) {
+      Reporter reporter) {
     for (int i = 0; i < options.length; i++) {
       String opt = options[i][0].toLowerCase(Locale.ENGLISH);
-      if (opt.equals(UNSTABLE_OPTION)) {
-        RootDocProcessor.stability = UNSTABLE_OPTION;
-      } else if (opt.equals(EVOLVING_OPTION)) {
-        RootDocProcessor.stability = EVOLVING_OPTION;
-      } else if (opt.equals(STABLE_OPTION)) {
-        RootDocProcessor.stability = STABLE_OPTION;
-      }
+      setFromOptionName(opt);
     }
+    applyToRootProcessor();
   }
-  
+
+  /**
+   * Filter out stability options from the doclet options array.
+   *
+   * @param options doclet options
+   * @return options without stability flags
+   */
   public static String[][] filterOptions(String[][] options) {
     List<String[]> optionsList = new ArrayList<String[]>();
     for (int i = 0; i < options.length; i++) {
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsStandardDoclet.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsStandardDoclet.java
deleted file mode 100644
index 5c535c8e9e3..00000000000
--- 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/ExcludePrivateAnnotationsStandardDoclet.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.hadoop.classification.tools;
-
-import com.sun.javadoc.DocErrorReporter;
-import com.sun.javadoc.LanguageVersion;
-import com.sun.javadoc.RootDoc;
-import com.sun.tools.doclets.standard.Standard;
-
-/**
- * A <a 
href="http://java.sun.com/javase/6/docs/jdk/api/javadoc/doclet/";>Doclet</a>
- * for excluding elements that are annotated with
- * {@link org.apache.hadoop.classification.InterfaceAudience.Private} or
- * {@link org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate}.
- * It delegates to the Standard Doclet, and takes the same options.
- */
-public class ExcludePrivateAnnotationsStandardDoclet {
-  
-  public static LanguageVersion languageVersion() {
-    return LanguageVersion.JAVA_1_5;
-  }
-  
-  public static boolean start(RootDoc root) {
-    System.out.println(
-        ExcludePrivateAnnotationsStandardDoclet.class.getSimpleName());
-    RootDoc excludedDoc = RootDocProcessor.process(root);
-    if (excludedDoc.specifiedPackages().length == 0) {
-      return true;
-    }
-    return Standard.start(excludedDoc);
-  }
-  
-  public static int optionLength(String option) {
-    Integer length = StabilityOptions.optionLength(option);
-    if (length != null) {
-      return length;
-    }
-    return Standard.optionLength(option);
-  }
-  
-  public static boolean validOptions(String[][] options,
-      DocErrorReporter reporter) {
-    StabilityOptions.validOptions(options, reporter);
-    String[][] filteredOptions = StabilityOptions.filterOptions(options);
-    return Standard.validOptions(filteredOptions, reporter);
-  }
-}
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/IncludePublicAnnotationsJDiffDoclet.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/IncludePublicAnnotationsJDiffDoclet.java
deleted file mode 100644
index 91b3a9ddf25..00000000000
--- 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/IncludePublicAnnotationsJDiffDoclet.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.hadoop.classification.tools;
-
-import com.sun.javadoc.DocErrorReporter;
-import com.sun.javadoc.LanguageVersion;
-import com.sun.javadoc.RootDoc;
-
-import jdiff.JDiff;
-
-/**
- * A <a 
href="http://java.sun.com/javase/6/docs/jdk/api/javadoc/doclet/";>Doclet</a>
- * that only includes class-level elements that are annotated with
- * {@link org.apache.hadoop.classification.InterfaceAudience.Public}.
- * Class-level elements with no annotation are excluded.
- * In addition, all elements that are annotated with
- * {@link org.apache.hadoop.classification.InterfaceAudience.Private} or
- * {@link org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate}
- * are also excluded.
- * It delegates to the JDiff Doclet, and takes the same options.
- */
-public class IncludePublicAnnotationsJDiffDoclet {
-
-  public static LanguageVersion languageVersion() {
-    return LanguageVersion.JAVA_1_5;
-  }
-
-  public static boolean start(RootDoc root) {
-    System.out.println(
-        IncludePublicAnnotationsJDiffDoclet.class.getSimpleName());
-    RootDocProcessor.treatUnannotatedClassesAsPrivate = true;
-    return JDiff.start(RootDocProcessor.process(root));
-  }
-
-  public static int optionLength(String option) {
-    Integer length = StabilityOptions.optionLength(option);
-    if (length != null) {
-      return length;
-    }
-    return JDiff.optionLength(option);
-  }
-
-  public static boolean validOptions(String[][] options,
-      DocErrorReporter reporter) {
-    StabilityOptions.validOptions(options, reporter);
-    String[][] filteredOptions = StabilityOptions.filterOptions(options);
-    return JDiff.validOptions(filteredOptions, reporter);
-  }
-}
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/IncludePublicAnnotationsStandardDoclet.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/IncludePublicAnnotationsStandardDoclet.java
deleted file mode 100644
index 10d554d07b5..00000000000
--- 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/IncludePublicAnnotationsStandardDoclet.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.hadoop.classification.tools;
-
-import com.sun.javadoc.DocErrorReporter;
-import com.sun.javadoc.LanguageVersion;
-import com.sun.javadoc.RootDoc;
-import com.sun.tools.doclets.standard.Standard;
-
-/**
- * A <a 
href="http://java.sun.com/javase/6/docs/jdk/api/javadoc/doclet/";>Doclet</a>
- * that only includes class-level elements that are annotated with
- * {@link org.apache.hadoop.classification.InterfaceAudience.Public}.
- * Class-level elements with no annotation are excluded.
- * In addition, all elements that are annotated with
- * {@link org.apache.hadoop.classification.InterfaceAudience.Private} or
- * {@link org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate}
- * are also excluded.
- * It delegates to the Standard Doclet, and takes the same options.
- */
-public class IncludePublicAnnotationsStandardDoclet {
-  
-  public static LanguageVersion languageVersion() {
-    return LanguageVersion.JAVA_1_5;
-  }
-  
-  public static boolean start(RootDoc root) {
-    System.out.println(
-        IncludePublicAnnotationsStandardDoclet.class.getSimpleName());
-    RootDocProcessor.treatUnannotatedClassesAsPrivate = true;
-    return Standard.start(RootDocProcessor.process(root));
-  }
-  
-  public static int optionLength(String option) {
-    Integer length = StabilityOptions.optionLength(option);
-    if (length != null) {
-      return length;
-    }
-    return Standard.optionLength(option);
-  }
-  
-  public static boolean validOptions(String[][] options,
-      DocErrorReporter reporter) {
-    StabilityOptions.validOptions(options, reporter);
-    String[][] filteredOptions = StabilityOptions.filterOptions(options);
-    return Standard.validOptions(filteredOptions, reporter);
-  }
-}
diff --git 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/RootDocProcessor.java
 
b/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/RootDocProcessor.java
deleted file mode 100644
index 60c2a6f6e93..00000000000
--- 
a/hadoop-common-project/hadoop-annotations/src/main/java8/org/apache/hadoop/classification/tools/RootDocProcessor.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * 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.hadoop.classification.tools;
-
-import com.sun.javadoc.AnnotationDesc;
-import com.sun.javadoc.AnnotationTypeDoc;
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.ConstructorDoc;
-import com.sun.javadoc.Doc;
-import com.sun.javadoc.FieldDoc;
-import com.sun.javadoc.MethodDoc;
-import com.sun.javadoc.PackageDoc;
-import com.sun.javadoc.ProgramElementDoc;
-import com.sun.javadoc.RootDoc;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-import org.apache.hadoop.classification.InterfaceAudience;
-import org.apache.hadoop.classification.InterfaceStability;
-
-/**
- * Process the {@link RootDoc} by substituting with (nested) proxy objects that
- * exclude elements with Private or LimitedPrivate annotations.
- * <p>
- * Based on code from 
http://www.sixlegs.com/blog/java/exclude-javadoc-tag.html.
- */
-class RootDocProcessor {
-
-  static String stability = StabilityOptions.UNSTABLE_OPTION;
-  static boolean treatUnannotatedClassesAsPrivate = false;
-
-  public static RootDoc process(RootDoc root) {
-    return (RootDoc) process(root, RootDoc.class);
-  }
-
-  private static Object process(Object obj, Class<?> type) {
-    if (obj == null) {
-      return null;
-    }
-    Class<?> cls = obj.getClass();
-    if (cls.getName().startsWith("com.sun.")) {
-      return getProxy(obj);
-    } else if (obj instanceof Object[]) {
-      Class<?> componentType = type.isArray() ? type.getComponentType()
-          : cls.getComponentType();
-      Object[] array = (Object[]) obj;
-      Object[] newArray = (Object[]) Array.newInstance(componentType,
-          array.length);
-      for (int i = 0; i < array.length; ++i) {
-        newArray[i] = process(array[i], componentType);
-      }
-      return newArray;
-    }
-    return obj;
-  }
-
-  private static Map<Object, Object> proxies =
-    new WeakHashMap<Object, Object>();
-
-  private static Object getProxy(Object obj) {
-    Object proxy = proxies.get(obj);
-    if (proxy == null) {
-      proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(),
-        obj.getClass().getInterfaces(), new ExcludeHandler(obj));
-      proxies.put(obj, proxy);
-    }
-    return proxy;
-  }
-
-  private static class ExcludeHandler implements InvocationHandler {
-    private Object target;
-
-    public ExcludeHandler(Object target) {
-      this.target = target;
-    }
-
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] args)
-        throws Throwable {
-      String methodName = method.getName();
-      if (target instanceof Doc) {
-        if (methodName.equals("isIncluded")) {
-          Doc doc = (Doc) target;
-          return !exclude(doc) && doc.isIncluded();
-        }
-        if (target instanceof RootDoc) {
-          if (methodName.equals("classes")) {
-            return filter(((RootDoc) target).classes(), ClassDoc.class);
-          } else if (methodName.equals("specifiedClasses")) {
-            return filter(((RootDoc) target).specifiedClasses(), 
ClassDoc.class);
-          } else if (methodName.equals("specifiedPackages")) {
-            return filter(((RootDoc) target).specifiedPackages(), 
PackageDoc.class);
-          }
-        } else if (target instanceof ClassDoc) {
-          if (isFiltered(args)) {
-            if (methodName.equals("methods")) {
-              return filter(((ClassDoc) target).methods(true), 
MethodDoc.class);
-            } else if (methodName.equals("fields")) {
-              return filter(((ClassDoc) target).fields(true), FieldDoc.class);
-            } else if (methodName.equals("innerClasses")) {
-              return filter(((ClassDoc) target).innerClasses(true),
-                  ClassDoc.class);
-            } else if (methodName.equals("constructors")) {
-              return filter(((ClassDoc) target).constructors(true),
-                  ConstructorDoc.class);
-            }
-          } else {
-            if (methodName.equals("methods")) {
-              return filter(((ClassDoc) target).methods(true), 
MethodDoc.class);
-            }
-          }
-        } else if (target instanceof PackageDoc) {
-          if (methodName.equals("allClasses")) {
-            if (isFiltered(args)) {
-              return filter(((PackageDoc) target).allClasses(true),
-                  ClassDoc.class);
-            } else {
-              return filter(((PackageDoc) target).allClasses(), 
ClassDoc.class);
-            }
-          } else if (methodName.equals("annotationTypes")) {
-            return filter(((PackageDoc) target).annotationTypes(),
-                AnnotationTypeDoc.class);
-          } else if (methodName.equals("enums")) {
-            return filter(((PackageDoc) target).enums(),
-                ClassDoc.class);
-          } else if (methodName.equals("errors")) {
-            return filter(((PackageDoc) target).errors(),
-                ClassDoc.class);
-          } else if (methodName.equals("exceptions")) {
-            return filter(((PackageDoc) target).exceptions(),
-                ClassDoc.class);
-          } else if (methodName.equals("interfaces")) {
-            return filter(((PackageDoc) target).interfaces(),
-                ClassDoc.class);
-          } else if (methodName.equals("ordinaryClasses")) {
-            return filter(((PackageDoc) target).ordinaryClasses(),
-                ClassDoc.class);
-          }
-        }
-      }
-
-      if (args != null) {
-        if (methodName.equals("compareTo") || methodName.equals("equals")
-            || methodName.equals("overrides")
-            || methodName.equals("subclassOf")) {
-          args[0] = unwrap(args[0]);
-        }
-      }
-      try {
-        return process(method.invoke(target, args), method.getReturnType());
-      } catch (InvocationTargetException e) {
-        throw e.getTargetException();
-      }
-    }
-
-    private static boolean exclude(Doc doc) {
-      AnnotationDesc[] annotations = null;
-      if (doc instanceof ProgramElementDoc) {
-        annotations = ((ProgramElementDoc) doc).annotations();
-      } else if (doc instanceof PackageDoc) {
-        annotations = ((PackageDoc) doc).annotations();
-      }
-      if (annotations != null) {
-        for (AnnotationDesc annotation : annotations) {
-          String qualifiedTypeName = 
annotation.annotationType().qualifiedTypeName();
-          if (qualifiedTypeName.equals(
-              InterfaceAudience.Private.class.getCanonicalName())
-              || qualifiedTypeName.equals(
-              InterfaceAudience.LimitedPrivate.class.getCanonicalName())) {
-            return true;
-          }
-          if (stability.equals(StabilityOptions.EVOLVING_OPTION)) {
-            if (qualifiedTypeName.equals(
-                InterfaceStability.Unstable.class.getCanonicalName())) {
-              return true;
-            }
-          }
-          if (stability.equals(StabilityOptions.STABLE_OPTION)) {
-            if (qualifiedTypeName.equals(
-                InterfaceStability.Unstable.class.getCanonicalName())
-                || qualifiedTypeName.equals(
-                InterfaceStability.Evolving.class.getCanonicalName())) {
-              return true;
-            }
-          }
-        }
-        for (AnnotationDesc annotation : annotations) {
-          String qualifiedTypeName =
-              annotation.annotationType().qualifiedTypeName();
-          if (qualifiedTypeName.equals(
-              InterfaceAudience.Public.class.getCanonicalName())) {
-            return false;
-          }
-        }
-      }
-      if (treatUnannotatedClassesAsPrivate) {
-        return doc.isClass() || doc.isInterface() || doc.isAnnotationType();
-      }
-      return false;
-    }
-
-    private static Object[] filter(Doc[] array, Class<?> componentType) {
-      if (array == null || array.length == 0) {
-        return array;
-      }
-      List<Object> list = new ArrayList<Object>(array.length);
-      for (Doc entry : array) {
-        if (!exclude(entry)) {
-          list.add(process(entry, componentType));
-        }
-      }
-      return list.toArray((Object[]) Array.newInstance(componentType, list
-          .size()));
-    }
-
-    private Object unwrap(Object proxy) {
-      if (proxy instanceof Proxy)
-        return ((ExcludeHandler) Proxy.getInvocationHandler(proxy)).target;
-      return proxy;
-    }
-
-    private boolean isFiltered(Object[] args) {
-      return args != null && Boolean.TRUE.equals(args[0]);
-    }
-
-  }
-
-}
diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/pom.xml 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/pom.xml
index f236c8770d3..f8c7ad3d4b9 100644
--- a/hadoop-mapreduce-project/hadoop-mapreduce-client/pom.xml
+++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/pom.xml
@@ -246,7 +246,7 @@
                 <configuration>
                   <artifactItems>
                     <artifactItem>
-                      <groupId>jdiff</groupId>
+                      <groupId>io.github.zhtttylz</groupId>
                       <artifactId>jdiff</artifactId>
                       <version>${jdiff.version}</version>
                       <overWrite>false</overWrite>
diff --git a/hadoop-project-dist/pom.xml b/hadoop-project-dist/pom.xml
index 68d29e84fbf..f09a22f23c5 100644
--- a/hadoop-project-dist/pom.xml
+++ b/hadoop-project-dist/pom.xml
@@ -178,7 +178,7 @@
                 <configuration>
                   <artifactItems>
                     <artifactItem>
-                      <groupId>jdiff</groupId>
+                      <groupId>io.github.zhtttylz</groupId>
                       <artifactId>jdiff</artifactId>
                       <version>${jdiff.version}</version>
                       <overWrite>false</overWrite>
@@ -462,5 +462,30 @@
         </plugins>
       </build>
     </profile>
+    <profile>
+      <id>doclet-jdk17</id>
+      <activation>
+        <jdk>[17,)</jdk>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              
<doclet>org.apache.hadoop.classification.tools.ExcludePrivateAnnotationsStandardDoclet</doclet>
+              <docletArtifacts>
+                <docletArtifact>
+                  <groupId>org.apache.hadoop</groupId>
+                  <artifactId>hadoop-annotations</artifactId>
+                  <version>${hadoop.version}</version>
+                </docletArtifact>
+              </docletArtifacts>
+              <useStandardDocletOptions>true</useStandardDocletOptions>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
   </profiles>
 </project>
diff --git a/hadoop-project/pom.xml b/hadoop-project/pom.xml
index cd83d2ae9a9..5d07b0228d5 100644
--- a/hadoop-project/pom.xml
+++ b/hadoop-project/pom.xml
@@ -45,7 +45,7 @@
 
     <!-- These 2 versions are defined here because they are used -->
     <!-- JDIFF generation from embedded ant in the antrun plugin -->
-    <jdiff.version>1.0.9</jdiff.version>
+    <jdiff.version>1.1.2-hadoop</jdiff.version>
     <!-- Version number for xerces used by JDiff -->
     <xerces.jdiff.version>2.12.2</xerces.jdiff.version>
 
@@ -268,7 +268,7 @@
         <scope>test</scope>
       </dependency>
       <dependency>
-        <groupId>jdiff</groupId>
+        <groupId>io.github.zhtttylz</groupId>
         <artifactId>jdiff</artifactId>
         <version>${jdiff.version}</version>
       </dependency>
diff --git a/hadoop-yarn-project/hadoop-yarn/pom.xml 
b/hadoop-yarn-project/hadoop-yarn/pom.xml
index db4a50542fd..7c216f90043 100644
--- a/hadoop-yarn-project/hadoop-yarn/pom.xml
+++ b/hadoop-yarn-project/hadoop-yarn/pom.xml
@@ -151,7 +151,7 @@
                 <configuration>
                   <artifactItems>
                     <artifactItem>
-                      <groupId>jdiff</groupId>
+                      <groupId>io.github.zhtttylz</groupId>
                       <artifactId>jdiff</artifactId>
                       <version>${jdiff.version}</version>
                       <overWrite>false</overWrite>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to