diff --git a/api-checker/README.md b/api-checker/README.md new file mode 100644 index 0000000000000..7db9851dde31f --- /dev/null +++ b/api-checker/README.md @@ -0,0 +1,90 @@ +# Kafka API-checker plugins + +This is a separate Gradle build (composite-included from the root `settings.gradle` via +`pluginManagement { includeBuild 'api-checker' }`) that produces the KIP-1265 API checkers. +Living outside Kafka's main build keeps the Maven runtime dependencies off the main-build +classpath and lets each published artifact carry only the classes its consumers need. + +| Subproject | Publishes | Audience | +|---|---|---| +| `:core` | `org.apache.kafka:kafka-api-checker-core` | Shared scanner + validator + reporter (ASM only). Both plugin jars depend on it. | +| `:gradle-plugins` | `org.apache.kafka:kafka-internal-api-checker-gradle-plugin` + plugin markers for `org.apache.kafka.public-api-checker` and `org.apache.kafka.internal-api-checker` | The Kafka-internal producer-side checker and the published consumer-side Gradle checker. | +| `:maven-plugin` | `org.apache.kafka:kafka-internal-api-checker-maven-plugin` | Maven equivalent of the consumer-side checker. | + +End-user documentation (Gradle/Maven snippets, `@SuppressKafkaInternalApiUsage`, +audience-inheritance rules) lives at +[`docs/apis/internal-api-checker.md`](../docs/apis/internal-api-checker.md). The notes +below cover building, testing, and publishing the plugins themselves. + +## Build + +```bash +./gradlew :api-checker:core:build :api-checker:gradle-plugins:build :api-checker:maven-plugin:build +``` + +## Test + +```bash +./gradlew :api-checker:core:test :api-checker:gradle-plugins:test +``` + +`:gradle-plugins:test` includes a Gradle TestKit end-to-end test that applies the +`org.apache.kafka.internal-api-checker` plugin to a synthetic consumer project. + +## Publish + +Each subproject's `publish` task stages to the URL passed via `-PmavenUrl` (with +`-PmavenUsername` / `-PmavenPassword` for credentials). The version is read from the +repo-root `gradle.properties`, so `release.py`'s existing `updateVersion` call sets it +automatically. `-PkafkaPluginsVersion=…` overrides for one-off out-of-band publishes. + +```bash +# Stage to ASF Nexus alongside the rest of an AK release +./gradlew :api-checker:core:publish \ + :api-checker:gradle-plugins:publish \ + :api-checker:maven-plugin:publish \ + -PmavenUrl=$ASF_NEXUS_STAGING_URL \ + -PmavenUsername=$NEXUS_USER \ + -PmavenPassword=$NEXUS_PASS + +# Local smoke-test +./gradlew :api-checker:core:publishToMavenLocal \ + :api-checker:gradle-plugins:publishToMavenLocal \ + :api-checker:maven-plugin:publishToMavenLocal +``` + +The five published coordinates: + +- `org.apache.kafka:kafka-api-checker-core:$KAFKA_VERSION` — shared scanner library. +- `org.apache.kafka:kafka-internal-api-checker-gradle-plugin:$KAFKA_VERSION` — Gradle plugin + implementation jar (consumed by the marker poms). +- `org.apache.kafka.internal-api-checker:org.apache.kafka.internal-api-checker.gradle.plugin:$KAFKA_VERSION` — + marker pom for `plugins { id 'org.apache.kafka.internal-api-checker' }`. +- `org.apache.kafka.public-api-checker:org.apache.kafka.public-api-checker.gradle.plugin:$KAFKA_VERSION` — + marker pom for the producer-side checker. (Kafka-internal use, but published from the + same module for consistency.) +- `org.apache.kafka:kafka-internal-api-checker-maven-plugin:$KAFKA_VERSION` — Maven plugin + (packaging `maven-plugin`). + +## Layout + +``` +api-checker/ +├── settings.gradle # declares the three subprojects +├── build.gradle # group / version / signing / common publishing config +├── core/ +│ ├── build.gradle # ASM dep; published as kafka-api-checker-core +│ └── src/ +│ ├── main/java/.../apicheck/ # scanner, validators, reporter +│ ├── test/java/.../apicheck/ # unit tests +│ └── testFixtures/java/.../apicheck/ # AsmClassFactory, TempJarBuilder +│ # — re-used by :gradle-plugins' tests +├── gradle-plugins/ +│ ├── build.gradle # java-gradle-plugin; depends on :core +│ └── src/{main,test}/java/.../gradle/ # Plugin/Task/Extension × 2 +└── maven-plugin/ + ├── build.gradle # Maven deps; templates plugin.xml at processResources + └── src/main/ + ├── java/.../maven/KafkaInternalApiCheckerMojo.java + └── resources/META-INF/maven/plugin.xml +``` diff --git a/api-checker/build.gradle b/api-checker/build.gradle new file mode 100644 index 0000000000000..b5e54456809ba --- /dev/null +++ b/api-checker/build.gradle @@ -0,0 +1,92 @@ +/* + * 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. + */ + +// Shared configuration for the api-checker included build. Lives outside Kafka's main +// settings tree so its Maven dependencies (in :maven-plugin) don't end up on every +// developer's main-build classpath, and so each published artifact carries only the classes +// its consumers need. + +// Default the published version to the same string as the rest of Kafka (gradle.properties +// at the repo root). release.py's `updateVersion` task writes that file, so the included +// build's artifacts ship under the AK release version automatically. `-PkafkaPluginsVersion=…` +// overrides for one-off out-of-band publishes. +def rootGradleProps = new Properties() +def rootGradlePropsFile = file('../gradle.properties') +if (rootGradlePropsFile.exists()) { + rootGradlePropsFile.withInputStream { rootGradleProps.load(it) } +} +def kafkaVersion = providers.gradleProperty('kafkaPluginsVersion') + .orElse(providers.provider { rootGradleProps.getProperty('version') }) + .orElse('1.0.0-SNAPSHOT') + +allprojects { + group = 'org.apache.kafka' + version = kafkaVersion.get() + + repositories { + gradlePluginPortal() + mavenCentral() + } +} + +subprojects { + apply plugin: 'java-library' + apply plugin: 'maven-publish' + apply plugin: 'signing' + apply plugin: 'checkstyle' + + java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + // Maven Central requires sources + javadoc jars alongside every artifact. + withSourcesJar() + withJavadocJar() + } + + test { + useJUnitPlatform() + } + + checkstyle { + toolVersion = '12.3.1' + configDirectory = file("$rootDir/../checkstyle") + configProperties = [importControlFile: 'import-control-api-checker.xml'] + } + + publishing { + repositories { + // Mirrors the root Kafka project's publishing.repositories block — credentials + // come from ~/.gradle/gradle.properties via the same -PmavenUrl / -PmavenUsername / + // -PmavenPassword properties release.py uses. + maven { + url = project.hasProperty('mavenUrl') ? project.mavenUrl : '' + credentials { + username = project.hasProperty('mavenUsername') ? project.mavenUsername : '' + password = project.hasProperty('mavenPassword') ? project.mavenPassword : '' + } + } + } + } + + def skipSigning = project.hasProperty('skipSigning') && skipSigning.toBoolean() + def shouldSign = !skipSigning && !version.toString().endsWith('SNAPSHOT') + if (shouldSign) { + signing { + sign publishing.publications + } + } +} diff --git a/api-checker/core/build.gradle b/api-checker/core/build.gradle new file mode 100644 index 0000000000000..dbf0b678db98b --- /dev/null +++ b/api-checker/core/build.gradle @@ -0,0 +1,79 @@ +/* + * 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. + */ + +// Shared scanner + validator + reporter for the KIP-1265 API checkers. Both the Gradle +// plugin and the Maven plugin depend on this module — neither carries the bytecode +// scanner classes themselves any more, so the published Gradle jar no longer drags Maven +// classes (and vice versa). + +apply plugin: 'java-test-fixtures' + +dependencies { + // ASM is the entire production dependency footprint. No Gradle, no Maven. + // + // ASM versions cap the JDK class-file major version they can parse. 9.6 covers up to + // Java 21 (class-file 65). If Kafka starts compiling against a newer JDK whose major + // exceeds what this ASM release knows about, the scanner will throw + // `IllegalArgumentException: Unsupported class file major version N` on encountering + // a fresh bytecode file. Bump in lockstep with the project's max-supported compile JDK. + api 'org.ow2.asm:asm:9.6' + api 'org.slf4j:slf4j-api:2.0.16' + + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.2' + testImplementation 'org.junit.platform:junit-platform-launcher:1.9.2' + + // ASM-based class-file builders used by every checker test in the included build. + // Exposed as test-fixtures so the gradle-plugins module's tests can pull them in via + // `testImplementation(testFixtures(project(':core')))` without us re-publishing them + // as a separate "tests" classifier artifact. + testFixturesImplementation 'org.ow2.asm:asm:9.6' +} + +publishing { + publications { + coreJar(MavenPublication) { + artifactId = 'kafka-api-checker-core' + from components.java + + pom { + name = 'Apache Kafka API Checker Core' + description = 'Bytecode scanner and reporter shared by the KIP-1265 Gradle and Maven plugins' + url = 'https://kafka.apache.org' + + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = 'apache-kafka' + name = 'Apache Kafka Team' + email = 'dev@kafka.apache.org' + } + } + scm { + connection = 'scm:git:https://github.com/apache/kafka.git' + developerConnection = 'scm:git:https://github.com/apache/kafka.git' + url = 'https://github.com/apache/kafka' + } + } + } + } +} diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/ApiSurface.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ApiSurface.java new file mode 100644 index 0000000000000..b5d1dab3d7bf5 --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ApiSurface.java @@ -0,0 +1,169 @@ +/* + * 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.kafka.apicheck; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; + +/** + * The Kafka public-API surface, resolved from one project-jars scan. Immutable; consumed by the + * cascade and javadoc validators. Built via {@link ApiSurfaceScanner}. + * + *

All lookup methods accept a class name in either binary ({@code Outer$Inner}) or dotted + * ({@code Outer.Inner}) form — callers don't need to know which form the surface stores. The two + * iteration sets ({@link #effectivePublic()} and {@link #directPublic()}) return {@link ClassFacts} + * directly so callers never juggle name strings. + */ +final class ApiSurface { + + /** Every class that is effectively {@code @Public} (direct or inherited), regardless of visibility. */ + private final Set effectivePublic; + /** Classes carrying a direct {@code @InterfaceAudience.Public} — drives the MISSING_JAVADOC iteration. */ + private final Set directPublic; + private final Map byDottedName; + private final Map jarByDottedName; + + private ApiSurface(Builder b) { + this.effectivePublic = Set.copyOf(b.effectivePublic); + this.directPublic = Set.copyOf(b.directPublic); + this.byDottedName = Map.copyOf(b.byDottedName); + this.jarByDottedName = Map.copyOf(b.jarByDottedName); + } + + /** + * Every class that is effectively {@code @Public} (direct or inherited). Cascade iteration + * filters this further on {@link ClassFacts#isExternallyVisible()} — private/package-private + * nested classes inherit the audience but their methods aren't reachable to consumers. + */ + Set effectivePublic() { + return effectivePublic; + } + + /** Classes carrying a *direct* {@code @InterfaceAudience.Public}. Drives the MISSING_JAVADOC check. */ + Set directPublic() { + return directPublic; + } + + /** Look up facts by either binary or dotted name. Returns {@code null} if not in any scanned jar. */ + ClassFacts factsOf(String name) { + return byDottedName.get(normalize(name)); + } + + /** @return the jar that contained the class, or {@code null} if not in any scanned jar. */ + File jarOf(String name) { + return jarByDottedName.get(normalize(name)); + } + + /** + * True iff the class is effectively {@code @Public} — directly or via enclosing-class + * inheritance, regardless of source-level access. Walks the enclosing chain just like + * {@link #isDeprecated}; explicit {@code @InterfaceAudience.Private} on a nested class + * overrides an inherited {@code @Public}. + */ + boolean isEffectivelyPublic(String name) { + ClassFacts hit = findInChain(name, f -> f.isPrivate() || f.isPublic()); + return hit != null && hit.isPublic(); + } + + /** + * True iff the class — or any enclosing class — carries {@code @Deprecated}. Deprecation + * propagates through nesting so a nested class of a {@code @Deprecated} outer is itself + * out of scope on both validation sides (mirrors the {@code @Public} inheritance model). + */ + boolean isDeprecated(String name) { + return findInChain(name, ClassFacts::isDeprecated) != null; + } + + /** + * Walk the enclosing chain and return the first {@link ClassFacts} for which {@code stopAt} + * is true, or {@code null} if nothing matches before we reach the top-level class. + * + *

When the current level resolves to {@link ClassFacts}, stepping uses + * {@link ClassFacts#enclosingName} (works for both binary and dotted-form input). When it + * doesn't — e.g. an anonymous intermediate like {@code Outer$1} that + * {@link ApiSurfaceScanner#isSyntheticOrAnonymous} dropped — we fall back to lexical + * {@code $}-stripping so the chain continues past the gap. That fallback matches the + * scanner's own {@code resolveEffectiveAudience} so the two walks agree on what counts as + * an effective audience. + */ + private ClassFacts findInChain(String name, Predicate stopAt) { + String current = name; + while (current != null) { + ClassFacts facts = factsOf(current); + if (facts != null) { + if (stopAt.test(facts)) return facts; + current = facts.enclosingName(); + } else { + String parent = ClassFacts.parentBinaryName(current); + if (parent == null) return null; + current = parent; + } + } + return null; + } + + /** + * Treat {@code $} purely as a Java-style nesting separator. This is correct for Java + * source-level nested classes and for the {@code @InterfaceAudience.Public} surface (which + * is itself defined in plain Java). It's a known oversimplification for Scala/Kotlin + * compiled output — e.g. Scala companion-object names ({@code Foo$}) or anonymous-function + * synthetics ({@code Foo$$anonfun$1}) — but those compiler-generated symbols are not part + * of the Public surface, so any normalization confusion they cause stays below the + * checker's prefix gate. + */ + private static String normalize(String name) { + return name.indexOf('$') < 0 ? name : name.replace('$', '.'); + } + + static Builder builder() { + return new Builder(); + } + + /** Accumulator used by {@link ApiSurfaceScanner}; {@link #build()} freezes into an {@link ApiSurface}. */ + static final class Builder { + private final Set effectivePublic = new HashSet<>(); + private final Set directPublic = new HashSet<>(); + private final Map byDottedName = new HashMap<>(); + private final Map jarByDottedName = new HashMap<>(); + + /** Record a class's facts and the jar it came from. First jar wins for duplicates. */ + Builder recordClass(ClassFacts facts, File jar) { + byDottedName.put(facts.dottedName(), facts); + jarByDottedName.putIfAbsent(facts.dottedName(), jar); + return this; + } + + /** Add a class that is effectively {@code @Public} (direct or inherited), any visibility. */ + Builder addEffectivePublic(ClassFacts facts) { + effectivePublic.add(facts); + return this; + } + + Builder addDirectPublic(ClassFacts facts) { + directPublic.add(facts); + return this; + } + + ApiSurface build() { + return new ApiSurface(this); + } + } +} \ No newline at end of file diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/ApiSurfaceScanner.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ApiSurfaceScanner.java new file mode 100644 index 0000000000000..5a991c51a9419 --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ApiSurfaceScanner.java @@ -0,0 +1,225 @@ +/* + * 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.kafka.apicheck; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * Builds an {@link ApiSurface} from a set of project jars in a single two-pass scan: + *

    + *
  1. Read each class's direct bytecode facts (annotations, source-level access).
  2. + *
  3. Walk every class's enclosing-class chain (Hadoop-style inheritance) to resolve effective + * audience and assemble the derived dotted-name sets in the surface.
  4. + *
+ * + *

Reads bytecode metadata via ASM rather than the classloader, so a class with broken + * transitive deps (gRPC stubs, telemetry shims, …) doesn't trip {@code LinkageError} — + * annotation descriptors live in the constant pool, no linking required. + */ +final class ApiSurfaceScanner { + + // Bytecode descriptors used to identify class-level annotations the checker cares about. + private static final String PUBLIC_API_DESCRIPTOR = + "Lorg/apache/kafka/common/annotation/InterfaceAudience$Public;"; + private static final String PRIVATE_API_DESCRIPTOR = + "Lorg/apache/kafka/common/annotation/InterfaceAudience$Private;"; + private static final String DEPRECATED_DESCRIPTOR = "Ljava/lang/Deprecated;"; + + private ApiSurfaceScanner() {} + + /** + * Scan the project's own jars and any reference jars (sibling Kafka modules it depends on) + * and return an immutable surface. + * + *

Reference-jar classes contribute to {@link ApiSurface#factsOf} lookups and the + * membership set behind {@link ApiSurface#isEffectivelyPublic} so cross-module + * {@code @Public} references resolve correctly, but they do NOT take part in this + * project's MISSING_JAVADOC iteration or cascade iteration — each module checks its + * own surface. + */ + static ApiSurface scan(List projectJars, List referenceJars) throws IOException { + ApiSurface.Builder surface = ApiSurface.builder(); + Map byBinaryName = new HashMap<>(); + Set projectJarDottedNames = new HashSet<>(); + + // Pass 1 — read facts for every in-scope class. Project-owned classes get tracked so + // pass 2 can keep them out of reference-only iteration sets. + scanJars(projectJars, byBinaryName, surface, projectJarDottedNames::add); + scanJars(referenceJars, byBinaryName, surface, name -> { }); + + // Pass 2 — resolve inheritance and populate the surface's derived sets. Deprecated + // classes are out of scope on both validation sides; the surface answers + // {@link ApiSurface#isDeprecated} directly from the per-class facts so no separate + // deprecated set is needed here. + for (ClassFacts facts : byBinaryName.values()) { + if (facts.isDeprecated() || !projectJarDottedNames.contains(facts.dottedName())) continue; + if (facts.isPublic()) { + surface.addDirectPublic(facts); + } + if (resolveEffectiveAudience(facts.binaryName(), byBinaryName) == DirectAudience.PUBLIC) { + // Owned effective-Public classes all go into the surface — cross-module + // @Public references resolve via {@link ApiSurface#isEffectivelyPublic} which + // walks the enclosing chain. Reference-jar classes don't need to be added + // here: they're validated by their own module's task. + // + // Iteration consumers (CascadeValidator) filter on + // {@link ClassFacts#isExternallyVisible()} at the call site — private nested + // classes inherit the audience but their methods/ctors aren't reachable to + // consumers and shouldn't be cascade-walked. + surface.addEffectivePublic(facts); + } + } + + return surface.build(); + } + + /** Backwards-compatible overload for callers that don't need reference jars (consumer-side scan). */ + static ApiSurface scan(List projectJars) throws IOException { + return scan(projectJars, java.util.Collections.emptyList()); + } + + private static void scanJars(List jars, Map byBinaryName, + ApiSurface.Builder surface, + java.util.function.Consumer markOwned) throws IOException { + for (File jar : jars) { + try (JarFile jarFile = new JarFile(jar)) { + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (!entry.getName().endsWith(".class")) continue; + + String binaryName = entry.getName() + .replace('/', '.') + .replaceAll(".class$", ""); + if (binaryName.endsWith("package-info") || binaryName.endsWith("module-info")) continue; + if (!binaryName.startsWith("org.apache.kafka.")) continue; + // Anonymous / local / synthetic classes are never part of the public API surface, + // but would otherwise inherit @Public from an enclosing class under the + // Hadoop-style inheritance rule and trip cascade checks. + if (isSyntheticOrAnonymous(binaryName)) continue; + // First jar wins for cross-jar duplicates — project jars are scanned first + // so they keep ownership over a class also present in a reference jar. + if (byBinaryName.containsKey(binaryName)) continue; + + ClassFacts facts = readClassFacts(jarFile, entry, binaryName); + byBinaryName.put(binaryName, facts); + surface.recordClass(facts, jar); + markOwned.accept(facts.dottedName()); + } + } + } + } + + /** Read a class file's bytecode facts via ASM (jar-entry variant). */ + static ClassFacts readClassFacts(JarFile jar, JarEntry entry, String binaryName) throws IOException { + try (InputStream in = jar.getInputStream(entry)) { + return readClassFactsFromStream(in, binaryName); + } + } + + /** Read a class file's bytecode facts via ASM (stream variant — used for classpath lookups). */ + static ClassFacts readClassFactsFromStream(InputStream in, String binaryName) throws IOException { + ClassFacts.Builder builder = ClassFacts.builder(binaryName); + String internalName = binaryName.replace('.', '/'); + ClassReader reader = new ClassReader(in); + reader.accept(new ClassVisitor(Opcodes.ASM9) { + @Override + public void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + builder.sourceAccess(access); // top-level access; overridden below for nested + } + + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + if (PUBLIC_API_DESCRIPTOR.equals(descriptor)) { + builder.addFlag(ClassFacts.Flag.PUBLIC_API); + } else if (PRIVATE_API_DESCRIPTOR.equals(descriptor)) { + builder.addFlag(ClassFacts.Flag.PRIVATE_API); + } else if (DEPRECATED_DESCRIPTOR.equals(descriptor)) { + builder.addFlag(ClassFacts.Flag.DEPRECATED); + } + return null; + } + + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + if (internalName.equals(name)) { + // For nested classes the InnerClasses entry holds the real source-level + // access; the class header's ACC_PUBLIC is a compiler artefact. + builder.sourceAccess(access); + } + } + }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + return builder.build(); + } + + /** + * @return true if the binary name encodes an anonymous, local, or compiler-synthetic class + * (e.g. {@code Outer$1}, {@code Outer$1$Inner}, {@code Outer$$Lambda$N}). Such classes + * are never part of the public API surface. + */ + private static boolean isSyntheticOrAnonymous(String binaryName) { + if (binaryName.contains("$$")) return true; // lambdas / synthetic accessor classes + int dollar = binaryName.indexOf('$'); + while (dollar >= 0) { + int nextDollar = binaryName.indexOf('$', dollar + 1); + int end = nextDollar < 0 ? binaryName.length() : nextDollar; + // A segment that starts with a digit is an anonymous or local class. + if (end > dollar + 1 && Character.isDigit(binaryName.charAt(dollar + 1))) { + return true; + } + dollar = nextDollar; + } + return false; + } + + /** + * Walk the enclosing-class chain (by stripping {@code $}-segments from the binary name) and + * return the audience of the nearest class with an explicit annotation. Default is + * {@code Private} per the KIP. Uses the same {@link ClassFacts#parentBinaryName} stepping + * rule as {@link ApiSurface#findInChain} so the two walks agree on missing intermediates. + */ + private static DirectAudience resolveEffectiveAudience(String binaryName, Map byBinaryName) { + String name = binaryName; + while (name != null) { + ClassFacts facts = byBinaryName.get(name); + if (facts != null) { + if (facts.isPublic()) return DirectAudience.PUBLIC; + if (facts.isPrivate()) return DirectAudience.PRIVATE; + } + name = ClassFacts.parentBinaryName(name); + } + return DirectAudience.PRIVATE; + } + + private enum DirectAudience { PUBLIC, PRIVATE } +} \ No newline at end of file diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/CascadeValidator.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/CascadeValidator.java new file mode 100644 index 0000000000000..6282f895cc2b8 --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/CascadeValidator.java @@ -0,0 +1,372 @@ +/* + * 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.kafka.apicheck; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.signature.SignatureReader; +import org.objectweb.asm.signature.SignatureVisitor; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * Checks that no public method of any effectively-{@code @Public} class leaks an internal Kafka + * type through its return type, parameter types, or declared exceptions. Each finding either + * lands in {@link CheckResult#violations()} (a real failure) or in + * {@link CheckResult#suppressions()} (silenced by a class- or method-level + * {@code @SuppressKafkaInternalApiUsage} — the reason is captured so reviewers can audit every + * escape hatch on every build). + * + *

Reads bytecode directly via ASM rather than reflecting on a loaded {@code Class}, which + * sidesteps {@code LinkageError} / {@code NoClassDefFoundError} from broken transitive deps + * (gRPC stubs, telemetry shims, etc.). The same robustness property as {@link ApiSurfaceScanner}. + */ +final class CascadeValidator { + + /** {@code @SuppressKafkaInternalApiUsage} — the escape hatch for known cascade leaks pending review. */ + private static final String SUPPRESS_DESCRIPTOR = + "Lorg/apache/kafka/common/annotation/SuppressKafkaInternalApiUsage;"; + + private CascadeValidator() {} + + static CheckResult validate(ApiSurface surface) throws IOException { + List violations = new ArrayList<>(); + List suppressions = new ArrayList<>(); + // Group by jar so each archive is opened once. Private/package-private nested classes + // inherit the audience but their methods and ctors aren't reachable to consumers, so + // cascade-walking them would just produce noise on internal helpers — filter them out + // before grouping. + Map> classesByJar = new LinkedHashMap<>(); + for (ClassFacts cls : surface.effectivePublic()) { + if (!cls.isExternallyVisible()) continue; + File jar = surface.jarOf(cls.binaryName()); + if (jar == null) continue; + classesByJar.computeIfAbsent(jar, j -> new ArrayList<>()).add(cls); + } + for (Map.Entry> e : classesByJar.entrySet()) { + try (JarFile jar = new JarFile(e.getKey())) { + for (ClassFacts cls : e.getValue()) { + checkClass(cls, jar, surface, violations, suppressions); + } + } + } + return new CheckResult(violations, suppressions); + } + + private static void checkClass(ClassFacts cls, JarFile jar, ApiSurface surface, + List violations, + List suppressions) throws IOException { + String entryPath = cls.binaryName().replace('.', '/') + ".class"; + JarEntry entry = jar.getJarEntry(entryPath); + if (entry == null) return; + try (InputStream in = jar.getInputStream(entry)) { + ClassReader reader = new ClassReader(in); + reader.accept(new CascadeClassVisitor(cls, surface, violations, suppressions), + ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + } + } + + /** + * Drives the cascade check for a single class: validates the class header (extends/implements + * + generic supertype args), then dispatches to per-method and per-field visitors that buffer + * findings so a member-level {@code @SuppressKafkaInternalApiUsage} can divert them after the + * fact. + */ + private static final class CascadeClassVisitor extends ClassVisitor { + private final ClassFacts cls; + private final ApiSurface surface; + private final List violations; + private final List suppressions; + /** Reason from a class-level {@code @SuppressKafkaInternalApiUsage}, or null. */ + private String classSuppressionReason; + /** + * Buffer extends/implements violations until {@link #visitEnd} so the + * class-level {@code @SuppressKafkaInternalApiUsage} (visited after the class + * header in ASM's event order) can divert them to suppressions if present. + */ + private final List headerBuffered = new ArrayList<>(); + + CascadeClassVisitor(ClassFacts cls, ApiSurface surface, + List violations, + List suppressions) { + super(Opcodes.ASM9); + this.cls = cls; + this.surface = surface; + this.violations = violations; + this.suppressions = suppressions; + } + + @Override + public void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + // The class header itself leaks a non-public type if the @Public class + // extends or implements an internal Kafka type the consumer can name. + if (superName != null && !"java/lang/Object".equals(superName)) { + checkSupertype(superName.replace('/', '.'), + "Public class extends non-public API type"); + } + if (interfaces != null) { + for (String iface : interfaces) { + checkSupertype(iface.replace('/', '.'), + "Public class implements non-public API type"); + } + } + // Generic supertype + interface type arguments live in the signature. + // Walk via the supertype-aware path so package-private intermediates are + // skipped just like the direct extends/implements check above. + if (signature != null) { + new SignatureReader(signature).accept(new SignatureVisitor(Opcodes.ASM9) { + @Override + public void visitClassType(String typeName) { + checkSupertype(typeName.replace('/', '.'), + "Public class header signature exposes non-public API type"); + } + }); + } + } + + /** + * Supertype cascade is stricter than the method/field cascade: package-private + * supertypes aren't a real leak because a consumer can't even name + * them from outside the package (no {@code instanceof}, no downcast). Skip + * those; otherwise fall through to the same cascade rule as everywhere else. + */ + private void checkSupertype(String binaryName, String message) { + ClassFacts target = surface.factsOf(binaryName); + if (target != null && !target.isExternallyVisible()) return; + checkBinaryReference(binaryName, "INVALID_SUPERTYPE", message, + cls.binaryName(), null, surface, headerBuffered); + } + + @Override + public void visitEnd() { + if (classSuppressionReason != null) { + for (PublicApiViolation original : headerBuffered) { + suppressions.add(asSuppression(original, classSuppressionReason)); + } + } else { + violations.addAll(headerBuffered); + } + } + + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + if (SUPPRESS_DESCRIPTOR.equals(descriptor)) { + return new ReasonCaptureVisitor(r -> classSuppressionReason = r); + } + return null; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, + String signature, String[] exceptions) { + // KIP-1265: a Public class's externally-visible methods (public + protected, + // since protected members are reachable to subclasses of an extensible Public + // class) must not leak non-public types. + if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) return null; + // Bridge/synthetic methods are compiler-generated and never source-level API. + if ((access & (Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC)) != 0) return null; + + // Buffer would-be violations and route them in visitEnd, because the method's + // own @SuppressKafkaInternalApiUsage is visited *after* visitMethod returns. + List buffered = new ArrayList<>(); + checkAsmType(Type.getReturnType(descriptor), "INVALID_RETURN_TYPE", + "Public method returns non-public API type", + cls.binaryName(), name, surface, buffered); + for (Type argType : Type.getArgumentTypes(descriptor)) { + checkAsmType(argType, "INVALID_PARAMETER_TYPE", + "Public method has non-public API parameter type", + cls.binaryName(), name, surface, buffered); + } + if (exceptions != null) { + for (String excInternal : exceptions) { + checkBinaryReference(excInternal.replace('/', '.'), + "INVALID_EXCEPTION_TYPE", + "Public method declares non-public API exception type", + cls.binaryName(), name, surface, buffered); + } + } + // Generic type arguments (e.g. Map) live in the + // signature, not the erased descriptor — walk them too so the cascade + // catches leaks the type-erasure layer would otherwise hide. + collectSignatureRefs(signature, "INVALID_PARAMETER_TYPE", + "Public method signature exposes non-public API type", + cls.binaryName(), name, surface, buffered); + + return new BufferedMemberVisitor(buffered); + } + + @Override + public FieldVisitor visitField(int access, String name, String descriptor, + String signature, Object value) { + // KIP-1265 names field types explicitly: a Public class's externally-visible + // fields (public + protected) must not expose non-public types either. + if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) return null; + if ((access & Opcodes.ACC_SYNTHETIC) != 0) return null; + + // Buffer the would-be violation and route it in visitEnd, because the + // field's own @SuppressKafkaInternalApiUsage is visited *after* visitField. + List buffered = new ArrayList<>(); + checkAsmType(Type.getType(descriptor), "INVALID_FIELD_TYPE", + "Public field exposes non-public API type", + cls.binaryName(), name, surface, buffered); + // Walk the generic field signature too — `List` etc. is + // erased to plain List in the descriptor. + collectSignatureRefs(signature, "INVALID_FIELD_TYPE", + "Public field signature exposes non-public API type", + cls.binaryName(), name, surface, buffered); + + return new BufferedFieldVisitor(buffered); + } + + /** + * Drains {@code buffered} into either {@link #violations} or {@link #suppressions} after + * the member's own {@code @SuppressKafkaInternalApiUsage} (if any) has been seen. Falls + * back to the class-level suppression reason when the member doesn't carry its own. + */ + private void flush(List buffered, String memberReason) { + String reason = memberReason != null ? memberReason : classSuppressionReason; + if (reason != null) { + for (PublicApiViolation original : buffered) { + suppressions.add(asSuppression(original, reason)); + } + } else { + violations.addAll(buffered); + } + } + + /** MethodVisitor that captures a method-level suppression reason and flushes on visitEnd. */ + private final class BufferedMemberVisitor extends MethodVisitor { + private final List buffered; + private String reason; + + BufferedMemberVisitor(List buffered) { + super(Opcodes.ASM9); + this.buffered = buffered; + } + + @Override + public AnnotationVisitor visitAnnotation(String d, boolean v) { + if (SUPPRESS_DESCRIPTOR.equals(d)) { + return new ReasonCaptureVisitor(r -> reason = r); + } + return null; + } + + @Override + public void visitEnd() { + flush(buffered, reason); + } + } + + /** FieldVisitor that captures a field-level suppression reason and flushes on visitEnd. */ + private final class BufferedFieldVisitor extends FieldVisitor { + private final List buffered; + private String reason; + + BufferedFieldVisitor(List buffered) { + super(Opcodes.ASM9); + this.buffered = buffered; + } + + @Override + public AnnotationVisitor visitAnnotation(String d, boolean v) { + if (SUPPRESS_DESCRIPTOR.equals(d)) { + return new ReasonCaptureVisitor(r -> reason = r); + } + return null; + } + + @Override + public void visitEnd() { + flush(buffered, reason); + } + } + } + + /** + * Walk a generic JVM signature and route each referenced class type through the cascade + * check. {@code signature} is the optional generic descriptor ASM hands to + * {@code visitMethod}/{@code visitField}; it's null for non-generic members. + */ + private static void collectSignatureRefs(String signature, String violationType, String message, + String owner, String memberName, ApiSurface surface, + List violations) { + if (signature == null) return; + new SignatureReader(signature).accept(new SignatureVisitor(Opcodes.ASM9) { + @Override + public void visitClassType(String name) { + checkBinaryReference(name.replace('/', '.'), + violationType, message, owner, memberName, surface, violations); + } + }); + } + + /** Recurse through array element types to find the concrete reference type, then check it. */ + private static void checkAsmType(Type type, String violationType, String message, + String owner, String methodName, ApiSurface surface, + List violations) { + if (type.getSort() == Type.ARRAY) { + checkAsmType(type.getElementType(), violationType, message, owner, methodName, surface, violations); + } else if (type.getSort() == Type.OBJECT) { + // Type.getClassName() returns the binary form (e.g. "org.apache.kafka.X$Y"). + checkBinaryReference(type.getClassName(), violationType, message, owner, methodName, surface, violations); + } + } + + /** + * Apply the cascade rule to one referenced type. The reference is a violation iff it is + * in {@code org.apache.kafka.*}, not deprecated, and not in the surface's + * effective-Public-dotted set. + */ + private static void checkBinaryReference(String binaryName, String violationType, String message, + String owner, String methodName, ApiSurface surface, + List violations) { + if (!binaryName.startsWith("org.apache.kafka.")) return; + if (surface.isDeprecated(binaryName)) return; + if (surface.isEffectivelyPublic(binaryName)) return; + violations.add(new PublicApiViolation(owner, violationType, message + ": " + binaryName, methodName)); + } + + /** + * Render a would-be violation as a suppression entry that the reporter prints in the + * "Suppressions" section. The reason from the {@code @SuppressKafkaInternalApiUsage} + * annotation is appended so reviewers can audit every escape hatch on every build. + */ + private static PublicApiViolation asSuppression(PublicApiViolation original, String reason) { + String prettyReason = reason.isEmpty() ? PublicApiViolation.NO_REASON_MARKER : reason; + String description = "Suppressed " + original.getViolationType() + " in " + + original.getClassName() + "#" + original.getMemberName() + + " — " + original.getDescription() + + " — reason: " + prettyReason; + return new PublicApiViolation(original.getClassName(), "SUPPRESSED", description, original.getMemberName()); + } + +} \ No newline at end of file diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/CheckResult.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/CheckResult.java new file mode 100644 index 0000000000000..9625461fb095a --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/CheckResult.java @@ -0,0 +1,52 @@ +/* + * 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.kafka.apicheck; + +import java.util.List; + +/** + * Outcome of any of the KIP-1265 checks: the Kafka-internal cascade and javadoc validators + * (returning would-be public-API leaks against Kafka's own surface) and the consumer-side + * internal-usage scanner (returning references from a downstream project's bytecode to a + * non-{@code @Public} Kafka type). + * + *

Violations are real failures that should fail the build. Suppressions are would-be + * violations that were silenced by a class-, method-, or field-level + * {@code @SuppressKafkaInternalApiUsage}; each carries the reason supplied to the annotation + * so reviewers can audit every escape hatch on every build. + */ +public final class CheckResult { + private final List violations; + private final List suppressions; + + public CheckResult(List violations, List suppressions) { + this.violations = violations == null ? List.of() : List.copyOf(violations); + this.suppressions = suppressions == null ? List.of() : List.copyOf(suppressions); + } + + public List violations() { + return violations; + } + + public List suppressions() { + return suppressions; + } + + public boolean hasViolations() { + return !violations.isEmpty(); + } +} \ No newline at end of file diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/ClassFacts.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ClassFacts.java new file mode 100644 index 0000000000000..2ba45922ce7bf --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ClassFacts.java @@ -0,0 +1,162 @@ +/* + * 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.kafka.apicheck; + +import org.objectweb.asm.Opcodes; + +import java.util.EnumSet; + +/** + * Everything the checker needs to know about a single class, read once via ASM and cached. + * Carries: + *

+ * + *

Reading from bytecode rather than loading the class sidesteps {@code LinkageError} / + * {@code NoClassDefFoundError} from broken transitive deps (gRPC stubs, telemetry shims, etc.) — + * annotation descriptors live in the class file's constant pool, no linking required. + * + *

Instances are immutable; construct via {@link #builder(String)} so the ASM visitor that + * populates each field has an explicit mutable target instead of poking the result type. + * Equality is by {@code binaryName} so instances can be deduplicated in sets. + */ +final class ClassFacts { + + /** Class-level bytecode annotation markers the checker cares about. */ + enum Flag { + PUBLIC_API, + PRIVATE_API, + DEPRECATED + } + + private final String binaryName; + private final String dottedName; + private final EnumSet flags; + private final int sourceAccess; + + private ClassFacts(Builder b) { + this.binaryName = b.binaryName; + this.dottedName = b.binaryName.replace('$', '.'); + this.flags = b.flags.isEmpty() ? EnumSet.noneOf(Flag.class) : EnumSet.copyOf(b.flags); + this.sourceAccess = b.sourceAccess; + } + + String binaryName() { + return binaryName; + } + + String dottedName() { + return dottedName; + } + + /** Carries a direct {@code @InterfaceAudience.Public}. */ + boolean isPublic() { + return flags.contains(Flag.PUBLIC_API); + } + + /** Carries a direct {@code @InterfaceAudience.Private} — overrides inherited Public on a nested class. */ + boolean isPrivate() { + return flags.contains(Flag.PRIVATE_API); + } + + /** Carries {@code @Deprecated} at the class level. */ + boolean isDeprecated() { + return flags.contains(Flag.DEPRECATED); + } + + /** True iff source-level access is {@code public} or {@code protected}. */ + boolean isExternallyVisible() { + return (sourceAccess & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0; + } + + /** + * @return dotted name of the enclosing class, or {@code null} if this is a top-level class. + * Lets chain walks avoid manipulating the {@code $} separator directly. + */ + String enclosingName() { + String parent = parentBinaryName(binaryName); + return parent == null ? null : parent.replace('$', '.'); + } + + /** + * @return the immediate-parent binary name of a nested class (strip the trailing + * {@code $segment}), or {@code null} for top-level classes. The single canonical + * way to step one level outward in the enclosing-class chain. + */ + static String parentBinaryName(String binaryName) { + int dollar = binaryName.lastIndexOf('$'); + return dollar < 0 ? null : binaryName.substring(0, dollar); + } + + /** + * @return the outermost compilation-unit binary name — strip everything from the first + * {@code $} onward. Used for self-reference detection (two binary names share the + * same outermost iff they're nested under the same top-level class). + */ + static String outermostBinaryName(String binaryName) { + int dollar = binaryName.indexOf('$'); + return dollar < 0 ? binaryName : binaryName.substring(0, dollar); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ClassFacts)) return false; + return binaryName.equals(((ClassFacts) o).binaryName); + } + + @Override + public int hashCode() { + return binaryName.hashCode(); + } + + static Builder builder(String binaryName) { + return new Builder(binaryName); + } + + /** Mutable accumulator used by the ASM visitor; {@link #build()} freezes into a {@link ClassFacts}. */ + static final class Builder { + private final String binaryName; + private final EnumSet flags = EnumSet.noneOf(Flag.class); + private int sourceAccess; + + private Builder(String binaryName) { + this.binaryName = binaryName; + } + + Builder addFlag(Flag flag) { + flags.add(flag); + return this; + } + + Builder sourceAccess(int access) { + this.sourceAccess = access; + return this; + } + + ClassFacts build() { + return new ClassFacts(this); + } + } +} \ No newline at end of file diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/JavadocConsistencyValidator.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/JavadocConsistencyValidator.java new file mode 100644 index 0000000000000..ece264e2860ea --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/JavadocConsistencyValidator.java @@ -0,0 +1,113 @@ +/* + * 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.kafka.apicheck; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * Cross-validates the published javadoc HTML against the project's bytecode-level audience + * annotations. Two complementary checks: + *

+ * + *

Deprecated classes are out of scope on both sides: the deprecation set on the + * {@link ApiSurface} is subtracted from the HTML-discovered set before cross-validation. + * + *

Returns a {@link CheckResult} with an empty suppressions list — these violations don't + * currently have an escape-hatch mechanism, but the uniform shape lets callers compose + * validators without per-validator special cases. + */ +final class JavadocConsistencyValidator { + + private JavadocConsistencyValidator() {} + + static CheckResult validate(File javadocJar, ApiSurface surface) throws IOException { + List violations = new ArrayList<>(); + + Set classesWithPublicDoc = findClassesFromJavadocHtml(javadocJar); + classesWithPublicDoc.removeIf(surface::isDeprecated); + + for (ClassFacts facts : surface.directPublic()) { + if (!classesWithPublicDoc.contains(facts.dottedName())) { + violations.add(new PublicApiViolation( + facts.dottedName(), + "MISSING_JAVADOC", + "Class has @InterfaceAudience.Public annotation but is missing from javadoc", + null)); + } + } + + for (String dottedName : classesWithPublicDoc) { + if (!surface.isEffectivelyPublic(dottedName)) { + violations.add(new PublicApiViolation( + dottedName, + "MISSING_PUBLICAPI_ANNOTATION", + "Class appears in javadoc but lacks @InterfaceAudience.Public annotation", + null)); + } + } + + return new CheckResult(violations, List.of()); + } + + /** Find Kafka-namespaced class names from HTML files in a javadoc JAR. */ + private static Set findClassesFromJavadocHtml(File javadocJar) throws IOException { + Set classes = new HashSet<>(); + try (JarFile jar = new JarFile(javadocJar)) { + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (!isClassHtmlFile(entry.getName())) continue; + String className = convertHtmlPathToClassName(entry.getName()); + if (className.startsWith("org.apache.kafka.")) { + classes.add(className); + } + } + } + return classes; + } + + /** True if the entry path is an {@code org/apache/kafka/...} class HTML page. */ + private static boolean isClassHtmlFile(String path) { + if (!path.endsWith(".html")) return false; + if (!path.startsWith("org/apache/kafka/")) return false; + String fileName = path.substring(path.lastIndexOf('/') + 1); + // Class HTML files start with an uppercase letter; structural pages (index, overview-tree, + // package-summary, …) don't. + String classNamePart = fileName.replaceAll(".html$", ""); + return !classNamePart.isEmpty() && Character.isUpperCase(classNamePart.charAt(0)); + } + + /** {@code org/apache/kafka/common/resource/Resource.html} → {@code org.apache.kafka.common.resource.Resource}. */ + private static String convertHtmlPathToClassName(String htmlPath) { + return htmlPath.replace('/', '.').replaceAll(".html$", ""); + } +} \ No newline at end of file diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/PluginDeveloperApiUsageScanner.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/PluginDeveloperApiUsageScanner.java new file mode 100644 index 0000000000000..0bf38949c4bbe --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/PluginDeveloperApiUsageScanner.java @@ -0,0 +1,615 @@ +/* + * 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.kafka.apicheck; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Handle; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.signature.SignatureReader; +import org.objectweb.asm.signature.SignatureVisitor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * Scans compiled JVM bytecode (.class files, packaged or loose) for references to Kafka classes + * that are not annotated with {@code @InterfaceAudience.Public}. Catches Java, Scala, Kotlin and + * any other JVM-language consumer uniformly — unlike a source-level scan, which is regex-bound + * to .java imports. + * + *

Known limitations

+ * A handful of bytecode reference kinds are intentionally not walked. None of these are likely + * in practice for plugin/connector code but they're worth knowing about when interpreting a + * "0 violations" report: + * + */ +public class PluginDeveloperApiUsageScanner { + private static final Logger LOG = LoggerFactory.getLogger(PluginDeveloperApiUsageScanner.class); + private static final int ASM_API = Opcodes.ASM9; + + /** Internal-form prefix (slashes) for any class we care about checking the audience of. */ + private static final String KAFKA_INTERNAL_PREFIX = "org/apache/kafka/"; + /** Descriptor of {@code @SuppressKafkaInternalApiUsage} — honoured when present on the enclosing class or member. */ + private static final String SUPPRESS_DESCRIPTOR = + "Lorg/apache/kafka/common/annotation/SuppressKafkaInternalApiUsage;"; + private static final String NO_REASON_GIVEN = PublicApiViolation.NO_REASON_MARKER; + + private final Predicate isPublicApi; + + /** + * @param isPublicApi callback that returns {@code true} when the given binary class name + * (e.g. {@code org.apache.kafka.clients.producer.KafkaProducer}) is part + * of the public API surface + */ + public PluginDeveloperApiUsageScanner(Predicate isPublicApi) { + this.isPublicApi = isPublicApi; + } + + /** + * Scan every {@code .class} entry reachable from the supplied roots. Each root may be a + * directory of class files, an individual .class file, or a .jar archive. + */ + public CheckResult scan(List roots) throws IOException { + // Use maps keyed by (consumer class, referenced internal class, member, line) so we + // don't double-record the same call site reachable through multiple visitor callbacks. + Map violations = new LinkedHashMap<>(); + Map suppressions = new LinkedHashMap<>(); + for (File root : roots) { + if (root == null || !root.exists()) { + continue; + } + if (root.isDirectory()) { + scanDirectory(root, violations, suppressions); + } else if (root.getName().endsWith(".jar")) { + scanJar(root, violations, suppressions); + } else if (root.getName().endsWith(".class")) { + try (InputStream in = new BufferedInputStream(Files.newInputStream(root.toPath()))) { + scanClassStream(in, violations, suppressions); + } + } + } + return new CheckResult(new ArrayList<>(violations.values()), + new ArrayList<>(suppressions.values())); + } + + private void scanDirectory(File dir, + Map violations, + Map suppressions) throws IOException { + File[] children = dir.listFiles(); + if (children == null) { + return; + } + for (File child : children) { + if (child.isDirectory()) { + scanDirectory(child, violations, suppressions); + } else if (child.getName().endsWith(".class")) { + try (InputStream in = new BufferedInputStream(Files.newInputStream(child.toPath()))) { + scanClassStream(in, violations, suppressions); + } + } + } + } + + private void scanJar(File jar, + Map violations, + Map suppressions) throws IOException { + try (JarFile jarFile = new JarFile(jar)) { + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (!entry.getName().endsWith(".class")) { + continue; + } + try (InputStream in = new BufferedInputStream(jarFile.getInputStream(entry))) { + scanClassStream(in, violations, suppressions); + } + } + } + } + + private void scanClassStream(InputStream in, + Map violations, + Map suppressions) throws IOException { + ClassReader reader = new ClassReader(in); + reader.accept(new ReferenceCollectingClassVisitor(violations, suppressions), ClassReader.SKIP_FRAMES); + } + + private void recordIfInternal(String internalName, + String consumerClass, + String memberName, + int line, + String suppressionReason, + Map violations, + Map suppressions) { + String binaryName = resolveInternalKafkaReference(internalName); + if (binaryName == null) { + return; + } + // Test the full nested name. The predicate (backed by ApiSurface#isEffectivelyPublic) + // walks the enclosing chain level-by-level, so an explicit @InterfaceAudience.Private + // on a nested class correctly overrides an inherited @Public from its outer — collapsing + // to the outer name here would silently allow exactly that override. + if (isPublicApi.test(binaryName)) { + return; + } + // Don't report a class flagging references to its own outermost compilation unit + // (covers self-references and references between siblings nested under the same outer). + if (ClassFacts.outermostBinaryName(binaryName).equals(ClassFacts.outermostBinaryName(consumerClass))) { + return; + } + String location = formatLocation(consumerClass, memberName, line); + String key = referenceKey(consumerClass, binaryName, memberName, line); + if (suppressionReason != null) { + recordSuppression(suppressions, key, binaryName, memberName, location, suppressionReason); + } else { + recordViolation(violations, key, binaryName, memberName, location); + } + } + + /** + * @return the dotted binary name of an {@code org.apache.kafka.*} type referenced by + * {@code internalName} (an ASM internal name or descriptor), or {@code null} if the + * reference is to a non-Kafka type, a primitive, or unparseable. + */ + private static String resolveInternalKafkaReference(String internalName) { + if (internalName == null) { + return null; + } + String trimmed = stripDescriptor(internalName); + if (trimmed == null || !trimmed.startsWith(KAFKA_INTERNAL_PREFIX)) { + return null; + } + return trimmed.replace('/', '.'); + } + + /** Render the consumer-side location as {@code Class#member (line N)}, omitting absent parts. */ + private static String formatLocation(String consumerClass, String memberName, int line) { + StringBuilder sb = new StringBuilder(consumerClass); + if (memberName != null) { + sb.append('#').append(memberName); + } + if (line > 0) { + sb.append(" (line ").append(line).append(')'); + } + return sb.toString(); + } + + /** Stable de-dup key so the same call-site reported via multiple visitor callbacks collapses to one entry. */ + private static String referenceKey(String consumerClass, String binaryName, String memberName, int line) { + return consumerClass + "|" + binaryName + "|" + (memberName == null ? "" : memberName) + "|" + line; + } + + private static void recordSuppression(Map suppressions, + String key, String binaryName, String memberName, + String location, String reason) { + String prettyReason = reason.isEmpty() ? NO_REASON_GIVEN : reason; + LOG.info("Suppressed internal-API reference to {} from {}: {}", binaryName, location, prettyReason); + String description = String.format( + "Suppressed reference to internal Kafka class %s from %s — reason: %s", + binaryName, location, prettyReason); + suppressions.putIfAbsent(key, + new PublicApiViolation(binaryName, "SUPPRESSED_INTERNAL_API_USAGE", description, memberName)); + } + + private static void recordViolation(Map violations, + String key, String binaryName, String memberName, String location) { + String description = String.format( + "Bytecode reference to internal Kafka class %s from %s", + binaryName, location); + violations.putIfAbsent(key, + new PublicApiViolation(binaryName, "INTERNAL_API_USAGE", description, memberName)); + } + + /** Convert any of: {@code Lorg/apache/kafka/Foo;}, {@code [Lorg/apache/kafka/Foo;}, {@code org/apache/kafka/Foo} to the bare internal form. */ + /** + * Return the ASM internal name for a reference-typed {@link Type} (OBJECT or ARRAY), or + * {@code null} for VOID/primitive types. {@link Type#getInternalName()} is only documented + * for reference types — calling it on a primitive happens to produce a single-char descriptor + * ("V"/"I"/...) today which the prefix gate happens to reject, but that's undefined behaviour + * we shouldn't depend on. + */ + private static String referenceInternalName(Type type) { + int sort = type.getSort(); + return (sort == Type.OBJECT || sort == Type.ARRAY) ? type.getInternalName() : null; + } + + private static String stripDescriptor(String name) { + if (name == null || name.isEmpty()) { + return null; + } + int i = 0; + while (i < name.length() && name.charAt(i) == '[') { + i++; + } + if (i >= name.length()) { + return null; + } + char c = name.charAt(i); + if (c == 'L' && name.endsWith(";")) { + return name.substring(i + 1, name.length() - 1); + } + // Primitive descriptor (I, J, Z, ...) — nothing internal to record. + if (i > 0 || "VZBSCIJFD".indexOf(c) >= 0) { + return null; + } + return name; + } + + /** + * Buffered reference. Header references (class super/interfaces, method return/param types, + * field type) are buffered because the {@code @SuppressKafkaInternalApiUsage} annotation that + * may legitimise them is visited after the header. Body-instruction references can be + * recorded immediately because annotations on a method/field are visited before the body. + */ + private static final class PendingReference { + final String internalName; + final String memberName; + final int line; + PendingReference(String internalName, String memberName, int line) { + this.internalName = internalName; + this.memberName = memberName; + this.line = line; + } + } + + /** Visits a class and records every referenced type, honouring {@code @SuppressKafkaInternalApiUsage}. */ + private final class ReferenceCollectingClassVisitor extends ClassVisitor { + private final Map violations; + private final Map suppressions; + private String currentClass; + private String classSuppression; // null = none; otherwise the reason (may be empty string) + private final List headerRefs = new ArrayList<>(); + + ReferenceCollectingClassVisitor(Map violations, + Map suppressions) { + super(ASM_API); + this.violations = violations; + this.suppressions = suppressions; + } + + /** + * Class header — superclass + interface list + generic signature. Caught here so a consumer + * that {@code extends} or {@code implements} an internal Kafka type is flagged even if its + * body never names the type. Generics ({@code class C extends Foo}) hide + * inside the signature string and are pulled out via {@link SignatureReader}. + */ + @Override + public void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + this.currentClass = name == null ? "" : name.replace('/', '.'); + if (superName != null) { + headerRefs.add(new PendingReference(superName, null, -1)); + } + if (interfaces != null) { + for (String iface : interfaces) { + headerRefs.add(new PendingReference(iface, null, -1)); + } + } + collectSignatureRefs(signature, null, -1, headerRefs); + } + + /** + * Class-level annotations. Two jobs: (a) capture the reason on + * {@code @SuppressKafkaInternalApiUsage} so header refs can be silenced, and (b) treat the + * annotation's own type as a reference — an {@code @InternalAnnotation} on a consumer class + * is still a reference into Kafka internals. + */ + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + if (SUPPRESS_DESCRIPTOR.equals(descriptor)) { + return new ReasonCaptureVisitor(r -> classSuppression = r); + } + headerRefs.add(new PendingReference(stripDescriptor(descriptor), null, -1)); + return null; + } + + /** + * Field declarations. The field's declared type (descriptor) and its full generic form + * (signature) can both name internal types — e.g. {@code private InternalCache cache} or + * {@code Map data}. Refs are buffered so a field-level + * {@code @SuppressKafkaInternalApiUsage} (visited after the declaration) can suppress them. + */ + @Override + public FieldVisitor visitField(int access, String name, String descriptor, + String signature, Object value) { + return new FieldVisitor(ASM_API) { + private String fieldSuppression; + private final List fieldRefs = new ArrayList<>(); + { + fieldRefs.add(new PendingReference(stripDescriptor(descriptor), name, -1)); + collectSignatureRefs(signature, name, -1, fieldRefs); + } + @Override + public AnnotationVisitor visitAnnotation(String d, boolean v) { + if (SUPPRESS_DESCRIPTOR.equals(d)) { + return new ReasonCaptureVisitor(r -> fieldSuppression = r); + } + fieldRefs.add(new PendingReference(stripDescriptor(d), name, -1)); + return null; + } + @Override + public void visitEnd() { + String reason = effective(fieldSuppression); + flush(fieldRefs, reason); + } + }; + } + + /** + * Per-method delegate. Each method's body is walked by a + * {@link ReferenceCollectingMethodVisitor} that records every kind of bytecode-level + * reference (see its own javadoc). + */ + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, + String signature, String[] exceptions) { + return new ReferenceCollectingMethodVisitor(name, descriptor, signature, exceptions); + } + + /** + * End of class. Flushes the buffered header refs (superclass / interfaces / generic + * signature / non-suppress annotations) now that the class-level + * {@code @SuppressKafkaInternalApiUsage} reason — which is visited after the + * header in ASM's callback order — is finally known. + */ + @Override + public void visitEnd() { + flush(headerRefs, classSuppression); + } + + /** {@code memberReason} takes precedence; falls back to class-level. */ + String effective(String memberReason) { + return memberReason != null ? memberReason : classSuppression; + } + + void flush(List refs, String reason) { + for (PendingReference r : refs) { + recordIfInternal(r.internalName, currentClass, r.memberName, r.line, reason, violations, suppressions); + } + } + + private void collectSignatureRefs(String signature, String member, int line, List out) { + if (signature == null) { + return; + } + new SignatureReader(signature).accept(new SignatureVisitor(ASM_API) { + @Override + public void visitClassType(String name) { + out.add(new PendingReference(name, member, line)); + } + }); + } + + /** Records type references encountered in method bodies; honours method-level + class-level suppression. */ + private final class ReferenceCollectingMethodVisitor extends MethodVisitor { + private final String methodName; + private final List headerBuffer = new ArrayList<>(); + private int currentLine = -1; + private String methodSuppression; + private boolean codeStarted; + + ReferenceCollectingMethodVisitor(String name, String descriptor, String signature, String[] exceptions) { + super(ASM_API); + this.methodName = name; + Type methodType = Type.getMethodType(descriptor); + headerBuffer.add(new PendingReference(referenceInternalName(methodType.getReturnType()), name, -1)); + for (Type arg : methodType.getArgumentTypes()) { + headerBuffer.add(new PendingReference(referenceInternalName(arg), name, -1)); + } + if (exceptions != null) { + for (String ex : exceptions) { + headerBuffer.add(new PendingReference(ex, name, -1)); + } + } + collectSignatureRefs(signature, name, -1, headerBuffer); + } + + /** + * Method-level annotations. {@code @SuppressKafkaInternalApiUsage} captures the reason + * to silence both header refs (return/param/exception types) and body refs in this + * method. All other annotation types are themselves recorded as references — an + * annotation IS a class reference, even if it's never used elsewhere. + */ + @Override + public AnnotationVisitor visitAnnotation(String d, boolean v) { + if (SUPPRESS_DESCRIPTOR.equals(d)) { + return new ReasonCaptureVisitor(r -> methodSuppression = r); + } + headerBuffer.add(new PendingReference(stripDescriptor(d), methodName, -1)); + return null; + } + + /** + * Marker fired when ASM transitions from method header to method body. All method-level + * annotations have already been visited by this point, so {@link #methodSuppression} is + * stable — header refs (return type / params / declared exceptions / generic signature + * / non-suppress annotations) are flushed now with the correct effective reason. + */ + @Override + public void visitCode() { + if (!codeStarted) { + flush(headerBuffer, effective(methodSuppression)); + headerBuffer.clear(); + codeStarted = true; + } + } + + /** + * Source line marker from the {@code LineNumberTable} debug attribute. Only fires for + * classes compiled with {@code javac -g} (the default). Carries no class reference of + * its own — we just track the current line so violations can be reported as + * {@code ConsumerClass#method (line N)}. Stays at -1 when debug info is stripped. + */ + @Override + public void visitLineNumber(int line, org.objectweb.asm.Label start) { + this.currentLine = line; + } + + /** + * Type-as-operand instructions: {@code NEW}, {@code ANEWARRAY}, {@code CHECKCAST}, + * {@code INSTANCEOF}. The operand is the class being instantiated, cast to, or tested — + * exactly the cases where a consumer reaches an internal type without naming it via a + * method call or field access. + */ + @Override + public void visitTypeInsn(int opcode, String type) { + recordBody(type); + } + + /** + * Field-access instructions: {@code GETFIELD}, {@code PUTFIELD}, {@code GETSTATIC}, + * {@code PUTSTATIC}. Both the field's owner (the declaring class) and its + * type (descriptor) can name internal Kafka classes — e.g. reading + * {@code InternalClass.CONSTANT} (owner is internal) or writing to a field whose type + * is internal. + */ + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + recordBody(owner); + recordBody(stripDescriptor(descriptor)); + } + + /** + * Method-invocation instructions: {@code INVOKEVIRTUAL}, {@code INVOKESPECIAL}, + * {@code INVOKESTATIC}, {@code INVOKEINTERFACE}. Three reference slots per call site: + * the owner (declaring class), the return type, and each argument type. Catches both + * "calls into an internal class" and "passes an internal type as an argument or + * receives one as a return". + */ + @Override + public void visitMethodInsn(int opcode, String owner, String name, + String descriptor, boolean isInterface) { + recordBody(owner); + Type methodType = Type.getMethodType(descriptor); + recordBody(referenceInternalName(methodType.getReturnType())); + for (Type arg : methodType.getArgumentTypes()) { + recordBody(referenceInternalName(arg)); + } + } + + /** + * {@code INVOKEDYNAMIC}. Emitted by {@code javac} for lambdas, method references, and + * {@code String} concatenation since Java 9. Only the call-site descriptor — return + * type and argument types — is walked. The bootstrap method handle itself is not + * followed, because the LambdaMetafactory machinery is JDK-owned and the user-visible + * references show up via the descriptor anyway. + */ + @Override + public void visitInvokeDynamicInsn(String name, String descriptor, + Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) { + Type methodType = Type.getMethodType(descriptor); + recordBody(referenceInternalName(methodType.getReturnType())); + for (Type arg : methodType.getArgumentTypes()) { + recordBody(referenceInternalName(arg)); + } + } + + /** + * {@code LDC} loads a constant onto the operand stack — int / long / float / double / + * String / and, relevantly here, {@code Class} literals such as + * {@code InternalClass.class}. Only the {@link Type} case is interesting; primitive + * and string constants carry no class reference. + */ + @Override + public void visitLdcInsn(Object value) { + if (value instanceof Type) { + Type t = (Type) value; + if (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY) { + recordBody(t.getInternalName()); + } + } + } + + /** + * {@code MULTIANEWARRAY} for multi-dimensional arrays + * ({@code new InternalClass[3][3]}). Single-dimensional array allocation goes through + * {@code ANEWARRAY} which is handled by {@link #visitTypeInsn}. + */ + @Override + public void visitMultiANewArrayInsn(String descriptor, int numDimensions) { + recordBody(stripDescriptor(descriptor)); + } + + /** + * Exception-handler table entries: {@code catch (InternalKafkaException e)}. The + * {@code type} is the internal name of the caught exception (or {@code null} for a + * {@code finally} block, which has no exception type to record). + */ + @Override + public void visitTryCatchBlock(org.objectweb.asm.Label start, org.objectweb.asm.Label end, + org.objectweb.asm.Label handler, String type) { + if (type != null) { + recordBody(type); + } + } + + /** + * End of method. {@link #visitCode} is never called for abstract / native methods — + * they have no body — so their header refs would otherwise leak unflushed. This safety + * net guarantees every method's return/param/exception types are still audited. + */ + @Override + public void visitEnd() { + if (!codeStarted) { + flush(headerBuffer, effective(methodSuppression)); + headerBuffer.clear(); + } + } + + private void recordBody(String internalName) { + recordIfInternal(internalName, currentClass, methodName, currentLine, + effective(methodSuppression), violations, suppressions); + } + } + } +} diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/PublicApiChecker.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/PublicApiChecker.java new file mode 100644 index 0000000000000..eea888f4b55a9 --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/PublicApiChecker.java @@ -0,0 +1,121 @@ +/* + * 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.kafka.apicheck; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Facade for the KIP-1265 public-API checker. Pre-scans the supplied Kafka jars into an + * {@link ApiSurface} once and delegates each check to a focused validator: + *
    + *
  • {@link JavadocConsistencyValidator} for {@code MISSING_JAVADOC} / {@code MISSING_PUBLICAPI_ANNOTATION}.
  • + *
  • {@link CascadeValidator} for {@code INVALID_RETURN_TYPE} / {@code INVALID_PARAMETER_TYPE} / + * {@code INVALID_EXCEPTION_TYPE} with {@code @SuppressKafkaInternalApiUsage} suppression.
  • + *
  • {@link PluginDeveloperApiUsageScanner} for the consumer-side check (via {@link #checkBytecode}).
  • + *
+ * + *

All bytecode reading is done via ASM; no classloading, no {@code LinkageError} risk from + * broken transitive deps. + */ +public class PublicApiChecker { + + private final ApiSurface surface; + + /** + * @param projectJars jars produced by the project being checked. Their classes drive + * the MISSING_JAVADOC iteration and are cascade-checked for method + * signature leaks. + * @param referenceJars jars from sibling Kafka modules this project depends on. Their + * classes contribute to the {@code @InterfaceAudience.Public} + * membership set so cross-module references resolve, but they don't + * take part in this project's own javadoc consistency or cascade + * iteration (each module checks its own surface). + */ + public PublicApiChecker(List projectJars, List referenceJars) throws IOException { + this.surface = ApiSurfaceScanner.scan(projectJars, referenceJars); + } + + /** Convenience for the consumer-side scanner: no separate reference jars needed. */ + public PublicApiChecker(List kafkaJars) throws IOException { + this(kafkaJars, java.util.Collections.emptyList()); + } + + /** + * Cross-validate the javadoc HTML against the project's bytecode audience annotations and + * cascade-check public method signatures for internal-type leaks. + */ + public CheckResult checkPublicApiConsistency(File javadocJar) throws IOException { + CheckResult javadoc = JavadocConsistencyValidator.validate(javadocJar, surface); + CheckResult cascade = CascadeValidator.validate(surface); + + List violations = new ArrayList<>(javadoc.violations()); + violations.addAll(cascade.violations()); + List suppressions = new ArrayList<>(javadoc.suppressions()); + suppressions.addAll(cascade.suppressions()); + return new CheckResult(violations, suppressions); + } + + /** + * Consumer-side check: walk compiled bytecode at the given roots and flag references to any + * {@code org.apache.kafka.*} class that isn't effectively {@code @InterfaceAudience.Public}. + * Roots may be class directories or jar archives. + */ + public CheckResult checkBytecode(List classFileRoots) throws IOException { + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(this::isPublicApi); + return scanner.scan(classFileRoots); + } + + /** + * Filter the supplied class-file roots to those that exist on disk. Both adapters + * (Gradle task, Maven mojo) seed the input from build configuration that may include + * directories the build hasn't produced yet (e.g. test classes when there are no tests). + */ + public static List collectExistingRoots(Iterable roots) { + List existing = new ArrayList<>(); + for (File root : roots) { + if (root.exists()) { + existing.add(root); + } + } + return existing; + } + + /** + * Consumer-side predicate: true if the binary class name (e.g. + * {@code org.apache.kafka.clients.producer.KafkaProducer} or + * {@code org.apache.kafka.clients.admin.OffsetSpec$LatestSpec}) is effectively + * {@code @InterfaceAudience.Public} — either via a direct annotation or by inheritance + * from an enclosing class. A direct {@code @InterfaceAudience.Private} overrides an + * inherited Public. Non-{@code org.apache.kafka.*} types are treated as out of scope. + * + *

Deprecation is intentionally not a bypass on the consumer side: + * {@code @Deprecated} internal types are exactly the ones most likely to be removed in + * the next release, so consumer references to them deserve a violation. The cascade + * validator has its own deprecation bypass for the producer-side leak check, which is + * fine — that side is just asking "did we expose this in the API surface?", whereas the + * consumer side is asking "am I going to break when Kafka removes this?". + */ + public boolean isPublicApi(String binaryClassName) { + if (!binaryClassName.startsWith("org.apache.kafka.")) { + return true; // not in scope + } + return surface.isEffectivelyPublic(binaryClassName); + } +} \ No newline at end of file diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/PublicApiViolation.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/PublicApiViolation.java new file mode 100644 index 0000000000000..acfb5a61397ba --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/PublicApiViolation.java @@ -0,0 +1,98 @@ +/* + * 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.kafka.apicheck; + +/** + * Represents a violation of the public API rules. + */ +public class PublicApiViolation { + /** + * Rendered into a suppression's description when the {@code @SuppressKafkaInternalApiUsage} + * annotation carried no {@code value()}. Stable marker so the reporter and the build tasks + * can surface unjustified suppressions consistently. + */ + public static final String NO_REASON_MARKER = "(no reason given)"; + + private final String className; + private final String violationType; + private final String description; + private final String memberName; + + public PublicApiViolation(String className, String violationType, String description, String memberName) { + this.className = className; + this.violationType = violationType; + this.description = description; + this.memberName = memberName; + } + + public String getClassName() { + return className; + } + + public String getViolationType() { + return violationType; + } + + public String getDescription() { + return description; + } + + public String getMemberName() { + return memberName; + } + + @Override + public String toString() { + if (memberName != null && !memberName.isEmpty()) { + return String.format("[%s] %s.%s: %s", violationType, className, memberName, description); + } else { + return String.format("[%s] %s: %s", violationType, className, description); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PublicApiViolation that = (PublicApiViolation) o; + + if (!className.equals(that.className)) return false; + if (!violationType.equals(that.violationType)) return false; + if (!description.equals(that.description)) return false; + return memberName != null ? memberName.equals(that.memberName) : that.memberName == null; + } + + /** + * @return true iff this suppression's description ends with {@link #NO_REASON_MARKER} — + * i.e. the {@code @SuppressKafkaInternalApiUsage} annotation carried no + * {@code value()}. KIP-1265 describes the reason as required, so the checker warns + * on unjustified suppressions. + */ + public boolean lacksReason() { + return description != null && description.endsWith("reason: " + NO_REASON_MARKER); + } + + @Override + public int hashCode() { + int result = className.hashCode(); + result = 31 * result + violationType.hashCode(); + result = 31 * result + description.hashCode(); + result = 31 * result + (memberName != null ? memberName.hashCode() : 0); + return result; + } +} \ No newline at end of file diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/ReasonCaptureVisitor.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ReasonCaptureVisitor.java new file mode 100644 index 0000000000000..6d30aa2272746 --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ReasonCaptureVisitor.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. + */ +package org.apache.kafka.apicheck; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Opcodes; + +import java.util.function.Consumer; + +/** + * Captures the {@code value()} string of a {@code @SuppressKafkaInternalApiUsage} annotation. + * If the annotation is present but its {@code value()} was omitted, {@link #visitEnd()} routes + * an empty string to the setter — the convention both checkers use to mean "suppressed without + * a reason." + */ +final class ReasonCaptureVisitor extends AnnotationVisitor { + + private final Consumer setter; + private boolean assigned; + + ReasonCaptureVisitor(Consumer setter) { + super(Opcodes.ASM9); + this.setter = setter; + } + + @Override + public void visit(String name, Object value) { + if ("value".equals(name) && value instanceof String) { + setter.accept((String) value); + assigned = true; + } + } + + @Override + public void visitEnd() { + if (!assigned) { + setter.accept(""); + } + } +} \ No newline at end of file diff --git a/api-checker/core/src/main/java/org/apache/kafka/apicheck/ViolationReporter.java b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ViolationReporter.java new file mode 100644 index 0000000000000..ada8c0eb105eb --- /dev/null +++ b/api-checker/core/src/main/java/org/apache/kafka/apicheck/ViolationReporter.java @@ -0,0 +1,157 @@ +/* + * 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.kafka.apicheck; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; + +/** + * Generates reports for public API violations. + */ +public class ViolationReporter { + + /** + * Write violations + suppressions to a text report file. Suppressions are rendered in a + * dedicated section so reviewers can audit every place {@code @SuppressKafkaInternalApiUsage} + * has been applied — together with the reason supplied to the annotation. + */ + public void writeTextReport(List violations, + List suppressions, + File reportFile) throws IOException { + reportFile.getParentFile().mkdirs(); + List safeSuppressions = + suppressions == null ? Collections.emptyList() : suppressions; + + // Report contents must be reproducible: any two runs over the same inputs should produce + // byte-identical reports so CI diff tooling and reviewers can compare cleanly. That rules + // out a wall-clock timestamp (omitted) and HashMap-order grouping (replaced with TreeMap + // + a stable per-list sort by class then member). + try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(reportFile.toPath(), StandardCharsets.UTF_8))) { + writer.println("Apache Kafka Public API Violation Report"); + writer.println("========================================"); + writer.println("Total violations: " + violations.size()); + writer.println("Total suppressions: " + safeSuppressions.size()); + writer.println(); + + if (violations.isEmpty()) { + writer.println("No violations found."); + } else { + Map> violationsByType = groupSorted( + violations, PublicApiViolation::getViolationType); + for (Map.Entry> entry : violationsByType.entrySet()) { + writer.println("## " + entry.getKey() + " (" + entry.getValue().size() + " violations)"); + writer.println(); + for (PublicApiViolation violation : entry.getValue()) { + writer.println("- " + violation.toString()); + } + writer.println(); + } + + writer.println("## Summary by Class"); + writer.println(); + Map> violationsByClass = groupSorted( + violations, PublicApiViolation::getClassName); + for (Map.Entry> entry : violationsByClass.entrySet()) { + writer.println("### " + entry.getKey() + " (" + entry.getValue().size() + " violations)"); + for (PublicApiViolation violation : entry.getValue()) { + writer.println(" - " + violation.getViolationType() + ": " + violation.getDescription()); + } + writer.println(); + } + } + + if (!safeSuppressions.isEmpty()) { + writer.println("## Suppressions (" + safeSuppressions.size() + " entries)"); + writer.println("Checks skipped due to @SuppressKafkaInternalApiUsage."); + writer.println("Each line shows the reason supplied to the annotation; review periodically."); + writer.println(); + List sortedSuppressions = new ArrayList<>(safeSuppressions); + sortedSuppressions.sort(VIOLATION_ORDER); + for (PublicApiViolation suppression : sortedSuppressions) { + writer.println("- " + suppression.getDescription()); + } + writer.println(); + } + } + } + + /** Stable sort key for any list of violations: class, then member, then description. */ + private static final Comparator VIOLATION_ORDER = + Comparator.comparing(PublicApiViolation::getClassName, Comparator.nullsFirst(String::compareTo)) + .thenComparing(PublicApiViolation::getMemberName, Comparator.nullsFirst(String::compareTo)) + .thenComparing(PublicApiViolation::getDescription, Comparator.nullsFirst(String::compareTo)); + + private static > Map> groupSorted( + List violations, + java.util.function.Function keyFn) { + Map> grouped = violations.stream() + .collect(Collectors.groupingBy(keyFn, TreeMap::new, Collectors.toList())); + grouped.values().forEach(list -> list.sort(VIOLATION_ORDER)); + return grouped; + } + + /** Back-compat overload — call sites that don't yet pass suppressions. */ + public void writeTextReport(List violations, File reportFile) throws IOException { + writeTextReport(violations, Collections.emptyList(), reportFile); + } + + /** + * Print violations to console with color coding (if supported). Suppressions are listed at the + * end so reviewers see what was waived (each with reason). + */ + public void printToConsole(List violations, + List suppressions, + boolean useColors) { + String redColor = useColors ? "\u001B[31m" : ""; + String greenColor = useColors ? "\u001B[32m" : ""; + String yellowColor = useColors ? "\u001B[33m" : ""; + String cyanColor = useColors ? "\u001B[36m" : ""; + String resetColor = useColors ? "\u001B[0m" : ""; + + if (violations.isEmpty()) { + System.out.println(greenColor + "No public API violations found." + resetColor); + } else { + System.out.println(redColor + "Found " + violations.size() + " public API violation(s):" + resetColor); + System.out.println(); + for (PublicApiViolation violation : violations) { + System.out.println(yellowColor + violation.toString() + resetColor); + } + System.out.println(); + System.out.println("Please fix these violations to ensure API compatibility."); + } + + if (suppressions != null && !suppressions.isEmpty()) { + System.out.println(); + System.out.println(cyanColor + suppressions.size() + + " check(s) suppressed via @SuppressKafkaInternalApiUsage:" + resetColor); + for (PublicApiViolation suppression : suppressions) { + System.out.println(cyanColor + " " + suppression.getDescription() + resetColor); + } + } + } + +} diff --git a/api-checker/core/src/test/java/org/apache/kafka/apicheck/ApiSurfaceScannerTest.java b/api-checker/core/src/test/java/org/apache/kafka/apicheck/ApiSurfaceScannerTest.java new file mode 100644 index 0000000000000..3e2c8b42f7843 --- /dev/null +++ b/api-checker/core/src/test/java/org/apache/kafka/apicheck/ApiSurfaceScannerTest.java @@ -0,0 +1,215 @@ +/* + * 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.kafka.apicheck; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.objectweb.asm.Opcodes; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ApiSurfaceScannerTest { + + @TempDir + Path tempDir; + + @Test + void publicTopLevelClass_isInDirectAndEffectiveSets() throws IOException { + File jar = projectJar("proj.jar", + AsmClassFactory.klass("org.apache.kafka.foo.Bar").access(Opcodes.ACC_PUBLIC).publicApi()); + ApiSurface s = scan(jar); + + assertTrue(containsDotted(s.directPublic(), "org.apache.kafka.foo.Bar")); + assertTrue(containsDotted(s.effectivePublic(), "org.apache.kafka.foo.Bar")); + assertTrue(s.isEffectivelyPublic("org.apache.kafka.foo.Bar")); + assertEquals(jar, s.jarOf("org.apache.kafka.foo.Bar")); + } + + @Test + void privateNested_overridesInheritedPublic() throws IOException { + File jar = projectJar("proj.jar", + AsmClassFactory.klass("org.apache.kafka.foo.Outer").access(Opcodes.ACC_PUBLIC).publicApi(), + AsmClassFactory.klass("org.apache.kafka.foo.Outer$Inner").access(Opcodes.ACC_PUBLIC).privateApi()); + ApiSurface s = scan(jar); + + assertTrue(s.isEffectivelyPublic("org.apache.kafka.foo.Outer")); + assertFalse(s.isEffectivelyPublic("org.apache.kafka.foo.Outer$Inner"), + "@Private must override inherited @Public"); + assertFalse(containsDotted(s.directPublic(), "org.apache.kafka.foo.Outer.Inner")); + assertFalse(containsDotted(s.effectivePublic(), "org.apache.kafka.foo.Outer.Inner")); + } + + @Test + void unannotatedNested_inheritsPublicFromOuter() throws IOException { + File jar = projectJar("proj.jar", + AsmClassFactory.klass("org.apache.kafka.foo.Outer").access(Opcodes.ACC_PUBLIC).publicApi(), + AsmClassFactory.klass("org.apache.kafka.foo.Outer$Inner").access(Opcodes.ACC_PUBLIC)); + ApiSurface s = scan(jar); + + assertTrue(s.isEffectivelyPublic("org.apache.kafka.foo.Outer$Inner")); + // Inner has no direct @Public, so it's not in the MISSING_JAVADOC iteration set. + assertFalse(containsDotted(s.directPublic(), "org.apache.kafka.foo.Outer.Inner")); + // Externally visible + effective @Public + owned → in the cascade iteration set. + assertTrue(containsDotted(s.effectivePublic(), "org.apache.kafka.foo.Outer.Inner")); + } + + @Test + void packagePrivateNested_inheritsPublicButNotInCascade() throws IOException { + // Nested-class header is ACC_PUBLIC (compiler convention) but the InnerClasses entry says + // package-private. The scanner must trust the InnerClasses entry over the header. + File jar = projectJar("proj.jar", + AsmClassFactory.klass("org.apache.kafka.foo.Outer").access(Opcodes.ACC_PUBLIC).publicApi(), + AsmClassFactory.klass("org.apache.kafka.foo.Outer$Inner") + .access(Opcodes.ACC_PUBLIC) + .nestedAccess(0)); + ApiSurface s = scan(jar); + + assertTrue(s.isEffectivelyPublic("org.apache.kafka.foo.Outer$Inner"), + "chain walk sees inherited @Public regardless of visibility"); + // The effectivePublic set contains all owned + effective-Public classes; CascadeValidator + // filters on isExternallyVisible() at the iteration site rather than at the scanner. + assertTrue(containsDotted(s.effectivePublic(), "org.apache.kafka.foo.Outer.Inner")); + ClassFacts innerFacts = s.factsOf("org.apache.kafka.foo.Outer$Inner"); + assertFalse(innerFacts.isExternallyVisible(), + "package-private nested classes are filtered out by CascadeValidator, not the scanner"); + } + + @Test + void deprecatedClass_isExcludedFromIterationSets() throws IOException { + File jar = projectJar("proj.jar", + AsmClassFactory.klass("org.apache.kafka.foo.OldBar") + .access(Opcodes.ACC_PUBLIC) + .publicApi() + .deprecated()); + ApiSurface s = scan(jar); + + assertTrue(s.isDeprecated("org.apache.kafka.foo.OldBar")); + assertTrue(s.directPublic().isEmpty(), "deprecated classes are out of scope on both validation sides"); + assertTrue(s.effectivePublic().isEmpty()); + // isEffectivelyPublic answers the audience question only — deprecation is handled + // separately by callers (CascadeValidator skips deprecated refs before this check). + assertTrue(s.isEffectivelyPublic("org.apache.kafka.foo.OldBar")); + } + + @Test + void anonymousAndLambdaClasses_areSkippedEntirely() throws IOException { + File jar = TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("org.apache.kafka.foo.Outer").access(Opcodes.ACC_PUBLIC).publicApi()) + .addClass(AsmClassFactory.klass("org.apache.kafka.foo.Outer$1").access(Opcodes.ACC_PUBLIC)) + .addClass(AsmClassFactory.klass("org.apache.kafka.foo.Outer$$Lambda$0").access(Opcodes.ACC_PUBLIC)) + .writeTo(tempDir, "proj.jar"); + ApiSurface s = scan(jar); + + assertNotNull(s.factsOf("org.apache.kafka.foo.Outer")); + assertNull(s.factsOf("org.apache.kafka.foo.Outer$1"), + "anonymous classes (digit after $) are not part of the API surface"); + assertNull(s.factsOf("org.apache.kafka.foo.Outer$$Lambda$0"), + "lambda / synthetic-accessor classes ($$) are skipped"); + } + + @Test + void nonKafkaClasses_areSkipped() throws IOException { + File jar = TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("com.example.External").access(Opcodes.ACC_PUBLIC).publicApi()) + .writeTo(tempDir, "proj.jar"); + ApiSurface s = scan(jar); + + assertNull(s.factsOf("com.example.External")); + assertTrue(s.directPublic().isEmpty()); + } + + @Test + void packageInfoAndModuleInfo_areSkipped() throws IOException { + // The scanner short-circuits on the binary name before reading any bytes, so the content + // of these entries is irrelevant — pass garbage to prove they aren't parsed. + File jar = TempJarBuilder.jar() + .addEntry("org/apache/kafka/foo/package-info.class", new byte[]{0}) + .addEntry("module-info.class", new byte[]{0}) + .addClass(AsmClassFactory.klass("org.apache.kafka.foo.Bar").access(Opcodes.ACC_PUBLIC).publicApi()) + .writeTo(tempDir, "proj.jar"); + ApiSurface s = scan(jar); + + assertNotNull(s.factsOf("org.apache.kafka.foo.Bar")); + assertNull(s.factsOf("org.apache.kafka.foo.package-info")); + assertNull(s.factsOf("module-info")); + } + + @Test + void referenceJar_contributesMembershipButNotIteration() throws IOException { + File proj = projectJar("proj.jar", + AsmClassFactory.klass("org.apache.kafka.proj.OwnedClass").access(Opcodes.ACC_PUBLIC).publicApi()); + File ref = TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("org.apache.kafka.ref.RefClass").access(Opcodes.ACC_PUBLIC).publicApi()) + .writeTo(tempDir, "ref.jar"); + ApiSurface s = ApiSurfaceScanner.scan(List.of(proj), List.of(ref)); + + // Reference class is recorded and contributes to the membership set so cross-module + // @Public references resolve in cascade checks… + assertNotNull(s.factsOf("org.apache.kafka.ref.RefClass")); + assertTrue(s.isEffectivelyPublic("org.apache.kafka.ref.RefClass")); + // …but doesn't take part in this project's MISSING_JAVADOC / cascade iteration. + assertFalse(containsDotted(s.directPublic(), "org.apache.kafka.ref.RefClass")); + assertFalse(containsDotted(s.effectivePublic(), "org.apache.kafka.ref.RefClass")); + // Project-owned class participates in both iteration sets. + assertTrue(containsDotted(s.directPublic(), "org.apache.kafka.proj.OwnedClass")); + assertTrue(containsDotted(s.effectivePublic(), "org.apache.kafka.proj.OwnedClass")); + } + + @Test + void crossJarDuplicate_projectJarWins() throws IOException { + // Same binary name in both jars — the project jar is scanned first and keeps ownership. + AsmClassFactory.ClassBuilder dup = + AsmClassFactory.klass("org.apache.kafka.dup.Dup").access(Opcodes.ACC_PUBLIC).publicApi(); + File proj = TempJarBuilder.jar().addClass(dup).writeTo(tempDir, "proj.jar"); + // Re-build a new ClassBuilder for the ref jar to avoid sharing state with the above call. + File ref = TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("org.apache.kafka.dup.Dup").access(Opcodes.ACC_PUBLIC).publicApi()) + .writeTo(tempDir, "ref.jar"); + + ApiSurface s = ApiSurfaceScanner.scan(List.of(proj), List.of(ref)); + + assertEquals(proj, s.jarOf("org.apache.kafka.dup.Dup")); + assertTrue(containsDotted(s.directPublic(), "org.apache.kafka.dup.Dup"), + "project-jar entry establishes ownership so the class participates in iteration"); + } + + // Helpers + + private File projectJar(String fileName, AsmClassFactory.ClassBuilder... builders) throws IOException { + TempJarBuilder jar = TempJarBuilder.jar(); + for (AsmClassFactory.ClassBuilder b : builders) jar.addClass(b); + return jar.writeTo(tempDir, fileName); + } + + private static ApiSurface scan(File... projectJars) throws IOException { + return ApiSurfaceScanner.scan(List.of(projectJars), Collections.emptyList()); + } + + private static boolean containsDotted(java.util.Collection set, String dottedName) { + return set.stream().anyMatch(f -> f.dottedName().equals(dottedName)); + } +} diff --git a/api-checker/core/src/test/java/org/apache/kafka/apicheck/ApiSurfaceTest.java b/api-checker/core/src/test/java/org/apache/kafka/apicheck/ApiSurfaceTest.java new file mode 100644 index 0000000000000..42155a77c2ee3 --- /dev/null +++ b/api-checker/core/src/test/java/org/apache/kafka/apicheck/ApiSurfaceTest.java @@ -0,0 +1,200 @@ +/* + * 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.kafka.apicheck; + +import org.junit.jupiter.api.Test; +import org.objectweb.asm.Opcodes; + +import java.io.File; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ApiSurfaceTest { + + private static final File JAR_A = new File("/tmp/a.jar"); + private static final File JAR_B = new File("/tmp/b.jar"); + + @Test + void factsOf_acceptsBothBinaryAndDottedNames() { + ClassFacts inner = facts("org.apache.kafka.foo.Outer$Inner"); + ApiSurface surface = ApiSurface.builder().recordClass(inner, JAR_A).build(); + + assertSame(inner, surface.factsOf("org.apache.kafka.foo.Outer$Inner")); + assertSame(inner, surface.factsOf("org.apache.kafka.foo.Outer.Inner")); + } + + @Test + void factsOf_returnsNullForUnknownClass() { + ApiSurface surface = ApiSurface.builder().build(); + assertNull(surface.factsOf("org.apache.kafka.NotThere")); + } + + @Test + void jarOf_returnsRecordedJar() { + ClassFacts f = facts("org.apache.kafka.foo.Bar"); + ApiSurface surface = ApiSurface.builder().recordClass(f, JAR_A).build(); + assertEquals(JAR_A, surface.jarOf("org.apache.kafka.foo.Bar")); + assertNull(surface.jarOf("org.apache.kafka.NotThere")); + } + + @Test + void recordClass_jarRegistrationIsFirstWins() { + // The scanner already de-dupes by binary name before calling recordClass, but the builder + // defends with putIfAbsent on the jar map so jarOf stays stable if a duplicate slips through. + ClassFacts f = facts("org.apache.kafka.foo.Bar"); + ApiSurface surface = ApiSurface.builder() + .recordClass(f, JAR_A) + .recordClass(f, JAR_B) + .build(); + assertEquals(JAR_A, surface.jarOf("org.apache.kafka.foo.Bar")); + } + + @Test + void isEffectivelyPublic_acceptsBothNameForms() { + // isEffectivelyPublic walks the enclosing chain on facts. Inner inherits via Outer's @Public. + ClassFacts outer = facts("org.apache.kafka.foo.Outer", ClassFacts.Flag.PUBLIC_API); + ClassFacts inner = facts("org.apache.kafka.foo.Outer$Inner"); + ApiSurface surface = ApiSurface.builder() + .recordClass(outer, JAR_A) + .recordClass(inner, JAR_A) + .build(); + + assertTrue(surface.isEffectivelyPublic("org.apache.kafka.foo.Outer$Inner")); + assertTrue(surface.isEffectivelyPublic("org.apache.kafka.foo.Outer.Inner")); + } + + @Test + void isEffectivelyPublic_skipsMissingIntermediates() { + // Bug #5 regression: an anonymous/synthetic intermediate like Outer$1 is filtered out + // of the surface by ApiSurfaceScanner#isSyntheticOrAnonymous, but a named nested class + // *inside* the synthetic (Outer$1$Inner) should still inherit Outer's @Public. The walk + // has to step past the missing intermediate lexically rather than stopping at the gap. + ClassFacts outer = facts("org.apache.kafka.foo.Outer", ClassFacts.Flag.PUBLIC_API); + ApiSurface surface = ApiSurface.builder() + .recordClass(outer, JAR_A) + .build(); + + assertTrue(surface.isEffectivelyPublic("org.apache.kafka.foo.Outer$1$Inner"), + "anonymous-enclosed nested class must still inherit Outer's @Public"); + } + + @Test + void isEffectivelyPublic_falseWhenNotAnnotated() { + ClassFacts f = facts("org.apache.kafka.foo.Bar"); + ApiSurface surface = ApiSurface.builder().recordClass(f, JAR_A).build(); + assertFalse(surface.isEffectivelyPublic("org.apache.kafka.foo.Bar")); + assertFalse(surface.isEffectivelyPublic("org.apache.kafka.UnknownClass")); + } + + @Test + void isEffectivelyPublic_privateNestedOverridesInheritedPublic() { + ClassFacts outer = facts("org.apache.kafka.foo.Outer", ClassFacts.Flag.PUBLIC_API); + ClassFacts inner = facts("org.apache.kafka.foo.Outer$Inner", ClassFacts.Flag.PRIVATE_API); + ApiSurface surface = ApiSurface.builder() + .recordClass(outer, JAR_A).recordClass(inner, JAR_A) + .build(); + + assertTrue(surface.isEffectivelyPublic("org.apache.kafka.foo.Outer")); + assertFalse(surface.isEffectivelyPublic("org.apache.kafka.foo.Outer$Inner")); + } + + @Test + void isDeprecated_trueWhenClassItselfIsDeprecated() { + ClassFacts f = facts("org.apache.kafka.foo.Bar", ClassFacts.Flag.DEPRECATED); + ApiSurface surface = ApiSurface.builder().recordClass(f, JAR_A).build(); + assertTrue(surface.isDeprecated("org.apache.kafka.foo.Bar")); + } + + @Test + void isDeprecated_inheritsFromEnclosingClass() { + // Outer is @Deprecated; Inner is not directly annotated. The walk up the enclosing chain + // (Outer$Inner → Outer) finds the deprecation and propagates it. + ClassFacts outer = facts("org.apache.kafka.foo.Outer", ClassFacts.Flag.DEPRECATED); + ClassFacts inner = facts("org.apache.kafka.foo.Outer$Inner"); + ApiSurface surface = ApiSurface.builder() + .recordClass(outer, JAR_A) + .recordClass(inner, JAR_A) + .build(); + + assertTrue(surface.isDeprecated("org.apache.kafka.foo.Outer$Inner")); + assertTrue(surface.isDeprecated("org.apache.kafka.foo.Outer.Inner")); + } + + @Test + void isDeprecated_falseWhenNeitherSelfNorEnclosingIsDeprecated() { + ClassFacts outer = facts("org.apache.kafka.foo.Outer"); + ClassFacts inner = facts("org.apache.kafka.foo.Outer$Inner"); + ApiSurface surface = ApiSurface.builder() + .recordClass(outer, JAR_A) + .recordClass(inner, JAR_A) + .build(); + + assertFalse(surface.isDeprecated("org.apache.kafka.foo.Outer$Inner")); + } + + @Test + void isDeprecated_falseWhenClassNotInSurface() { + // factsOf returns null on the very first iteration; the walk exits cleanly with false. + ApiSurface surface = ApiSurface.builder().build(); + assertFalse(surface.isDeprecated("org.apache.kafka.NotThere")); + } + + @Test + void isDeprecated_falseWhenEnclosingNotInSurface() { + // Nested class is recorded but its outer isn't. The walk finds the inner (not deprecated), + // then looks up the missing outer, gets null, and exits with false. No inheritance possible + // without facts for the enclosing class. + ClassFacts inner = facts("org.apache.kafka.foo.Outer$Inner"); + ApiSurface surface = ApiSurface.builder().recordClass(inner, JAR_A).build(); + assertFalse(surface.isDeprecated("org.apache.kafka.foo.Outer$Inner")); + } + + @Test + void iterationSets_containWhatWasAdded() { + ClassFacts a = facts("org.apache.kafka.foo.A"); + ClassFacts b = facts("org.apache.kafka.foo.B"); + ApiSurface surface = ApiSurface.builder() + .recordClass(a, JAR_A).recordClass(b, JAR_A) + .addEffectivePublic(a) + .addDirectPublic(b) + .build(); + + assertEquals(1, surface.effectivePublic().size()); + assertTrue(surface.effectivePublic().contains(a)); + assertEquals(1, surface.directPublic().size()); + assertTrue(surface.directPublic().contains(b)); + } + + @Test + void iterationSets_areImmutable() { + ApiSurface surface = ApiSurface.builder().build(); + ClassFacts f = facts("org.apache.kafka.foo.Bar"); + assertThrows(UnsupportedOperationException.class, () -> surface.effectivePublic().add(f)); + assertThrows(UnsupportedOperationException.class, () -> surface.directPublic().add(f)); + } + + private static ClassFacts facts(String binaryName, ClassFacts.Flag... flags) { + ClassFacts.Builder b = ClassFacts.builder(binaryName).sourceAccess(Opcodes.ACC_PUBLIC); + for (ClassFacts.Flag flag : flags) b.addFlag(flag); + return b.build(); + } +} diff --git a/api-checker/core/src/test/java/org/apache/kafka/apicheck/CascadeValidatorTest.java b/api-checker/core/src/test/java/org/apache/kafka/apicheck/CascadeValidatorTest.java new file mode 100644 index 0000000000000..c015e7511fb69 --- /dev/null +++ b/api-checker/core/src/test/java/org/apache/kafka/apicheck/CascadeValidatorTest.java @@ -0,0 +1,391 @@ +/* + * 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.kafka.apicheck; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.objectweb.asm.Opcodes; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CascadeValidatorTest { + + private static final String OWNER_BIN = "org.apache.kafka.api.Owner"; + private static final String INTERNAL_BIN = "org.apache.kafka.internals.Internal"; + private static final String INTERNAL_DESC = "Lorg/apache/kafka/internals/Internal;"; + private static final String INTERNAL_INTERNAL_NAME = "org/apache/kafka/internals/Internal"; + + @TempDir + Path tempDir; + + @Test + void publicMethodWithInternalReturnType_emitsInvalidReturnType() throws IOException { + CheckResult r = run(owner() + .method(AsmClassFactory.method("leak").returns(INTERNAL_DESC))); + + assertEquals(1, r.violations().size()); + PublicApiViolation v = r.violations().get(0); + assertEquals("INVALID_RETURN_TYPE", v.getViolationType()); + assertEquals(OWNER_BIN, v.getClassName()); + assertEquals("leak", v.getMemberName()); + assertTrue(v.getDescription().contains(INTERNAL_BIN), + "description should name the leaked type: " + v.getDescription()); + } + + @Test + void publicMethodWithInternalParameter_emitsInvalidParameterType() throws IOException { + CheckResult r = run(owner() + .method(AsmClassFactory.method("take").param(INTERNAL_DESC))); + + assertEquals(1, r.violations().size()); + assertEquals("INVALID_PARAMETER_TYPE", r.violations().get(0).getViolationType()); + } + + @Test + void publicMethodWithInternalException_emitsInvalidExceptionType() throws IOException { + CheckResult r = run(owner() + .method(AsmClassFactory.method("boom").throwsExc(INTERNAL_INTERNAL_NAME))); + + assertEquals(1, r.violations().size()); + assertEquals("INVALID_EXCEPTION_TYPE", r.violations().get(0).getViolationType()); + } + + @Test + void arrayOfInternalType_recursesAndFlags() throws IOException { + // Array descriptors prepend "[" to the element descriptor. The validator must recurse + // through the array layer to reach the object element type. + CheckResult r = run(owner() + .method(AsmClassFactory.method("batch").returns("[" + INTERNAL_DESC))); + + assertEquals(1, r.violations().size()); + assertEquals("INVALID_RETURN_TYPE", r.violations().get(0).getViolationType()); + } + + @Test + void publicMethodWithInternalInGenericSignature_emitsParameterTypeViolation() throws IOException { + // The erased descriptor is `()Ljava/util/Map;` — no internal type. The generic signature + // `()Ljava/util/Map;` carries + // the internal type as a Map value parameter. Cascade must walk the signature. + CheckResult r = run(owner() + .method(AsmClassFactory.method("getStuff") + .returns("Ljava/util/Map;") + .signature("()Ljava/util/Map;"))); + + assertTrue(r.violations().stream().anyMatch(v -> "INVALID_PARAMETER_TYPE".equals(v.getViolationType()) + && v.getDescription().contains(INTERNAL_BIN)), + "generic type argument should surface as an INVALID_PARAMETER_TYPE; got: " + r.violations()); + } + + @Test + void publicFieldWithInternalInGenericSignature_emitsFieldTypeViolation() throws IOException { + // The erased descriptor is `Ljava/util/List;`. The signature + // `Ljava/util/List;` exposes Internal as a + // List element parameter. Cascade must walk the signature. + CheckResult r = run(owner() + .field(AsmClassFactory.field("things") + .ofType("Ljava/util/List;") + .signature("Ljava/util/List;"))); + + assertTrue(r.violations().stream().anyMatch(v -> "INVALID_FIELD_TYPE".equals(v.getViolationType()) + && v.getDescription().contains(INTERNAL_BIN)), + "generic field signature should surface as an INVALID_FIELD_TYPE; got: " + r.violations()); + } + + @Test + void publicClassExtendingInternalType_emitsSupertypeViolation() throws IOException { + // A @Public class whose superclass is an internal Kafka type exposes the supertype + // to consumers (it's part of the type's public contract — inherited methods, casts, + // etc.). The cascade catches this from the class-header visit. + CheckResult r = run(owner().superClass("org/apache/kafka/internals/Internal")); + + assertTrue(r.violations().stream().anyMatch(v -> "INVALID_SUPERTYPE".equals(v.getViolationType()) + && v.getDescription().contains(INTERNAL_BIN)), + "extending an internal type must trigger an INVALID_SUPERTYPE; got: " + r.violations()); + } + + @Test + void publicClassImplementingInternalInterface_emitsSupertypeViolation() throws IOException { + CheckResult r = run(owner().interfaces("org/apache/kafka/internals/Internal")); + + assertTrue(r.violations().stream().anyMatch(v -> "INVALID_SUPERTYPE".equals(v.getViolationType()) + && v.getDescription().contains(INTERNAL_BIN)), + "implementing an internal interface must trigger an INVALID_SUPERTYPE; got: " + r.violations()); + } + + @Test + void classLevelSuppress_silencesSupertypeViolation() throws IOException { + // Class-level @SuppressKafkaInternalApiUsage diverts the header leak to the + // suppressions list, same as for method-level cascade leaks. + CheckResult r = run(owner() + .suppress("legacy-base-class") + .superClass("org/apache/kafka/internals/Internal")); + + assertTrue(r.violations().isEmpty(), "class-level suppress should silence the header leak"); + assertTrue(r.suppressions().stream().anyMatch(s -> s.getDescription().contains("reason: legacy-base-class")), + "suppression must carry the annotation reason; got: " + r.suppressions()); + } + + @Test + void deprecatedInternalType_isNotFlagged() throws IOException { + // Internal is recorded with @Deprecated → out of scope on both sides. + CheckResult r = runWithExtras(owner() + .method(AsmClassFactory.method("legacy").returns(INTERNAL_DESC)), + facts(INTERNAL_BIN, ClassFacts.Flag.DEPRECATED)); + + assertTrue(r.violations().isEmpty(), + "deprecated referenced type must not trigger: " + r.violations()); + } + + @Test + void referenceToEffectivelyPublicType_isNotFlagged() throws IOException { + // Internal is in the membership set → counts as part of the public API surface. + CheckResult r = runWithEffectivelyPublic(owner() + .method(AsmClassFactory.method("ok").returns(INTERNAL_DESC)), + INTERNAL_BIN); + + assertTrue(r.violations().isEmpty()); + } + + @Test + void referenceToNonKafkaType_isNotFlagged() throws IOException { + // JDK types (java/util/Map) and third-party types are out of scope — the cascade rule + // only constrains references inside org.apache.kafka.*. + CheckResult r = run(owner() + .method(AsmClassFactory.method("safe") + .returns("Ljava/util/Map;") + .param("Lcom/example/External;"))); + + assertTrue(r.violations().isEmpty()); + } + + @Test + void privateMethod_isIgnored() throws IOException { + // Cascade only inspects externally-visible methods. Private leaks are tolerated + // because they're invisible to consumers. + CheckResult r = run(owner() + .method(AsmClassFactory.method("priv").access(Opcodes.ACC_PRIVATE).returns(INTERNAL_DESC))); + + assertTrue(r.violations().isEmpty()); + } + + @Test + void protectedMethod_emitsViolation() throws IOException { + // KIP-1265: protected members on an extensible @Public class are reachable to + // subclasses, so they count toward the public API surface and must not leak + // non-public types. + CheckResult r = run(owner() + .method(AsmClassFactory.method("prot").access(Opcodes.ACC_PROTECTED).returns(INTERNAL_DESC))); + + assertEquals(1, r.violations().size()); + assertEquals("INVALID_RETURN_TYPE", r.violations().get(0).getViolationType()); + } + + @Test + void publicFieldOfInternalType_emitsInvalidFieldType() throws IOException { + // KIP-1265: field types are part of the cascade — a public field of an internal type + // leaks the internal type just like a method signature does. + CheckResult r = run(owner() + .field(AsmClassFactory.field("leakField").ofType(INTERNAL_DESC))); + + assertEquals(1, r.violations().size()); + PublicApiViolation v = r.violations().get(0); + assertEquals("INVALID_FIELD_TYPE", v.getViolationType()); + assertEquals(OWNER_BIN, v.getClassName()); + assertEquals("leakField", v.getMemberName()); + assertTrue(v.getDescription().contains(INTERNAL_BIN), + "description should name the leaked type: " + v.getDescription()); + } + + @Test + void protectedFieldOfInternalType_emitsInvalidFieldType() throws IOException { + // protected fields on an extensible @Public class are also part of the API surface. + CheckResult r = run(owner() + .field(AsmClassFactory.field("protLeak").access(Opcodes.ACC_PROTECTED).ofType(INTERNAL_DESC))); + + assertEquals(1, r.violations().size()); + assertEquals("INVALID_FIELD_TYPE", r.violations().get(0).getViolationType()); + } + + @Test + void privateFieldOfInternalType_isIgnored() throws IOException { + CheckResult r = run(owner() + .field(AsmClassFactory.field("hidden").access(Opcodes.ACC_PRIVATE).ofType(INTERNAL_DESC))); + + assertTrue(r.violations().isEmpty()); + } + + @Test + void arrayFieldOfInternalType_recursesAndFlags() throws IOException { + CheckResult r = run(owner() + .field(AsmClassFactory.field("buf").ofType("[" + INTERNAL_DESC))); + + assertEquals(1, r.violations().size()); + assertEquals("INVALID_FIELD_TYPE", r.violations().get(0).getViolationType()); + } + + @Test + void fieldLevelSuppress_movesFieldViolationToSuppressions() throws IOException { + CheckResult r = run(owner() + .field(AsmClassFactory.field("leak").ofType(INTERNAL_DESC).suppress("legacy-field"))); + + assertTrue(r.violations().isEmpty()); + assertEquals(1, r.suppressions().size()); + assertTrue(r.suppressions().get(0).getDescription().contains("reason: legacy-field")); + } + + @Test + void classLevelSuppress_silencesFieldLeaks() throws IOException { + CheckResult r = run(owner() + .suppress("legacy-api") + .field(AsmClassFactory.field("leak").ofType(INTERNAL_DESC))); + + assertTrue(r.violations().isEmpty()); + assertEquals(1, r.suppressions().size()); + assertTrue(r.suppressions().get(0).getDescription().contains("reason: legacy-api")); + } + + @Test + void syntheticField_isIgnored() throws IOException { + // Compiler-generated synthetic fields (e.g. $assertionsDisabled) are not source-level API. + CheckResult r = run(owner() + .field(AsmClassFactory.field("synth") + .access(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC) + .ofType(INTERNAL_DESC))); + + assertTrue(r.violations().isEmpty()); + } + + @Test + void syntheticMethod_isIgnored() throws IOException { + // Bridge / ACC_SYNTHETIC methods are compiler-generated, not source-level API. + CheckResult r = run(owner() + .method(AsmClassFactory.method("bridge").bridge().returns(INTERNAL_DESC)) + .method(AsmClassFactory.method("synth").synthetic().returns(INTERNAL_DESC))); + + assertTrue(r.violations().isEmpty()); + } + + @Test + void classLevelSuppress_movesAllViolationsToSuppressions() throws IOException { + CheckResult r = run(owner() + .suppress("legacy-api") + .method(AsmClassFactory.method("leak").returns(INTERNAL_DESC))); + + assertTrue(r.violations().isEmpty(), "class-level suppress should silence every method"); + assertEquals(1, r.suppressions().size()); + PublicApiViolation s = r.suppressions().get(0); + assertEquals("SUPPRESSED", s.getViolationType()); + assertTrue(s.getDescription().contains("reason: legacy-api"), + "suppression must carry the annotation's reason: " + s.getDescription()); + } + + @Test + void methodLevelSuppress_overridesClassLevelReason() throws IOException { + // Class-level "class-reason" applies to methods without their own annotation; + // a method-level annotation wins for that method. + CheckResult r = run(owner() + .suppress("class-reason") + .method(AsmClassFactory.method("m1").returns(INTERNAL_DESC).suppress("method-reason")) + .method(AsmClassFactory.method("m2").returns(INTERNAL_DESC))); + + assertTrue(r.violations().isEmpty()); + assertEquals(2, r.suppressions().size()); + assertTrue(r.suppressions().stream().anyMatch(v -> + v.getMemberName().equals("m1") && v.getDescription().contains("reason: method-reason"))); + assertTrue(r.suppressions().stream().anyMatch(v -> + v.getMemberName().equals("m2") && v.getDescription().contains("reason: class-reason"))); + } + + @Test + void suppressWithNoValue_recordsNoReasonGiven() throws IOException { + // @SuppressKafkaInternalApiUsage on its own (no value()) → ReasonCaptureVisitor records + // an empty reason, which the reporter renders as "(no reason given)". + CheckResult r = run(owner() + .method(AsmClassFactory.method("leak").returns(INTERNAL_DESC).suppress(null))); + + assertTrue(r.violations().isEmpty()); + assertEquals(1, r.suppressions().size()); + assertTrue(r.suppressions().get(0).getDescription().contains("reason: (no reason given)"), + "empty reason must render as '(no reason given)': " + + r.suppressions().get(0).getDescription()); + } + + @Test + void jarOfReturnsNull_classIsSilentlySkipped() throws IOException { + // Class is in the cascade iteration set but no jar is recorded for it. The validator + // bails on the missing jar without throwing — defensive against scan/cascade desync. + ClassFacts orphan = facts("org.apache.kafka.api.Orphan", ClassFacts.Flag.PUBLIC_API); + ApiSurface surface = ApiSurface.builder() + .addEffectivePublic(orphan) + .addEffectivePublic(orphan) + .build(); + + CheckResult r = CascadeValidator.validate(surface); + assertTrue(r.violations().isEmpty()); + assertTrue(r.suppressions().isEmpty()); + } + + // ----- helpers ----- + + /** Owner class scaffolding shared by every cascade test: top-level public, audience @Public. */ + private static AsmClassFactory.ClassBuilder owner() { + return AsmClassFactory.klass(OWNER_BIN).access(Opcodes.ACC_PUBLIC).publicApi(); + } + + private CheckResult run(AsmClassFactory.ClassBuilder owner) throws IOException { + return runWithExtras(owner); + } + + /** Validate against a surface that registers {@code extras} in addition to the owner class. */ + private CheckResult runWithExtras(AsmClassFactory.ClassBuilder owner, ClassFacts... extras) throws IOException { + File jar = TempJarBuilder.jar().addClass(owner).writeTo(tempDir, "x.jar"); + ClassFacts ownerFacts = facts(owner.binaryName(), ClassFacts.Flag.PUBLIC_API); + ApiSurface.Builder b = ApiSurface.builder() + .recordClass(ownerFacts, jar) + .addEffectivePublic(ownerFacts) + .addEffectivePublic(ownerFacts); + for (ClassFacts f : extras) b.recordClass(f, jar); + return CascadeValidator.validate(b.build()); + } + + /** Validate against a surface where the named extras are also marked effectively public. */ + private CheckResult runWithEffectivelyPublic(AsmClassFactory.ClassBuilder owner, + String... effectivelyPublicBinaryNames) throws IOException { + File jar = TempJarBuilder.jar().addClass(owner).writeTo(tempDir, "x.jar"); + ClassFacts ownerFacts = facts(owner.binaryName(), ClassFacts.Flag.PUBLIC_API); + ApiSurface.Builder b = ApiSurface.builder() + .recordClass(ownerFacts, jar) + .addEffectivePublic(ownerFacts) + .addEffectivePublic(ownerFacts); + for (String name : effectivelyPublicBinaryNames) { + ClassFacts f = facts(name, ClassFacts.Flag.PUBLIC_API); + b.recordClass(f, jar).addEffectivePublic(f); + } + return CascadeValidator.validate(b.build()); + } + + private static ClassFacts facts(String binaryName, ClassFacts.Flag... flags) { + ClassFacts.Builder b = ClassFacts.builder(binaryName).sourceAccess(Opcodes.ACC_PUBLIC); + for (ClassFacts.Flag f : flags) b.addFlag(f); + return b.build(); + } +} diff --git a/api-checker/core/src/test/java/org/apache/kafka/apicheck/JavadocConsistencyValidatorTest.java b/api-checker/core/src/test/java/org/apache/kafka/apicheck/JavadocConsistencyValidatorTest.java new file mode 100644 index 0000000000000..ebd186d942a49 --- /dev/null +++ b/api-checker/core/src/test/java/org/apache/kafka/apicheck/JavadocConsistencyValidatorTest.java @@ -0,0 +1,206 @@ +/* + * 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.kafka.apicheck; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.objectweb.asm.Opcodes; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class JavadocConsistencyValidatorTest { + + private static final File DUMMY_JAR = new File("ignored"); + + @TempDir + Path tempDir; + + @Test + void directPublicMissingFromJavadoc_emitsMissingJavadoc() throws IOException { + ClassFacts bar = factsPublic("org.apache.kafka.foo.Bar"); + ApiSurface surface = ApiSurface.builder() + .recordClass(bar, DUMMY_JAR) + .addDirectPublic(bar) + .addEffectivePublic(bar) + .build(); + File javadocJar = TempJarBuilder.jar().writeTo(tempDir, "javadoc.jar"); + + CheckResult result = JavadocConsistencyValidator.validate(javadocJar, surface); + + assertEquals(1, result.violations().size()); + PublicApiViolation v = result.violations().get(0); + assertEquals("MISSING_JAVADOC", v.getViolationType()); + assertEquals("org.apache.kafka.foo.Bar", v.getClassName()); + assertTrue(result.suppressions().isEmpty()); + } + + @Test + void htmlClassNotEffectivelyPublic_emitsMissingAnnotation() throws IOException { + // HTML claims a class is documented; the surface has nothing on it. + ApiSurface surface = ApiSurface.builder().build(); + File javadocJar = TempJarBuilder.jar() + .addHtml("org/apache/kafka/foo/Sneaky.html", "") + .writeTo(tempDir, "javadoc.jar"); + + CheckResult result = JavadocConsistencyValidator.validate(javadocJar, surface); + + assertEquals(1, result.violations().size()); + PublicApiViolation v = result.violations().get(0); + assertEquals("MISSING_PUBLICAPI_ANNOTATION", v.getViolationType()); + assertEquals("org.apache.kafka.foo.Sneaky", v.getClassName()); + } + + @Test + void effectivelyPublicViaInheritance_isNotFlagged() throws IOException { + // Inner has no direct @Public but inherits it from Outer. Real javadoc emits nested-class + // pages using the dotted form (Outer.Inner.html), which the validator must recognise. + ClassFacts outer = factsPublic("org.apache.kafka.foo.Outer"); + ClassFacts inner = factsPlain("org.apache.kafka.foo.Outer$Inner"); + ApiSurface surface = ApiSurface.builder() + .recordClass(outer, DUMMY_JAR).recordClass(inner, DUMMY_JAR) + .addDirectPublic(outer) + .addEffectivePublic(outer).addEffectivePublic(inner) + .build(); + File javadocJar = TempJarBuilder.jar() + .addHtml("org/apache/kafka/foo/Outer.html", "") + .addHtml("org/apache/kafka/foo/Outer.Inner.html", "") + .writeTo(tempDir, "javadoc.jar"); + + CheckResult result = JavadocConsistencyValidator.validate(javadocJar, surface); + + assertTrue(result.violations().isEmpty(), + "perfect match (direct + inherited) should yield no violations: " + result.violations()); + } + + @Test + void deprecatedClassInJavadoc_isFilteredOut() throws IOException { + // OldClass is deprecated and not in directPublic — would normally trip MISSING_PUBLICAPI_ANNOTATION, + // but isDeprecated removes it from the HTML set first. + ClassFacts deprecated = factsBuilder("org.apache.kafka.foo.OldClass") + .addFlag(ClassFacts.Flag.DEPRECATED) + .build(); + ApiSurface surface = ApiSurface.builder().recordClass(deprecated, DUMMY_JAR).build(); + File javadocJar = TempJarBuilder.jar() + .addHtml("org/apache/kafka/foo/OldClass.html", "") + .writeTo(tempDir, "javadoc.jar"); + + CheckResult result = JavadocConsistencyValidator.validate(javadocJar, surface); + assertTrue(result.violations().isEmpty(), + "deprecated classes are out of scope on both validation sides"); + } + + @Test + void perfectMatch_noViolations() throws IOException { + ClassFacts bar = factsPublic("org.apache.kafka.foo.Bar"); + ApiSurface surface = ApiSurface.builder() + .recordClass(bar, DUMMY_JAR) + .addDirectPublic(bar) + .addEffectivePublic(bar) + .build(); + File javadocJar = TempJarBuilder.jar() + .addHtml("org/apache/kafka/foo/Bar.html", "") + .writeTo(tempDir, "javadoc.jar"); + + CheckResult result = JavadocConsistencyValidator.validate(javadocJar, surface); + assertTrue(result.violations().isEmpty()); + assertTrue(result.suppressions().isEmpty()); + } + + @Test + void structuralHtmlPages_areIgnored() throws IOException { + // Javadoc emits many non-class HTML files alongside class pages. The validator must skip + // them; otherwise every javadoc jar trips bogus MISSING_PUBLICAPI_ANNOTATION violations. + ApiSurface surface = ApiSurface.builder().build(); + File javadocJar = TempJarBuilder.jar() + .addHtml("org/apache/kafka/foo/package-summary.html", "") + .addHtml("org/apache/kafka/foo/overview-tree.html", "") + .addHtml("org/apache/kafka/foo/index-all.html", "") + .addHtml("index.html", "") + .writeTo(tempDir, "javadoc.jar"); + + CheckResult result = JavadocConsistencyValidator.validate(javadocJar, surface); + assertTrue(result.violations().isEmpty(), + "structural HTML must not be misread as class pages: " + result.violations()); + } + + @Test + void nonKafkaHtml_isIgnored() throws IOException { + ApiSurface surface = ApiSurface.builder().build(); + File javadocJar = TempJarBuilder.jar() + .addHtml("com/example/External.html", "") + .addHtml("java/util/HashMap.html", "") + .writeTo(tempDir, "javadoc.jar"); + + CheckResult result = JavadocConsistencyValidator.validate(javadocJar, surface); + assertTrue(result.violations().isEmpty()); + } + + @Test + void emptyJavadocJar_flagsAllDirectPublicClasses() throws IOException { + ClassFacts a = factsPublic("org.apache.kafka.foo.A"); + ClassFacts b = factsPublic("org.apache.kafka.foo.B"); + ApiSurface surface = ApiSurface.builder() + .recordClass(a, DUMMY_JAR).recordClass(b, DUMMY_JAR) + .addDirectPublic(a).addDirectPublic(b) + .addEffectivePublic(a).addEffectivePublic(b) + .build(); + File javadocJar = TempJarBuilder.jar().writeTo(tempDir, "javadoc.jar"); + + CheckResult result = JavadocConsistencyValidator.validate(javadocJar, surface); + + assertEquals(2, result.violations().size()); + assertTrue(result.violations().stream() + .allMatch(v -> "MISSING_JAVADOC".equals(v.getViolationType()))); + } + + @Test + void suppressionsListIsAlwaysEmpty_evenWithViolations() throws IOException { + // JavadocConsistencyValidator doesn't carry a suppression mechanism — the CheckResult + // always has an empty suppressions list. Callers compose validators uniformly, so the + // shape matters even when no suppressions are possible. + ClassFacts bar = factsPublic("org.apache.kafka.foo.Bar"); + ApiSurface surface = ApiSurface.builder() + .recordClass(bar, DUMMY_JAR) + .addDirectPublic(bar) + .build(); + File javadocJar = TempJarBuilder.jar().writeTo(tempDir, "javadoc.jar"); + + CheckResult result = JavadocConsistencyValidator.validate(javadocJar, surface); + assertFalse(result.violations().isEmpty()); + assertNotNull(result.suppressions()); + assertTrue(result.suppressions().isEmpty()); + } + + private static ClassFacts factsPublic(String binaryName) { + return factsBuilder(binaryName).addFlag(ClassFacts.Flag.PUBLIC_API).build(); + } + + private static ClassFacts factsPlain(String binaryName) { + return factsBuilder(binaryName).build(); + } + + private static ClassFacts.Builder factsBuilder(String binaryName) { + return ClassFacts.builder(binaryName).sourceAccess(Opcodes.ACC_PUBLIC); + } +} diff --git a/api-checker/core/src/test/java/org/apache/kafka/apicheck/PluginDeveloperApiUsageScannerTest.java b/api-checker/core/src/test/java/org/apache/kafka/apicheck/PluginDeveloperApiUsageScannerTest.java new file mode 100644 index 0000000000000..dee7f5aaef140 --- /dev/null +++ b/api-checker/core/src/test/java/org/apache/kafka/apicheck/PluginDeveloperApiUsageScannerTest.java @@ -0,0 +1,509 @@ +/* + * 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.kafka.apicheck; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import java.util.function.Predicate; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PluginDeveloperApiUsageScannerTest { + + @TempDir + Path tempDir; + + @Test + void scan_noRoots_returnsEmpty() throws IOException { + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(true)); + CheckResult result = scanner.scan(Collections.emptyList()); + assertTrue(result.violations().isEmpty()); + assertTrue(result.suppressions().isEmpty()); + } + + @Test + void scan_consumerReferencesPublicApiClass_returnsNoViolations() throws IOException { + File classFile = writeClassFile("com/example/PublicConsumer", + generateConsumerReferencing("com/example/PublicConsumer", "org/apache/kafka/clients/producer/KafkaProducer")); + + Predicate isPublic = name -> "org.apache.kafka.clients.producer.KafkaProducer".equals(name); + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(isPublic); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + assertTrue(violations.isEmpty(), + "Reference to an @InterfaceAudience.Public class must not be reported, but got: " + violations); + } + + @Test + void scan_consumerReferencesInternalApiClass_returnsViolation() throws IOException { + File classFile = writeClassFile("com/example/InternalConsumer", + generateConsumerReferencing("com/example/InternalConsumer", "org/apache/kafka/internals/SecretCabal")); + + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + assertFalse(violations.isEmpty(), "Reference to an internal Kafka class must be reported"); + PublicApiViolation v = violations.get(0); + assertEquals("INTERNAL_API_USAGE", v.getViolationType()); + assertEquals("org.apache.kafka.internals.SecretCabal", v.getClassName()); + assertTrue(v.getDescription().contains("com.example.InternalConsumer"), + "violation must name the consumer class. got: " + v.getDescription()); + } + + @Test + void scan_ignoresNonKafkaReferences() throws IOException { + File classFile = writeClassFile("com/example/JdkConsumer", + generateConsumerReferencing("com/example/JdkConsumer", "java/util/HashMap")); + + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + assertTrue(violations.isEmpty(), + "References to non-Kafka classes (e.g. JDK) must not be reported, got: " + violations); + } + + @Test + void scan_classesPackagedInJar_areScanned() throws IOException { + byte[] internalBytes = generateConsumerReferencing( + "com/example/JarConsumer", "org/apache/kafka/internals/Hidden"); + File jar = tempDir.resolve("consumer.jar").toFile(); + try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jar))) { + jos.putNextEntry(new JarEntry("com/example/JarConsumer.class")); + jos.write(internalBytes); + jos.closeEntry(); + } + + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + List violations = scanner.scan(List.of(jar)).violations(); + + assertFalse(violations.isEmpty(), "scan of jar should find the internal reference"); + assertEquals("org.apache.kafka.internals.Hidden", violations.get(0).getClassName()); + } + + @Test + void scan_classWithKafkaFieldOfInternalType_returnsViolation() throws IOException { + // Different bytecode shape: a field whose type is an internal Kafka class. + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC, "com/example/FieldHolder", null, "java/lang/Object", null); + cw.visitField(Opcodes.ACC_PRIVATE, "secret", "Lorg/apache/kafka/internals/Hidden;", null, null).visitEnd(); + // default ctor + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + cw.visitEnd(); + File classFile = writeClassFile("com/example/FieldHolder", cw.toByteArray()); + + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + assertTrue(violations.stream().anyMatch(v -> "org.apache.kafka.internals.Hidden".equals(v.getClassName())), + "field-type reference must be reported, got: " + violations); + } + + @Test + void scan_classLevelSuppressionAnnotation_skipsViolations() throws IOException { + byte[] bytes = generateConsumerReferencing( + "com/example/SuppressedClass", "org/apache/kafka/internals/Hidden", + ClassAnnotation.suppress("ports legacy adapter; tracked in JIRA-1234"), + MethodAnnotations.none()); + File classFile = writeClassFile("com/example/SuppressedClass", bytes); + + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + CheckResult result = scanner.scan(List.of(classFile.getParentFile())); + + assertTrue(result.violations().isEmpty(), + "Class-level @SuppressKafkaInternalApiUsage must suppress all violations; got: " + result.violations()); + assertFalse(result.suppressions().isEmpty(), + "suppressions list must record the skipped reference so it shows in the report"); + PublicApiViolation s = result.suppressions().get(0); + assertEquals("SUPPRESSED_INTERNAL_API_USAGE", s.getViolationType()); + assertTrue(s.getDescription().contains("ports legacy adapter; tracked in JIRA-1234"), + "suppression description must carry the annotation's reason; got: " + s.getDescription()); + } + + @Test + void scan_methodLevelSuppression_skipsOnlyThatMethod() throws IOException { + byte[] bytes = generateConsumerWithTwoMethods( + "com/example/PartiallySuppressed", + "org/apache/kafka/internals/Hidden", + MethodAnnotations.suppressOn("useIt", "intentional fallback")); + File classFile = writeClassFile("com/example/PartiallySuppressed", bytes); + + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + // The other method ("alsoUseIt") is not suppressed -- it must still report. + assertEquals(1, violations.size(), + "method-level suppression must only affect that method; got: " + violations); + assertEquals("alsoUseIt", violations.get(0).getMemberName(), + "unsuppressed method should be the one reported"); + } + + @Test + void scan_suppressionWithoutReason_stillSuppresses() throws IOException { + byte[] bytes = generateConsumerReferencing( + "com/example/SuppressedNoReason", "org/apache/kafka/internals/Hidden", + ClassAnnotation.suppress(null), // annotation present, no value() + MethodAnnotations.none()); + File classFile = writeClassFile("com/example/SuppressedNoReason", bytes); + + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + assertTrue(violations.isEmpty(), + "@SuppressKafkaInternalApiUsage with no reason must still suppress; got: " + violations); + } + + @Test + void scan_nestedPrivateOverride_isFlagged_evenWhenOuterIsPublic() throws IOException { + // KIP-1265: a nested class explicitly marked @InterfaceAudience.Private must override an + // inherited @Public from its outer. The predicate is given the full nested name; a Private + // override must propagate through it, so a reference to org/apache/kafka/Outer$Inner is a + // violation even though Outer alone is Public. + File classFile = writeClassFile("com/example/NestedConsumer", + generateConsumerReferencing("com/example/NestedConsumer", "org/apache/kafka/Outer$Inner")); + + // Outer is public, but the nested Outer$Inner is explicitly Private. + Predicate audience = name -> "org.apache.kafka.Outer".equals(name); + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(audience); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + assertFalse(violations.isEmpty(), + "Reference to a Private-nested type must be flagged even when its outer is Public; got: " + violations); + assertEquals("org.apache.kafka.Outer$Inner", violations.get(0).getClassName()); + } + + @Test + void scan_tryCatchOnInternalException_isFlagged() throws IOException { + // `catch (InternalKafkaException ignored)` where the variable is never used leaves the + // only reference to the exception type in the exception-handler table — visitTryCatchBlock. + // Without that visitor override the scanner would miss it. + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC, "com/example/CatchConsumer", null, "java/lang/Object", null); + MethodVisitor ctor = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + ctor.visitCode(); + ctor.visitVarInsn(Opcodes.ALOAD, 0); + ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + ctor.visitInsn(Opcodes.RETURN); + ctor.visitMaxs(0, 0); + ctor.visitEnd(); + + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "doIt", "()V", null, null); + mv.visitCode(); + org.objectweb.asm.Label start = new org.objectweb.asm.Label(); + org.objectweb.asm.Label end = new org.objectweb.asm.Label(); + org.objectweb.asm.Label handler = new org.objectweb.asm.Label(); + org.objectweb.asm.Label after = new org.objectweb.asm.Label(); + mv.visitTryCatchBlock(start, end, handler, "org/apache/kafka/internals/Boom"); + mv.visitLabel(start); + // empty try body + mv.visitLabel(end); + mv.visitJumpInsn(Opcodes.GOTO, after); + mv.visitLabel(handler); + mv.visitInsn(Opcodes.POP); + mv.visitLabel(after); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + cw.visitEnd(); + + File classFile = writeClassFile("com/example/CatchConsumer", cw.toByteArray()); + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + assertTrue(violations.stream().anyMatch(v -> "org.apache.kafka.internals.Boom".equals(v.getClassName())), + "exception-table entry must be reported; got: " + violations); + } + + @Test + void scan_methodHeaderRefBuffering_returnTypeFlushedAtVisitCode() throws IOException { + // The method-header ref (return type from the descriptor) is buffered until + // visitCode fires — that's when the method-level @SuppressKafkaInternalApiUsage has + // been visited and we know the effective reason. A non-suppressed method must still + // produce the violation. + byte[] bytes = generateMethodWithInternalReturnType("com/example/HeaderRef", + "fetch", "Lorg/apache/kafka/internals/Hidden;", null); + File classFile = writeClassFile("com/example/HeaderRef", bytes); + + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + assertTrue(violations.stream().anyMatch(v -> "org.apache.kafka.internals.Hidden".equals(v.getClassName())), + "method-header return-type ref must flush as a violation; got: " + violations); + } + + @Test + void scan_abstractMethodHeaderRef_flushedAtVisitEnd() throws IOException { + // Abstract methods have no body, so ASM never fires visitCode. The scanner's visitEnd + // safety net must flush the buffered header refs anyway, otherwise an abstract method's + // internal return/param/exception types would silently slip through. + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, + "com/example/AbstractConsumer", null, "java/lang/Object", null); + + MethodVisitor ctor = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + ctor.visitCode(); + ctor.visitVarInsn(Opcodes.ALOAD, 0); + ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + ctor.visitInsn(Opcodes.RETURN); + ctor.visitMaxs(0, 0); + ctor.visitEnd(); + + // public abstract Hidden fetch(); — no body, no visitCode, no visitMaxs. + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, + "fetch", "()Lorg/apache/kafka/internals/Hidden;", null, null); + mv.visitEnd(); + cw.visitEnd(); + + File classFile = writeClassFile("com/example/AbstractConsumer", cw.toByteArray()); + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + List violations = scanner.scan(List.of(classFile.getParentFile())).violations(); + + assertTrue(violations.stream().anyMatch(v -> "org.apache.kafka.internals.Hidden".equals(v.getClassName())), + "abstract-method header ref must be flushed at visitEnd; got: " + violations); + } + + @Test + void scan_methodHeaderRefBuffering_methodLevelSuppressDivertsToSuppressions() throws IOException { + // Same method header as the previous test, but the method carries + // @SuppressKafkaInternalApiUsage. visitCode flushes the buffered header refs using the + // effective reason (method-level wins over class-level), so they land in suppressions. + byte[] bytes = generateMethodWithInternalReturnType("com/example/SuppressedHeader", + "fetch", "Lorg/apache/kafka/internals/Hidden;", "header-ref reason"); + File classFile = writeClassFile("com/example/SuppressedHeader", bytes); + + PluginDeveloperApiUsageScanner scanner = new PluginDeveloperApiUsageScanner(always(false)); + CheckResult r = scanner.scan(List.of(classFile.getParentFile())); + + assertTrue(r.violations().isEmpty(), + "method-level suppress must divert the buffered header ref; got violations: " + r.violations()); + assertTrue(r.suppressions().stream().anyMatch(s -> s.getDescription().contains("reason: header-ref reason")), + "suppression list must carry the method's reason; got: " + r.suppressions()); + } + + /** + * Generate a class with a single method whose return type descriptor names an internal + * Kafka type. If {@code suppressReason} is non-null, the method carries + * {@code @SuppressKafkaInternalApiUsage(suppressReason)} (or no value when ""). + */ + private static byte[] generateMethodWithInternalReturnType(String consumerInternalName, + String methodName, + String returnDescriptor, + String suppressReason) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC, consumerInternalName, null, "java/lang/Object", null); + + MethodVisitor ctor = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + ctor.visitCode(); + ctor.visitVarInsn(Opcodes.ALOAD, 0); + ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + ctor.visitInsn(Opcodes.RETURN); + ctor.visitMaxs(0, 0); + ctor.visitEnd(); + + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, methodName, "()" + returnDescriptor, null, null); + if (suppressReason != null) { + AnnotationVisitor av = mv.visitAnnotation(SUPPRESS_DESC, true); + if (!suppressReason.isEmpty()) { + av.visit("value", suppressReason); + } + av.visitEnd(); + } + mv.visitCode(); // triggers the header-ref flush in the scanner's visitor + mv.visitInsn(Opcodes.ACONST_NULL); + mv.visitInsn(Opcodes.ARETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + cw.visitEnd(); + return cw.toByteArray(); + } + + /** Build a class with a default ctor and a method that loads a class constant of {@code internalNameOfReferenced}. */ + private static byte[] generateConsumerReferencing(String consumerInternalName, String internalNameOfReferenced) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC, consumerInternalName, null, "java/lang/Object", null); + + // default ctor + MethodVisitor ctor = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + ctor.visitCode(); + ctor.visitVarInsn(Opcodes.ALOAD, 0); + ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + ctor.visitInsn(Opcodes.RETURN); + ctor.visitMaxs(0, 0); + ctor.visitEnd(); + + // public void useIt() { Class c = .class; } + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "useIt", "()V", null, null); + mv.visitCode(); + mv.visitLdcInsn(org.objectweb.asm.Type.getObjectType(internalNameOfReferenced)); + mv.visitInsn(Opcodes.POP); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + + cw.visitEnd(); + return cw.toByteArray(); + } + + private File writeClassFile(String internalName, byte[] bytes) throws IOException { + File classFile = tempDir.resolve(internalName.replace('/', '_') + ".class").toFile(); + Files.write(classFile.toPath(), bytes); + return classFile; + } + + private static Predicate always(boolean value) { + return s -> value; + } + + // --- suppression-aware test helpers ------------------------------------------------- + + private static final String SUPPRESS_DESC = + "Lorg/apache/kafka/common/annotation/SuppressKafkaInternalApiUsage;"; + + /** Class-level annotation descriptor — empty = no class annotation. */ + private static final class ClassAnnotation { + final String reason; // null reason => annotation present with no value(); empty marker => no annotation + final boolean present; + private ClassAnnotation(boolean present, String reason) { + this.present = present; + this.reason = reason; + } + static ClassAnnotation none() { + return new ClassAnnotation(false, null); + } + static ClassAnnotation suppress(String reason) { + return new ClassAnnotation(true, reason); + } + } + + /** Per-method suppression directives. */ + private static final class MethodAnnotations { + final String suppressedMethod; + final String reason; + private MethodAnnotations(String suppressedMethod, String reason) { + this.suppressedMethod = suppressedMethod; + this.reason = reason; + } + static MethodAnnotations none() { + return new MethodAnnotations(null, null); + } + static MethodAnnotations suppressOn(String methodName, String reason) { + return new MethodAnnotations(methodName, reason); + } + } + + /** Overload that also writes class-level + method-level suppression annotations. */ + private static byte[] generateConsumerReferencing(String consumerInternalName, + String internalNameOfReferenced, + ClassAnnotation classAnnotation, + MethodAnnotations methodAnnotations) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC, consumerInternalName, null, "java/lang/Object", null); + + if (classAnnotation.present) { + AnnotationVisitor av = cw.visitAnnotation(SUPPRESS_DESC, true); + if (classAnnotation.reason != null) { + av.visit("value", classAnnotation.reason); + } + av.visitEnd(); + } + + // default ctor + MethodVisitor ctor = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + ctor.visitCode(); + ctor.visitVarInsn(Opcodes.ALOAD, 0); + ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + ctor.visitInsn(Opcodes.RETURN); + ctor.visitMaxs(0, 0); + ctor.visitEnd(); + + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "useIt", "()V", null, null); + if ("useIt".equals(methodAnnotations.suppressedMethod)) { + AnnotationVisitor mav = mv.visitAnnotation(SUPPRESS_DESC, true); + if (methodAnnotations.reason != null) { + mav.visit("value", methodAnnotations.reason); + } + mav.visitEnd(); + } + mv.visitCode(); + mv.visitLdcInsn(org.objectweb.asm.Type.getObjectType(internalNameOfReferenced)); + mv.visitInsn(Opcodes.POP); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + + cw.visitEnd(); + return cw.toByteArray(); + } + + /** Two methods both referencing the same internal class, with a suppression on one. */ + private static byte[] generateConsumerWithTwoMethods(String consumerInternalName, + String internalNameOfReferenced, + MethodAnnotations methodAnnotations) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC, consumerInternalName, null, "java/lang/Object", null); + + // default ctor + MethodVisitor ctor = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + ctor.visitCode(); + ctor.visitVarInsn(Opcodes.ALOAD, 0); + ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + ctor.visitInsn(Opcodes.RETURN); + ctor.visitMaxs(0, 0); + ctor.visitEnd(); + + for (String methodName : List.of("useIt", "alsoUseIt")) { + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, methodName, "()V", null, null); + if (methodName.equals(methodAnnotations.suppressedMethod)) { + AnnotationVisitor mav = mv.visitAnnotation(SUPPRESS_DESC, true); + if (methodAnnotations.reason != null) { + mav.visit("value", methodAnnotations.reason); + } + mav.visitEnd(); + } + mv.visitCode(); + mv.visitLdcInsn(org.objectweb.asm.Type.getObjectType(internalNameOfReferenced)); + mv.visitInsn(Opcodes.POP); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + cw.visitEnd(); + return cw.toByteArray(); + } +} diff --git a/api-checker/core/src/test/java/org/apache/kafka/apicheck/PublicApiCheckerTest.java b/api-checker/core/src/test/java/org/apache/kafka/apicheck/PublicApiCheckerTest.java new file mode 100644 index 0000000000000..9ca4e05141799 --- /dev/null +++ b/api-checker/core/src/test/java/org/apache/kafka/apicheck/PublicApiCheckerTest.java @@ -0,0 +1,216 @@ +/* + * 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.kafka.apicheck; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.objectweb.asm.Opcodes; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Tests for the {@link PublicApiChecker} facade: surface construction, {@code isPublicApi} + * predicate semantics, and merged results from {@link JavadocConsistencyValidator} + + * {@link CascadeValidator} + {@link PluginDeveloperApiUsageScanner}. + */ +class PublicApiCheckerTest { + + @TempDir + Path tempDir; + + // ----- isPublicApi ----- + + @Test + void isPublicApi_nonKafkaClass_returnsTrueOutOfScope() throws IOException { + PublicApiChecker checker = checkerFor(); + assertTrue(checker.isPublicApi("java.util.Map")); + assertTrue(checker.isPublicApi("com.example.Foo")); + } + + @Test + void isPublicApi_directPublic_returnsTrue() throws IOException { + PublicApiChecker checker = checkerFor( + AsmClassFactory.klass("org.apache.kafka.api.Pub").access(Opcodes.ACC_PUBLIC).publicApi()); + assertTrue(checker.isPublicApi("org.apache.kafka.api.Pub")); + } + + @Test + void isPublicApi_directPrivate_returnsFalse() throws IOException { + PublicApiChecker checker = checkerFor( + AsmClassFactory.klass("org.apache.kafka.api.Hidden").access(Opcodes.ACC_PUBLIC).privateApi()); + assertFalse(checker.isPublicApi("org.apache.kafka.api.Hidden")); + } + + @Test + void isPublicApi_deprecatedInternal_isStillFlagged() throws IOException { + // Consumer side: @Deprecated does NOT make an internal class out-of-scope. + // Deprecated-internal types are the most likely to be removed in the next release, so + // a consumer reference to one is exactly the kind of break the checker exists to catch. + // (The cascade validator still has its own deprecation bypass for the producer-side + // leak check, which is a separate policy.) + PublicApiChecker checker = checkerFor( + AsmClassFactory.klass("org.apache.kafka.api.Old") + .access(Opcodes.ACC_PUBLIC).privateApi().deprecated()); + assertFalse(checker.isPublicApi("org.apache.kafka.api.Old"), + "consumer predicate must flag @Deprecated @Private — those are the highest-risk references"); + } + + @Test + void isPublicApi_nestedInheritsFromOuter() throws IOException { + PublicApiChecker checker = checkerFor( + AsmClassFactory.klass("org.apache.kafka.api.Outer").access(Opcodes.ACC_PUBLIC).publicApi(), + AsmClassFactory.klass("org.apache.kafka.api.Outer$Inner").access(Opcodes.ACC_PUBLIC)); + assertTrue(checker.isPublicApi("org.apache.kafka.api.Outer$Inner")); + } + + @Test + void isPublicApi_nestedPrivateOverridesOuterPublic() throws IOException { + PublicApiChecker checker = checkerFor( + AsmClassFactory.klass("org.apache.kafka.api.Outer").access(Opcodes.ACC_PUBLIC).publicApi(), + AsmClassFactory.klass("org.apache.kafka.api.Outer$Inner").access(Opcodes.ACC_PUBLIC).privateApi()); + assertFalse(checker.isPublicApi("org.apache.kafka.api.Outer$Inner")); + } + + @Test + void isPublicApi_unknownKafkaClass_returnsFalse() throws IOException { + PublicApiChecker checker = checkerFor(); + assertFalse(checker.isPublicApi("org.apache.kafka.UnknownClass")); + } + + @Test + void isPublicApi_nestedWithoutOuterFacts_returnsFalse() throws IOException { + // Inner is recorded but Outer isn't. The chain walk finds Inner (no annotation), looks up + // Outer, gets null, exits with false — inheritance requires the outer to be in scope. + PublicApiChecker checker = checkerFor( + AsmClassFactory.klass("org.apache.kafka.api.Outer$Inner").access(Opcodes.ACC_PUBLIC)); + assertFalse(checker.isPublicApi("org.apache.kafka.api.Outer$Inner")); + } + + // ----- checkPublicApiConsistency ----- + + @Test + void checkPublicApiConsistency_mergesJavadocAndCascadeViolations() throws IOException { + // Bar is @Public with a method that leaks an internal type; javadoc jar is empty. + // Expected: MISSING_JAVADOC from the javadoc validator + INVALID_RETURN_TYPE from cascade. + AsmClassFactory.ClassBuilder bar = AsmClassFactory.klass("org.apache.kafka.api.Bar") + .access(Opcodes.ACC_PUBLIC).publicApi() + .method(AsmClassFactory.method("leak").returns("Lorg/apache/kafka/internals/Internal;")); + File projectJar = TempJarBuilder.jar().addClass(bar).writeTo(tempDir, "proj.jar"); + File javadocJar = TempJarBuilder.jar().writeTo(tempDir, "javadoc.jar"); + + CheckResult result = new PublicApiChecker(List.of(projectJar)).checkPublicApiConsistency(javadocJar); + + assertTrue(result.violations().stream().anyMatch(v -> "MISSING_JAVADOC".equals(v.getViolationType())), + "expected MISSING_JAVADOC from javadoc validator: " + result.violations()); + assertTrue(result.violations().stream().anyMatch(v -> "INVALID_RETURN_TYPE".equals(v.getViolationType())), + "expected INVALID_RETURN_TYPE from cascade validator: " + result.violations()); + } + + @Test + void checkPublicApiConsistency_mergesSuppressionsFromCascade() throws IOException { + // Class-level @SuppressKafkaInternalApiUsage routes the cascade leak into suppressions + // instead of violations. Javadoc HTML present → no MISSING_JAVADOC. + AsmClassFactory.ClassBuilder bar = AsmClassFactory.klass("org.apache.kafka.api.Bar") + .access(Opcodes.ACC_PUBLIC).publicApi().suppress("legacy") + .method(AsmClassFactory.method("leak").returns("Lorg/apache/kafka/internals/Internal;")); + File projectJar = TempJarBuilder.jar().addClass(bar).writeTo(tempDir, "proj.jar"); + File javadocJar = TempJarBuilder.jar() + .addHtml("org/apache/kafka/api/Bar.html", "") + .writeTo(tempDir, "javadoc.jar"); + + CheckResult result = new PublicApiChecker(List.of(projectJar)).checkPublicApiConsistency(javadocJar); + + assertTrue(result.violations().isEmpty(), "everything suppressed: " + result.violations()); + assertEquals(1, result.suppressions().size()); + assertTrue(result.suppressions().get(0).getDescription().contains("reason: legacy"), + "suppression must carry the annotation reason: " + result.suppressions().get(0).getDescription()); + } + + // ----- checkBytecode ----- + + @Test + void checkBytecode_flagsConsumerReferenceToInternalClass() throws IOException { + // Project surface defines Hidden as an in-scope Kafka class with no @Public annotation. + // The consumer references it → checkBytecode should report INTERNAL_API_USAGE. + File projectJar = TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("org.apache.kafka.internals.Hidden").access(Opcodes.ACC_PUBLIC)) + .writeTo(tempDir, "proj.jar"); + File consumerJar = TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("com.example.Consumer") + .access(Opcodes.ACC_PUBLIC) + .method(AsmClassFactory.method("hold").returns("Lorg/apache/kafka/internals/Hidden;"))) + .writeTo(tempDir, "consumer.jar"); + + CheckResult result = new PublicApiChecker(List.of(projectJar)).checkBytecode(List.of(consumerJar)); + + assertFalse(result.violations().isEmpty(), + "unannotated Kafka class reference must be flagged: " + result.violations()); + assertEquals("INTERNAL_API_USAGE", result.violations().get(0).getViolationType()); + assertEquals("org.apache.kafka.internals.Hidden", result.violations().get(0).getClassName()); + } + + @Test + void checkBytecode_passesConsumerReferenceToPublicClass() throws IOException { + File projectJar = TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("org.apache.kafka.api.Pub").access(Opcodes.ACC_PUBLIC).publicApi()) + .writeTo(tempDir, "proj.jar"); + File consumerJar = TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("com.example.Consumer") + .access(Opcodes.ACC_PUBLIC) + .method(AsmClassFactory.method("use").returns("Lorg/apache/kafka/api/Pub;"))) + .writeTo(tempDir, "consumer.jar"); + + CheckResult result = new PublicApiChecker(List.of(projectJar)).checkBytecode(List.of(consumerJar)); + + assertTrue(result.violations().isEmpty(), + "reference to a @Public class must pass: " + result.violations()); + } + + // ----- constructor overload ----- + + @Test + void singleArgConstructor_equivalentToEmptyReferenceJars() throws IOException { + File projectJar = TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("org.apache.kafka.api.Bar").access(Opcodes.ACC_PUBLIC).publicApi()) + .writeTo(tempDir, "proj.jar"); + + PublicApiChecker single = new PublicApiChecker(List.of(projectJar)); + PublicApiChecker dual = new PublicApiChecker(List.of(projectJar), Collections.emptyList()); + + assertTrue(single.isPublicApi("org.apache.kafka.api.Bar")); + assertTrue(dual.isPublicApi("org.apache.kafka.api.Bar")); + assertFalse(single.isPublicApi("org.apache.kafka.UnknownClass")); + assertFalse(dual.isPublicApi("org.apache.kafka.UnknownClass")); + } + + // ----- helper ----- + + private PublicApiChecker checkerFor(AsmClassFactory.ClassBuilder... classes) throws IOException { + if (classes.length == 0) return new PublicApiChecker(List.of()); + TempJarBuilder jar = TempJarBuilder.jar(); + for (AsmClassFactory.ClassBuilder c : classes) jar.addClass(c); + return new PublicApiChecker(List.of(jar.writeTo(tempDir, "proj.jar"))); + } +} diff --git a/api-checker/core/src/testFixtures/java/org/apache/kafka/apicheck/AsmClassFactory.java b/api-checker/core/src/testFixtures/java/org/apache/kafka/apicheck/AsmClassFactory.java new file mode 100644 index 0000000000000..d1df74baf2d34 --- /dev/null +++ b/api-checker/core/src/testFixtures/java/org/apache/kafka/apicheck/AsmClassFactory.java @@ -0,0 +1,366 @@ +/* + * 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.kafka.apicheck; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.util.ArrayList; +import java.util.List; + +/** + * Synthesises {@code .class} bytes for KIP-1265 checker tests so they don't depend on real Kafka + * classes on the classpath. Carries enough knobs to exercise the audience-annotation, nested-class + * inner-access, and {@code @SuppressKafkaInternalApiUsage} paths the checker reads. + */ +public final class AsmClassFactory { + + public static final String PUBLIC_API_DESC = + "Lorg/apache/kafka/common/annotation/InterfaceAudience$Public;"; + public static final String PRIVATE_API_DESC = + "Lorg/apache/kafka/common/annotation/InterfaceAudience$Private;"; + public static final String SUPPRESS_DESC = + "Lorg/apache/kafka/common/annotation/SuppressKafkaInternalApiUsage;"; + public static final String DEPRECATED_DESC = "Ljava/lang/Deprecated;"; + + private AsmClassFactory() {} + + public static ClassBuilder klass(String binaryName) { + return new ClassBuilder(binaryName); + } + + public static MethodSpec method(String name) { + return new MethodSpec(name); + } + + public static FieldSpec field(String name) { + return new FieldSpec(name); + } + + /** Wrap an internal name ("org/apache/kafka/X") as an object type descriptor. */ + public static String objDesc(String internalName) { + return "L" + internalName + ";"; + } + + public static String toInternal(String binaryName) { + return binaryName.replace('.', '/'); + } + + public static final class ClassBuilder { + private final String binaryName; + private int headerAccess = Opcodes.ACC_PUBLIC; + private Integer nestedAccess; + private String superInternal = "java/lang/Object"; + private String[] interfaceInternals = new String[0]; + private boolean isInterface; + private boolean publicApi; + private boolean privateApi; + private boolean deprecated; + private boolean hasSuppress; + private String suppressReason; + private final List methods = new ArrayList<>(); + private final List fields = new ArrayList<>(); + + private ClassBuilder(String binaryName) { + this.binaryName = binaryName; + } + + public String binaryName() { + return binaryName; + } + + public ClassBuilder access(int access) { + this.headerAccess = access; + return this; + } + + /** + * Add an {@code InnerClasses} attribute entry for this class with the given source-level + * access — the scanner reads this in preference to the (compiler-synthesised) header access + * for nested classes. Binary name must contain {@code $}. + */ + public ClassBuilder nestedAccess(int access) { + this.nestedAccess = access; + return this; + } + + public ClassBuilder superClass(String internalName) { + this.superInternal = internalName; + return this; + } + + public ClassBuilder interfaces(String... internalNames) { + this.interfaceInternals = internalNames; + return this; + } + + public ClassBuilder asInterface() { + this.isInterface = true; + return this; + } + + public ClassBuilder publicApi() { + this.publicApi = true; + return this; + } + + public ClassBuilder privateApi() { + this.privateApi = true; + return this; + } + + public ClassBuilder deprecated() { + this.deprecated = true; + return this; + } + + /** {@code @SuppressKafkaInternalApiUsage("reason")}; pass {@code null} to omit {@code value()}. */ + public ClassBuilder suppress(String reason) { + this.hasSuppress = true; + this.suppressReason = reason; + return this; + } + + public ClassBuilder method(MethodSpec method) { + this.methods.add(method); + return this; + } + + public ClassBuilder field(FieldSpec field) { + this.fields.add(field); + return this; + } + + public byte[] toBytes() { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + String internalName = toInternal(binaryName); + int access = headerAccess | (isInterface ? Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT : 0); + cw.visit(Opcodes.V11, access, internalName, null, + isInterface ? "java/lang/Object" : superInternal, interfaceInternals); + writeClassAnnotations(cw); + writeInnerClassEntry(cw, internalName); + if (!isInterface) { + writeDefaultCtor(cw, superInternal); + } + for (FieldSpec f : fields) { + f.write(cw); + } + for (MethodSpec m : methods) { + m.write(cw); + } + cw.visitEnd(); + return cw.toByteArray(); + } + + private void writeClassAnnotations(ClassWriter cw) { + if (publicApi) { + cw.visitAnnotation(PUBLIC_API_DESC, true).visitEnd(); + } + if (privateApi) { + cw.visitAnnotation(PRIVATE_API_DESC, true).visitEnd(); + } + if (deprecated) { + cw.visitAnnotation(DEPRECATED_DESC, true).visitEnd(); + } + if (hasSuppress) { + writeSuppress(cw.visitAnnotation(SUPPRESS_DESC, true), suppressReason); + } + } + + private void writeInnerClassEntry(ClassWriter cw, String internalName) { + if (nestedAccess == null) { + return; + } + int dollar = internalName.lastIndexOf('$'); + if (dollar < 0) { + throw new IllegalStateException( + "nestedAccess requires a binaryName containing '$' (got " + binaryName + ")"); + } + cw.visitInnerClass(internalName, internalName.substring(0, dollar), + internalName.substring(dollar + 1), nestedAccess); + } + } + + public static final class MethodSpec { + private final String name; + private int access = Opcodes.ACC_PUBLIC; + private String returnDesc = "V"; + private final List paramDescs = new ArrayList<>(); + private final List exceptionInternals = new ArrayList<>(); + private String signature; + private boolean hasSuppress; + private String suppressReason; + + private MethodSpec(String name) { + this.name = name; + } + + public MethodSpec access(int access) { + this.access = access; + return this; + } + + public MethodSpec returns(String desc) { + this.returnDesc = desc; + return this; + } + + public MethodSpec param(String desc) { + this.paramDescs.add(desc); + return this; + } + + public MethodSpec throwsExc(String internalName) { + this.exceptionInternals.add(internalName); + return this; + } + + /** Generic signature (JVMS §4.7.9), e.g. {@code "()Ljava/util/Map;"}. */ + public MethodSpec signature(String signature) { + this.signature = signature; + return this; + } + + public MethodSpec bridge() { + this.access |= Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC; + return this; + } + + public MethodSpec synthetic() { + this.access |= Opcodes.ACC_SYNTHETIC; + return this; + } + + public MethodSpec suppress(String reason) { + this.hasSuppress = true; + this.suppressReason = reason; + return this; + } + + public void write(ClassWriter cw) { + String desc = "(" + String.join("", paramDescs) + ")" + returnDesc; + String[] excs = exceptionInternals.isEmpty() + ? null : exceptionInternals.toArray(new String[0]); + MethodVisitor mv = cw.visitMethod(access, name, desc, signature, excs); + if (hasSuppress) { + writeSuppress(mv.visitAnnotation(SUPPRESS_DESC, true), suppressReason); + } + mv.visitCode(); + emitZeroReturn(mv, returnDesc); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + } + + public static final class FieldSpec { + private final String name; + private int access = Opcodes.ACC_PUBLIC; + private String typeDesc = "I"; + private String signature; + private boolean hasSuppress; + private String suppressReason; + + private FieldSpec(String name) { + this.name = name; + } + + public FieldSpec access(int access) { + this.access = access; + return this; + } + + public FieldSpec ofType(String desc) { + this.typeDesc = desc; + return this; + } + + /** Generic signature (JVMS §4.7.9), e.g. {@code "Ljava/util/List;"}. */ + public FieldSpec signature(String signature) { + this.signature = signature; + return this; + } + + public FieldSpec suppress(String reason) { + this.hasSuppress = true; + this.suppressReason = reason; + return this; + } + + public void write(ClassWriter cw) { + FieldVisitor fv = cw.visitField(access, name, typeDesc, signature, null); + if (hasSuppress) { + writeSuppress(fv.visitAnnotation(SUPPRESS_DESC, true), suppressReason); + } + fv.visitEnd(); + } + } + + private static void writeSuppress(AnnotationVisitor av, String reason) { + if (reason != null) { + av.visit("value", reason); + } + av.visitEnd(); + } + + private static void writeDefaultCtor(ClassWriter cw, String superInternal) { + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, superInternal, "", "()V", false); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + private static void emitZeroReturn(MethodVisitor mv, String desc) { + switch (desc.charAt(0)) { + case 'V': + mv.visitInsn(Opcodes.RETURN); + break; + case 'I': + case 'B': + case 'S': + case 'C': + case 'Z': + mv.visitInsn(Opcodes.ICONST_0); + mv.visitInsn(Opcodes.IRETURN); + break; + case 'J': + mv.visitInsn(Opcodes.LCONST_0); + mv.visitInsn(Opcodes.LRETURN); + break; + case 'F': + mv.visitInsn(Opcodes.FCONST_0); + mv.visitInsn(Opcodes.FRETURN); + break; + case 'D': + mv.visitInsn(Opcodes.DCONST_0); + mv.visitInsn(Opcodes.DRETURN); + break; + case 'L': + case '[': + mv.visitInsn(Opcodes.ACONST_NULL); + mv.visitInsn(Opcodes.ARETURN); + break; + default: + throw new IllegalArgumentException("Unsupported return descriptor: " + desc); + } + } +} diff --git a/api-checker/core/src/testFixtures/java/org/apache/kafka/apicheck/TempJarBuilder.java b/api-checker/core/src/testFixtures/java/org/apache/kafka/apicheck/TempJarBuilder.java new file mode 100644 index 0000000000000..bfa471cb0ffcb --- /dev/null +++ b/api-checker/core/src/testFixtures/java/org/apache/kafka/apicheck/TempJarBuilder.java @@ -0,0 +1,89 @@ +/* + * 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.kafka.apicheck; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +/** + * Builds a temp {@code .jar} with class-bytes and/or HTML entries — covers both jar shapes the + * checker consumes: project/reference jars (class bytes) and javadoc jars (HTML). + */ +public final class TempJarBuilder { + + private final List entries = new ArrayList<>(); + + public static TempJarBuilder jar() { + return new TempJarBuilder(); + } + + private TempJarBuilder() {} + + /** Add a class entry; jar path is derived from the binary name. */ + public TempJarBuilder addClass(String binaryName, byte[] bytes) { + entries.add(new Entry(binaryName.replace('.', '/') + ".class", bytes)); + return this; + } + + /** Convenience: build the bytes from a {@link AsmClassFactory.ClassBuilder} and add them. */ + public TempJarBuilder addClass(AsmClassFactory.ClassBuilder builder) { + return addClass(builder.binaryName(), builder.toBytes()); + } + + /** Add a javadoc HTML entry under the given jar-relative path; body may be empty. */ + public TempJarBuilder addHtml(String entryPath, String body) { + entries.add(new Entry(entryPath, body.getBytes(StandardCharsets.UTF_8))); + return this; + } + + /** Escape hatch for arbitrary entry paths (e.g. {@code module-info.class}, package-info, ...). */ + public TempJarBuilder addEntry(String entryPath, byte[] bytes) { + entries.add(new Entry(entryPath, bytes)); + return this; + } + + public File writeTo(File jarFile) throws IOException { + try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile))) { + for (Entry e : entries) { + jos.putNextEntry(new JarEntry(e.path)); + jos.write(e.bytes); + jos.closeEntry(); + } + } + return jarFile; + } + + public File writeTo(Path tempDir, String fileName) throws IOException { + return writeTo(tempDir.resolve(fileName).toFile()); + } + + private static final class Entry { + final String path; + final byte[] bytes; + Entry(String path, byte[] bytes) { + this.path = path; + this.bytes = bytes; + } + } +} diff --git a/api-checker/gradle-plugins/build.gradle b/api-checker/gradle-plugins/build.gradle new file mode 100644 index 0000000000000..d5aa722412b8d --- /dev/null +++ b/api-checker/gradle-plugins/build.gradle @@ -0,0 +1,116 @@ +/* + * 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. + */ + +apply plugin: 'java-gradle-plugin' + +dependencies { + api project(':core') + + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.2' + testImplementation 'org.junit.platform:junit-platform-launcher:1.9.2' + testImplementation 'org.mockito:mockito-core:5.3.1' + testImplementation gradleTestKit() + // Re-use the ASM-based class-file builders from :core's test-fixtures (AsmClassFactory, + // TempJarBuilder) instead of duplicating them. + testImplementation(testFixtures(project(':core'))) +} + +gradlePlugin { + plugins { + kafkaPublicApiChecker { + id = 'org.apache.kafka.public-api-checker' + implementationClass = 'org.apache.kafka.gradle.KafkaPublicApiCheckerPlugin' + displayName = 'Kafka Public API Checker' + description = 'Internal plugin for checking public API consistency in Kafka codebase' + } + kafkaInternalApiChecker { + id = 'org.apache.kafka.internal-api-checker' + implementationClass = 'org.apache.kafka.gradle.KafkaInternalApiCheckerPlugin' + displayName = 'Kafka Internal API Checker' + description = 'Plugin for external projects to check they don\'t use internal Kafka APIs' + } + } +} + +// The `java-gradle-plugin` plugin auto-generates one publication per declared plugin +// (the marker poms) plus a `pluginMaven` publication carrying the implementation jar. +// Rename the implementation jar to a sensible Maven coordinate; the markers point at it +// by group + artifactId. +// The `public-api-checker` plugin is Kafka-internal: it's applied to Kafka's own subprojects +// via the includedBuild wiring, but shipping its marker pom to Maven Central would only +// invite consumers to apply a plugin that expects Kafka-style javadoc layout. Disable the +// publish tasks for that marker only — the plugin must stay registered in +// `gradlePlugin { plugins { } }` above so `apply plugin: 'org.apache.kafka.public-api-checker'` +// continues to resolve, but the marker artifact never reaches a remote repository. +tasks.matching { it.name.startsWith('publishKafkaPublicApiCheckerPluginMarkerMavenPublication') }.configureEach { + enabled = false +} + +afterEvaluate { + publishing.publications.matching { it.name == 'pluginMaven' }.configureEach { + artifactId = 'kafka-internal-api-checker-gradle-plugin' + pom { + name = 'Apache Kafka Internal API Checker Gradle Plugin' + description = 'Gradle plugin that flags references to non-@Public Kafka classes in a downstream project' + url = 'https://kafka.apache.org' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = 'apache-kafka' + name = 'Apache Kafka Team' + email = 'dev@kafka.apache.org' + } + } + scm { + connection = 'scm:git:https://github.com/apache/kafka.git' + developerConnection = 'scm:git:https://github.com/apache/kafka.git' + url = 'https://github.com/apache/kafka' + } + } + } + publishing.publications.matching { it.name.endsWith('PluginMarkerMaven') }.configureEach { + pom { + name = 'Apache Kafka Internal API Checker Gradle Plugin' + description = 'Gradle plugin marker resolving the Apache Kafka internal-API checker' + url = 'https://kafka.apache.org' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = 'apache-kafka' + name = 'Apache Kafka Team' + email = 'dev@kafka.apache.org' + } + } + scm { + connection = 'scm:git:https://github.com/apache/kafka.git' + developerConnection = 'scm:git:https://github.com/apache/kafka.git' + url = 'https://github.com/apache/kafka' + } + } + } +} diff --git a/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerExtension.java b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerExtension.java new file mode 100644 index 0000000000000..f17a04c423a32 --- /dev/null +++ b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerExtension.java @@ -0,0 +1,118 @@ +/* + * 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.kafka.gradle; + +import org.gradle.api.Project; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.Property; + +import java.io.File; + +/** + * Configuration extension for the KafkaInternalApiChecker plugin. + * This plugin is used by external projects to ensure they don't use internal Kafka APIs. + */ +public class KafkaInternalApiCheckerExtension { + private final Property enabled; + private final Property failOnViolation; + private final Property failOnNoKafkaDependency; + private final ConfigurableFileCollection classDirs; + private final ConfigurableFileCollection kafkaDependencyJars; + private final RegularFileProperty reportFile; + + public KafkaInternalApiCheckerExtension(Project project) { + this.enabled = project.getObjects().property(Boolean.class); + this.enabled.convention(true); + + this.failOnViolation = project.getObjects().property(Boolean.class); + this.failOnViolation.convention(true); + + // Safety net for misconfigured projects. By default the task warns when it can't find + // any org.apache.kafka:* artifact on the classpath and proceeds with an empty surface + // (back-compat). Setting this to true turns that warning into a hard failure so a + // classpath or configuration mistake doesn't silently produce a "0 violations" report. + this.failOnNoKafkaDependency = project.getObjects().property(Boolean.class); + this.failOnNoKafkaDependency.convention(false); + + this.classDirs = project.getObjects().fileCollection(); + // Intentionally empty at construction. KafkaInternalApiCheckerPlugin reacts to the + // Java plugin being applied — see project.getPlugins().withType(JavaPlugin.class) — and + // adds sourceSets.main.output.classesDirs as a default contributor. That FileCollection + // carries the producer-task info for compileJava / compileScala / compileKotlin / …, so + // Gradle's @InputFiles validation can infer the compile-task dependency automatically. + // A raw project.file("build/classes") would scan the same bytecode but with no producer + // info attached, tripping "implicit dependency" validation errors on Gradle 9+. + // + // Users can still extend or replace this default from their build script: + // kafkaInternalApiChecker { classDirs.from(file("extra-classes")) } // extend + // kafkaInternalApiChecker { classDirs.setFrom(file("only-this")) } // replace + + this.kafkaDependencyJars = project.getObjects().fileCollection(); + + this.reportFile = project.getObjects().fileProperty(); + this.reportFile.convention(project.getLayout().getBuildDirectory().file("reports/kafka-internal-api-usage.txt")); + } + + public Property getEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled.set(enabled); + } + + public Property getFailOnViolation() { + return failOnViolation; + } + + public void setFailOnViolation(boolean failOnViolation) { + this.failOnViolation.set(failOnViolation); + } + + public Property getFailOnNoKafkaDependency() { + return failOnNoKafkaDependency; + } + + public void setFailOnNoKafkaDependency(boolean failOnNoKafkaDependency) { + this.failOnNoKafkaDependency.set(failOnNoKafkaDependency); + } + + public ConfigurableFileCollection getClassDirs() { + return classDirs; + } + + public void setClassDirs(Object... classDirs) { + this.classDirs.setFrom(classDirs); + } + + public ConfigurableFileCollection getKafkaDependencyJars() { + return kafkaDependencyJars; + } + + public void setKafkaDependencyJars(Object... jars) { + this.kafkaDependencyJars.setFrom(jars); + } + + public RegularFileProperty getReportFile() { + return reportFile; + } + + public void setReportFile(File reportFile) { + this.reportFile.set(reportFile); + } +} \ No newline at end of file diff --git a/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerPlugin.java b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerPlugin.java new file mode 100644 index 0000000000000..4ec5a3b13bd1c --- /dev/null +++ b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerPlugin.java @@ -0,0 +1,127 @@ +/* + * 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.kafka.gradle; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.artifacts.component.ModuleComponentIdentifier; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.api.tasks.TaskProvider; + +/** + * Gradle plugin for checking that external projects don't use internal Kafka APIs. + * This plugin is intended to be published and used by external Kafka plugin/application developers. + * + *

Wiring strategy

+ * + * The plugin uses a reactive {@code Plugins.withType(JavaPlugin.class)} callback rather than + * {@code project.afterEvaluate(...)} for the source-set + lifecycle wiring. Two reasons: + * + *
    + *
  • Order-insensitive. {@code withType} fires whenever the Java plugin is applied, + * regardless of whether the user listed {@code id 'java'} before or after this plugin. + * Scala and Kotlin plugins apply JavaPlugin transitively, so the same callback also + * handles those.
  • + *
  • Configuration-cache friendly. {@code afterEvaluate} forces eager evaluation + * at configuration time, which is at odds with the configuration cache and with + * Gradle's longer-term direction (isolated projects). The reactive form survives both.
  • + *
+ * + *

How {@code classDirs} is fed

+ * + * The extension's {@code classDirs} starts empty. When the Java plugin is applied, this plugin + * adds {@code sourceSets.main.output.classesDirs} as a contributor. That FileCollection + * carries producer-task info for the compile tasks, so Gradle's {@code @InputFiles} validation + * can infer the {@code compileJava} / {@code compileScala} / {@code compileKotlin} ordering + * automatically — no manual {@code dependsOn} required. Users can still call {@code .from(…)} + * on the extension to extend, or {@code .setFrom(…)} to replace. + * + *

The task's {@code classDirs} is wired to the extension's {@code ConfigurableFileCollection} + * by reference at task-registration time. Because {@code Property.set(FileCollection)} + * stores the same reference, later {@code .from(...)} calls on the extension (including the + * main-source-set contribution made by the {@code withType} callback) are visible at task + * execution time. + */ +public class KafkaInternalApiCheckerPlugin implements Plugin { + + /** Project property name that disables this checker for the current Gradle invocation. */ + static final String SKIP_PROPERTY = "kafkaInternalApiChecker.skip"; + + @Override + public void apply(Project project) { + // Create the extension for configuration + KafkaInternalApiCheckerExtension extension = project.getExtensions() + .create("kafkaInternalApiChecker", KafkaInternalApiCheckerExtension.class, project); + + if (KafkaPublicApiCheckerPlugin.isPropertyTruthy(project, SKIP_PROPERTY)) { + extension.getEnabled().set(false); + project.getLogger().lifecycle("Internal API checking disabled via -P{}", SKIP_PROPERTY); + } + + // Register the task. classDirs is wired directly to the extension's ConfigurableFileCollection + // by reference, so anything added to extension.classDirs later (either by the JavaPlugin + // hook below or by the user's build script) is visible to the task at execution time. + TaskProvider taskProvider = project.getTasks() + .register("kafkaInternalApiChecker", KafkaInternalApiCheckerTask.class, task -> { + task.getCheckerEnabled().set(extension.getEnabled()); + task.getFailOnViolation().set(extension.getFailOnViolation()); + task.getFailOnNoKafkaDependency().set(extension.getFailOnNoKafkaDependency()); + task.getClassDirs().set(extension.getClassDirs()); + task.getKafkaDependencyJars().from(extension.getKafkaDependencyJars()); + task.getReportFile().set(extension.getReportFile()); + }); + + // Reactive hook: fires when the Java plugin (or any plugin that applies JavaPlugin + // transitively, e.g. Scala or Kotlin) becomes part of this project. See the class-level + // javadoc for why this is preferred over `project.afterEvaluate(...)`. + project.getPlugins().withType(JavaPlugin.class, plugin -> { + SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); + + // Contribute main source set output as the default scanning target. Wrapped in a + // Provider so the underlying FileCollection (and its producer-task dependencies) + // is resolved lazily — important for configuration cache compatibility. + extension.getClassDirs().from( + sourceSets.named("main").map(s -> s.getOutput().getClassesDirs()) + ); + + // Default kafkaDependencyJars: the org.apache.kafka-filtered artifact view of the + // project's compile classpaths. Wired through ArtifactView (not raw resolution) so + // (a) it's a declared task input — a Kafka version bump invalidates the task — and + // (b) resolution is deferred to execution time, which is configuration-cache safe. + extension.getKafkaDependencyJars().from( + kafkaArtifactsFromConfiguration(project, JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME), + kafkaArtifactsFromConfiguration(project, JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME) + ); + + // Lifecycle wiring: make `check` depend on our task. The 'check' task itself comes + // from LifecycleBasePlugin, which JavaPlugin pulls in. + project.getTasks().named("check").configure(checkTask -> checkTask.dependsOn(taskProvider)); + }); + + project.getLogger().debug("Applied KafkaInternalApiChecker plugin to project: {}", project.getName()); + } + + private static org.gradle.api.file.FileCollection kafkaArtifactsFromConfiguration(Project project, String configurationName) { + return project.getConfigurations().getByName(configurationName) + .getIncoming() + .artifactView(view -> view.componentFilter(id -> + id instanceof ModuleComponentIdentifier + && "org.apache.kafka".equals(((ModuleComponentIdentifier) id).getGroup()))) + .getFiles(); + } +} \ No newline at end of file diff --git a/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerTask.java b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerTask.java new file mode 100644 index 0000000000000..932e94d9f00e6 --- /dev/null +++ b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaInternalApiCheckerTask.java @@ -0,0 +1,190 @@ +/* + * 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.kafka.gradle; + +import org.apache.kafka.apicheck.PublicApiChecker; +import org.apache.kafka.apicheck.PublicApiViolation; +import org.apache.kafka.apicheck.CheckResult; +import org.apache.kafka.apicheck.ViolationReporter; + +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; +import org.gradle.api.tasks.TaskAction; +import org.gradle.work.DisableCachingByDefault; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Gradle task for checking that external projects don't use internal Kafka APIs. + * + *

Scans compiled bytecode (.class files) under the project's class output directories, so it + * works uniformly for Java, Scala, Kotlin and any other JVM-language consumer. The task + * therefore runs after the project's {@code classes} task. + */ +@DisableCachingByDefault(because = "Reports are tiny; caching the bytecode scan adds little") +public class KafkaInternalApiCheckerTask extends DefaultTask { + + private final Property enabled = getProject().getObjects().property(Boolean.class); + private final Property failOnViolation = getProject().getObjects().property(Boolean.class); + private final Property failOnNoKafkaDependency = getProject().getObjects().property(Boolean.class); + private final Property classDirs = getProject().getObjects().property(FileCollection.class); + private final ConfigurableFileCollection kafkaDependencyJars = getProject().getObjects().fileCollection(); + private final RegularFileProperty reportFile = getProject().getObjects().fileProperty(); + + public KafkaInternalApiCheckerTask() { + setGroup("verification"); + setDescription("Checks that compiled bytecode doesn't reference internal Kafka APIs"); + + // Set default values + enabled.convention(true); + failOnViolation.convention(true); + failOnNoKafkaDependency.convention(false); + classDirs.convention(getProject().files("build/classes")); + reportFile.convention(getProject().getLayout().getBuildDirectory().file("reports/kafka-internal-api-usage.txt")); + } + + @TaskAction + public void checkInternalApiUsage() { + if (!getCheckerEnabled().get()) { + getLogger().info("KafkaInternalApiChecker is disabled, skipping..."); + return; + } + + FileCollection classes = classDirs.get(); + if (classes.isEmpty()) { + getLogger().info("No class directories configured, skipping internal API check"); + return; + } + + getLogger().info("Checking for internal Kafka API usage in compiled bytecode..."); + + List kafkaJars = new ArrayList<>(kafkaDependencyJars.getFiles()); + if (kafkaJars.isEmpty()) { + handleNoKafkaDependency(); + return; + } + + List classRoots = PublicApiChecker.collectExistingRoots(classes.getFiles()); + if (classRoots.isEmpty()) { + getLogger().info("No class files found, skipping internal API check"); + return; + } + + runCheck(kafkaJars, classRoots); + } + + private void handleNoKafkaDependency() { + String msg = "No org.apache.kafka:* dependencies found on the configured " + + "kafkaDependencyJars. The checker cannot derive an API surface and would " + + "produce a meaningless '0 violations' report — likely a classpath or " + + "configuration issue."; + if (failOnNoKafkaDependency.get()) { + throw new GradleException(msg); + } + getLogger().warn("{} Skipping internal API check. " + + "Set kafkaInternalApiChecker.failOnNoKafkaDependency = true to make this fatal.", msg); + } + + private void runCheck(List kafkaJars, List classRoots) { + try { + getLogger().info("Scanning {} class file root(s) for internal API usage", classRoots.size()); + CheckResult result = new PublicApiChecker(kafkaJars).checkBytecode(classRoots); + reportResults(result); + } catch (IOException e) { + throw new GradleException("Failed to check internal API usage: " + e.getMessage(), e); + } + } + + private void reportResults(CheckResult result) throws IOException { + List violations = result.violations(); + List suppressions = result.suppressions(); + + ViolationReporter reporter = new ViolationReporter(); + File report = reportFile.get().getAsFile(); + reporter.writeTextReport(violations, suppressions, report); + reporter.printToConsole(violations, suppressions, true); + + getLogger().info("Internal API usage check completed. Report written to: {}", report.getAbsolutePath()); + + long unjustified = suppressions.stream().filter(PublicApiViolation::lacksReason).count(); + if (unjustified > 0) { + getLogger().warn("{} suppression(s) carry no reason — KIP-1265 requires a justification on every @SuppressKafkaInternalApiUsage", unjustified); + } + + if (violations.isEmpty()) { + getLogger().info("No internal API usage found."); + return; + } + + String message = String.format("Found %d internal API usage violations. See report: %s", + violations.size(), report.getAbsolutePath()); + if (failOnViolation.get()) { + throw new GradleException(message); + } + getLogger().warn(message); + } + + @Input + public Property getCheckerEnabled() { + return enabled; + } + + @Input + public Property getFailOnViolation() { + return failOnViolation; + } + + @Input + public Property getFailOnNoKafkaDependency() { + return failOnNoKafkaDependency; + } + + @InputFiles + @PathSensitive(PathSensitivity.RELATIVE) + public Property getClassDirs() { + return classDirs; + } + + /** + * The Kafka jars whose {@code @InterfaceAudience.Public} annotations define the legal API + * surface. Declared as an {@code @InputFiles} so a Kafka version bump (i.e. a different jar + * path or content) invalidates the task and re-runs the scan. The plugin wires the default + * from the project's compile classpath, filtered to {@code org.apache.kafka}. + */ + @InputFiles + @PathSensitive(PathSensitivity.RELATIVE) + public ConfigurableFileCollection getKafkaDependencyJars() { + return kafkaDependencyJars; + } + + @OutputFile + public RegularFileProperty getReportFile() { + return reportFile; + } +} \ No newline at end of file diff --git a/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerExtension.java b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerExtension.java new file mode 100644 index 0000000000000..6aca486d02802 --- /dev/null +++ b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerExtension.java @@ -0,0 +1,98 @@ +/* + * 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.kafka.gradle; + +import org.gradle.api.Project; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.Property; + +import java.io.File; + +/** + * Configuration extension for the KafkaPublicApiChecker plugin. + */ +public class KafkaPublicApiCheckerExtension { + private final Property enabled; + private final Property failOnViolation; + private final RegularFileProperty javadocJarPath; + private final ConfigurableFileCollection projectJarFiles; + private final ConfigurableFileCollection referenceJarFiles; + private final RegularFileProperty reportFile; + + public KafkaPublicApiCheckerExtension(Project project) { + this.enabled = project.getObjects().property(Boolean.class); + this.enabled.convention(true); + + this.failOnViolation = project.getObjects().property(Boolean.class); + this.failOnViolation.convention(true); + + this.javadocJarPath = project.getObjects().fileProperty(); + + this.projectJarFiles = project.getObjects().fileCollection(); + + this.referenceJarFiles = project.getObjects().fileCollection(); + + this.reportFile = project.getObjects().fileProperty(); + this.reportFile.convention(project.getLayout().getBuildDirectory().file("reports/kafka-public-api-checker.txt")); + } + + public Property getEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled.set(enabled); + } + + public Property getFailOnViolation() { + return failOnViolation; + } + + public void setFailOnViolation(boolean failOnViolation) { + this.failOnViolation.set(failOnViolation); + } + + public RegularFileProperty getJavadocJarPath() { + return javadocJarPath; + } + + public void setJavadocJarPath(File javadocJarPath) { + this.javadocJarPath.set(javadocJarPath); + } + + public ConfigurableFileCollection getProjectJarFiles() { + return projectJarFiles; + } + + /** + * Jars of sibling Kafka modules this project depends on. Their classes are merged into the + * scanned surface so cross-module {@code @InterfaceAudience.Public} references resolve, but + * they don't contribute to this module's own javadoc-consistency or cascade iteration. + */ + public ConfigurableFileCollection getReferenceJarFiles() { + return referenceJarFiles; + } + + public RegularFileProperty getReportFile() { + return reportFile; + } + + public void setReportFile(File reportFile) { + this.reportFile.set(reportFile); + } +} \ No newline at end of file diff --git a/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerPlugin.java b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerPlugin.java new file mode 100644 index 0000000000000..2774b56c2623e --- /dev/null +++ b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerPlugin.java @@ -0,0 +1,117 @@ +/* + * 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.kafka.gradle; + +import org.gradle.api.DefaultTask; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.tasks.TaskProvider; +import org.gradle.api.tasks.bundling.Jar; + +/** + * Gradle plugin for checking public API consistency in the Kafka codebase. + * This is an internal plugin that runs as part of Kafka's own build process. + */ +public class KafkaPublicApiCheckerPlugin implements Plugin { + + /** Project property name that disables this checker for the current Gradle invocation. */ + static final String SKIP_PROPERTY = "kafkaPublicApiChecker.skip"; + + @Override + public void apply(Project project) { + // Create the extension for configuration + KafkaPublicApiCheckerExtension extension = project.getExtensions() + .create("kafkaPublicApiChecker", KafkaPublicApiCheckerExtension.class, project); + + if (isPropertyTruthy(project, SKIP_PROPERTY)) { + extension.getEnabled().set(false); + } + + // Register the task + TaskProvider taskProvider = project.getTasks() + .register("kafkaPublicApiChecker", KafkaPublicApiCheckerTask.class, task -> { + task.getCheckerEnabled().set(extension.getEnabled()); + task.getFailOnViolation().set(extension.getFailOnViolation()); + // Intentionally NOT calling task.getJavadocJarPath().set(extension.getJavadocJarPath()) + // here — `set(Provider)` marks the property as explicitly assigned even if the upstream + // is absent, which silently disables any later `.convention(...)` we install in + // afterEvaluate. The convention block below is the single source of truth. + task.getProjectJarFiles().from(extension.getProjectJarFiles()); + task.getReferenceJarFiles().from(extension.getReferenceJarFiles()); + task.getReportFile().set(extension.getReportFile()); + }); + + // Configure task to run after javadoc + project.afterEvaluate(p -> { + TaskProvider docsJarTask = p.getTasks().named("docsJar", DefaultTask.class); + + // Wire the checker's `javadocJarPath` input to the `javadocJar` task's `archiveFile` + // output where it exists. Reading the task's lazy output Provider — rather than + // recomputing the path from project.name + version — guarantees we read the *exact* + // file this Gradle run produced, which closes a stale-jar foot-gun: + // + // build/libs/kafka-foo-4.3.0-SNAPSHOT-javadoc.jar (left over from a months-old build) + // build/libs/kafka-foo-4.4.0-SNAPSHOT-javadoc.jar (just produced this run) + // + // The pre-fix auto-detect listed the directory and picked files[0], which on APFS + // returned the 4.3.0 (alphabetically earlier) jar. The checker then compared + // months-old javadoc against current bytecode and reported "all clean" while the + // module had real MISSING_PUBLICAPI_ANNOTATION violations against the fresh code. + Task javadocJarRaw = p.getTasks().findByName("javadocJar"); + taskProvider.configure(task -> { + task.mustRunAfter(docsJarTask); + task.dependsOn(docsJarTask); + + if (javadocJarRaw instanceof Jar) { + Jar javadocJar = (Jar) javadocJarRaw; + task.getJavadocJarPath().convention( + extension.getJavadocJarPath().orElse(javadocJar.getArchiveFile()) + ); + } else { + // No `javadocJar` task on this project — fall back to whatever the extension + // declared. The task's @TaskAction throws a clear error if neither is set, + // rather than silently scanning the wrong file. + task.getJavadocJarPath().convention(extension.getJavadocJarPath()); + } + }); + + // Make javadoc task finalize with our checker + docsJarTask.configure(javadoc -> javadoc.finalizedBy(taskProvider)); + + // Add to check task dependencies if it exists + project.getTasks().matching(task -> task.getName().equals("check")).configureEach(checkTask -> { + checkTask.dependsOn(taskProvider); + }); + }); + + if (isPropertyTruthy(project, SKIP_PROPERTY)) { + project.getLogger().lifecycle("Public API checking disabled via -P{}", SKIP_PROPERTY); + } + + project.getLogger().debug("Applied KafkaPublicApiChecker plugin to project: {}", project.getName()); + } + + /** Treat property values "true", "1", "yes" (case-insensitive) — or an empty value (just {@code -PsomeProp}) — as true. */ + static boolean isPropertyTruthy(Project project, String name) { + if (!project.hasProperty(name)) return false; + Object raw = project.findProperty(name); + if (raw == null) return true; + String s = raw.toString().trim(); + return s.isEmpty() || "true".equalsIgnoreCase(s) || "1".equals(s) || "yes".equalsIgnoreCase(s); + } +} \ No newline at end of file diff --git a/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerTask.java b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerTask.java new file mode 100644 index 0000000000000..1b9a7885cb420 --- /dev/null +++ b/api-checker/gradle-plugins/src/main/java/org/apache/kafka/gradle/KafkaPublicApiCheckerTask.java @@ -0,0 +1,175 @@ +/* + * 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.kafka.gradle; + +import org.apache.kafka.apicheck.CheckResult; +import org.apache.kafka.apicheck.PublicApiChecker; +import org.apache.kafka.apicheck.PublicApiViolation; +import org.apache.kafka.apicheck.ViolationReporter; + +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; +import org.gradle.api.tasks.TaskAction; +import org.gradle.work.DisableCachingByDefault; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Gradle task for checking public API consistency in Kafka codebase. + */ +@DisableCachingByDefault(because = "Reports are tiny; caching the bytecode scan adds little and complicates Hadoop-style audience-inheritance debugging") +public class KafkaPublicApiCheckerTask extends DefaultTask { + + private final Property enabled = getProject().getObjects().property(Boolean.class); + private final Property failOnViolation = getProject().getObjects().property(Boolean.class); + private final RegularFileProperty javadocJarPath = getProject().getObjects().fileProperty(); + private final ConfigurableFileCollection projectJarFiles = getProject().getObjects().fileCollection(); + private final ConfigurableFileCollection referenceJarFiles = getProject().getObjects().fileCollection(); + private final RegularFileProperty reportFile = getProject().getObjects().fileProperty(); + + public KafkaPublicApiCheckerTask() { + setGroup("verification"); + setDescription("Checks consistency between javadoc HTML files and @InterfaceAudience.Public annotations across project JARs"); + + // Set default values + enabled.convention(true); + failOnViolation.convention(true); + reportFile.convention(getProject().getLayout().getBuildDirectory().file("reports/kafka-public-api-checker.txt")); + } + + @TaskAction + public void checkPublicApi() { + if (!getCheckerEnabled().get()) { + getLogger().info("KafkaPublicApiChecker is disabled, skipping..."); + return; + } + + File jarFile = getJavadocJarFile(); + if (!jarFile.exists()) { + throw new GradleException("Javadoc JAR file not found: " + jarFile.getAbsolutePath() + + ". Make sure the javadoc task has run first."); + } + + getLogger().info("Checking public API consistency in: {}", jarFile.getAbsolutePath()); + + try { + if (projectJarFiles.getFiles().isEmpty()) { + throw new GradleException( + "No project JARs configured on kafkaPublicApiChecker.projectJarFiles — " + + "the checker needs at least one classes/jar source to build the API surface."); + } + PublicApiChecker checker = new PublicApiChecker( + new ArrayList<>(projectJarFiles.getFiles()), + new ArrayList<>(referenceJarFiles.getFiles())); + CheckResult result = checker.checkPublicApiConsistency(jarFile); + List violations = result.violations(); + List suppressions = result.suppressions(); + + // Generate report + ViolationReporter reporter = new ViolationReporter(); + File report = reportFile.get().getAsFile(); + reporter.writeTextReport(violations, suppressions, report); + + // Print summary to console + reporter.printToConsole(violations, suppressions, true); + + getLogger().info("Public API check completed. Report written to: {}", report.getAbsolutePath()); + + if (!suppressions.isEmpty()) { + getLogger().lifecycle("{} suppression(s) honoured — see report for justifications.", suppressions.size()); + long unjustified = suppressions.stream().filter(PublicApiViolation::lacksReason).count(); + if (unjustified > 0) { + getLogger().warn("{} suppression(s) carry no reason — KIP-1265 requires a justification on every @SuppressKafkaInternalApiUsage", unjustified); + } + } + if (!violations.isEmpty()) { + String message = String.format("Found %d public API violations. See report: %s", + violations.size(), report.getAbsolutePath()); + + if (failOnViolation.get()) { + throw new GradleException(message); + } else { + getLogger().warn(message); + } + } else { + getLogger().info("No public API violations found."); + } + + } catch (IOException e) { + throw new GradleException("Failed to check public API: " + e.getMessage(), e); + } + } + + private File getJavadocJarFile() { + if (!javadocJarPath.isPresent()) { + throw new GradleException("kafkaPublicApiChecker.javadocJarPath is not set. " + + "Either configure it explicitly on the extension, or apply this plugin to a " + + "project that defines a 'javadocJar' Jar task whose output the plugin can " + + "wire automatically."); + } + return javadocJarPath.get().getAsFile(); + } + + @Input + public Property getCheckerEnabled() { + return enabled; + } + + @Input + public Property getFailOnViolation() { + return failOnViolation; + } + + @InputFile + @Optional + @PathSensitive(PathSensitivity.RELATIVE) + public RegularFileProperty getJavadocJarPath() { + return javadocJarPath; + } + + @InputFiles + @Optional + @PathSensitive(PathSensitivity.RELATIVE) + public ConfigurableFileCollection getProjectJarFiles() { + return projectJarFiles; + } + + @InputFiles + @Optional + @PathSensitive(PathSensitivity.RELATIVE) + public ConfigurableFileCollection getReferenceJarFiles() { + return referenceJarFiles; + } + + @OutputFile + public RegularFileProperty getReportFile() { + return reportFile; + } +} \ No newline at end of file diff --git a/api-checker/gradle-plugins/src/test/java/org/apache/kafka/gradle/KafkaInternalApiCheckerPluginTest.java b/api-checker/gradle-plugins/src/test/java/org/apache/kafka/gradle/KafkaInternalApiCheckerPluginTest.java new file mode 100644 index 0000000000000..b90bb63c4b438 --- /dev/null +++ b/api-checker/gradle-plugins/src/test/java/org/apache/kafka/gradle/KafkaInternalApiCheckerPluginTest.java @@ -0,0 +1,93 @@ +/* + * 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.kafka.gradle; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Plugin-wiring coverage for the consumer-facing {@code internal-api-checker}. The actual scan + * logic is covered by {@code PluginDeveloperApiUsageScannerTest}; this class verifies that + * applying the plugin produces a working extension/task and that the JavaPlugin reactive hook + * contributes the expected defaults (classDirs + kafkaDependencyJars + `check` dependency). + */ +class KafkaInternalApiCheckerPluginTest { + + @Test + void pluginApply_createsExtensionAndTask() { + Project project = ProjectBuilder.builder().build(); + project.getPlugins().apply(KafkaInternalApiCheckerPlugin.class); + + assertNotNull(project.getExtensions().findByName("kafkaInternalApiChecker"), + "expected the extension to be registered"); + assertNotNull(project.getTasks().findByName("kafkaInternalApiChecker"), + "expected the kafkaInternalApiChecker task to be registered"); + } + + @Test + void skipProperty_disablesTheChecker() { + // -PkafkaInternalApiChecker.skip flips extension.enabled to false at configure time + // (replacement for the old execution-phase skipInternalApiCheck task, whose doLast + // mutation never reliably propagated). + Project project = ProjectBuilder.builder().build(); + project.getExtensions().getExtraProperties().set("kafkaInternalApiChecker.skip", "true"); + project.getPlugins().apply(KafkaInternalApiCheckerPlugin.class); + + KafkaInternalApiCheckerExtension extension = (KafkaInternalApiCheckerExtension) + project.getExtensions().getByName("kafkaInternalApiChecker"); + assertFalse(extension.getEnabled().get(), + "extension.enabled must flip to false when the skip property is set"); + } + + @Test + void pluginApplyWithJavaPlugin_wiresClassDirsKafkaJarsAndCheckLifecycle() { + Project project = ProjectBuilder.builder().build(); + project.getPlugins().apply(KafkaInternalApiCheckerPlugin.class); + project.getPlugins().apply(JavaPlugin.class); + + KafkaInternalApiCheckerExtension extension = (KafkaInternalApiCheckerExtension) + project.getExtensions().getByName("kafkaInternalApiChecker"); + KafkaInternalApiCheckerTask task = (KafkaInternalApiCheckerTask) + project.getTasks().getByName("kafkaInternalApiChecker"); + + // classDirs default: sourceSets.main.output.classesDirs contributed by the reactive hook. + // Resolving via getFiles() walks the contributors lazily. + assertTrue(extension.getClassDirs().getFiles().stream() + .anyMatch(f -> f.getPath().contains("classes")), + "JavaPlugin hook should contribute main source set output to classDirs, got: " + + extension.getClassDirs().getFiles()); + + // The new declared input. With no Kafka deps on the test project's classpath the filter + // produces an empty file collection; what matters is that the file collection itself is + // wired (not null) so version bumps can later invalidate the task. + assertNotNull(task.getKafkaDependencyJars(), + "task.getKafkaDependencyJars() must be declared and wired by the plugin"); + + // Lifecycle: kafkaInternalApiChecker must be a dependency of `check`. + Task checkTask = project.getTasks().getByName("check"); + assertTrue(checkTask.getTaskDependencies().getDependencies(checkTask).stream() + .anyMatch(d -> "kafkaInternalApiChecker".equals(d.getName())), + "`check` task should depend on `kafkaInternalApiChecker`"); + } +} \ No newline at end of file diff --git a/api-checker/gradle-plugins/src/test/java/org/apache/kafka/gradle/KafkaInternalApiCheckerTaskTest.java b/api-checker/gradle-plugins/src/test/java/org/apache/kafka/gradle/KafkaInternalApiCheckerTaskTest.java new file mode 100644 index 0000000000000..cc0bf8663f35e --- /dev/null +++ b/api-checker/gradle-plugins/src/test/java/org/apache/kafka/gradle/KafkaInternalApiCheckerTaskTest.java @@ -0,0 +1,169 @@ +/* + * 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.kafka.gradle; + +import org.apache.kafka.apicheck.AsmClassFactory; +import org.apache.kafka.apicheck.TempJarBuilder; + +import org.gradle.api.GradleException; +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * End-to-end coverage of the consumer Gradle path: feeds a {@link KafkaInternalApiCheckerTask} + * a synthetic Kafka surface jar + synthetic consumer bytecode and runs the task action directly. + * + *

The scanner itself is unit-tested in {@code PluginDeveloperApiUsageScannerTest}; what this + * class adds is the wiring between the task's declared {@code kafkaDependencyJars} / + * {@code classDirs} inputs, the {@code @TaskAction}, and the GradleException-vs-warning routing + * via {@code failOnViolation}. + */ +class KafkaInternalApiCheckerTaskTest { + + @TempDir + Path tempDir; + + private Project project; + private KafkaInternalApiCheckerTask task; + + @BeforeEach + void setUp() { + project = ProjectBuilder.builder().build(); + task = project.getTasks().create("kafkaInternalApiChecker", KafkaInternalApiCheckerTask.class); + } + + @Test + void disabled_returnsWithoutScanning() { + task.getCheckerEnabled().set(false); + assertDoesNotThrow(() -> task.checkInternalApiUsage()); + } + + @Test + void emptyKafkaDependencyJars_skipsCheckWithWarning() throws IOException { + // classDirs configured, but no Kafka jars on the classpath — the scanner has no public + // surface to validate against, so the task warns and returns rather than treating every + // org.apache.kafka.* reference in the consumer bytecode as a violation. + task.getClassDirs().set(project.files(consumerClassesDir("org/apache/kafka/internals/Hidden"))); + assertDoesNotThrow(() -> task.checkInternalApiUsage()); + } + + @Test + void consumerReferencingInternalKafkaType_failsWhenFailOnViolation() throws IOException { + File kafkaJar = synthesisedKafkaJarWithPublicClass(); + File classesDir = consumerClassesDir("org/apache/kafka/internals/Hidden"); + + task.getKafkaDependencyJars().from(kafkaJar); + task.getClassDirs().set(project.files(classesDir)); + task.getFailOnViolation().set(true); + + GradleException ex = assertThrows(GradleException.class, () -> task.checkInternalApiUsage()); + org.junit.jupiter.api.Assertions.assertTrue(ex.getMessage().contains("internal API usage violations"), + "expected violations message, got: " + ex.getMessage()); + } + + @Test + void consumerReferencingInternalKafkaType_warnsWhenFailOnViolationFalse() throws IOException { + File kafkaJar = synthesisedKafkaJarWithPublicClass(); + File classesDir = consumerClassesDir("org/apache/kafka/internals/Hidden"); + + task.getKafkaDependencyJars().from(kafkaJar); + task.getClassDirs().set(project.files(classesDir)); + task.getFailOnViolation().set(false); + + // Logs a warning but does not throw — useful for adopt-as-warning rollouts. + assertDoesNotThrow(() -> task.checkInternalApiUsage()); + } + + @Test + void consumerReferencingPublicKafkaType_passes() throws IOException { + File kafkaJar = synthesisedKafkaJarWithPublicClass(); + // Consumer references the @Public type rather than the internal one. + File classesDir = consumerClassesDir("org/apache/kafka/clients/producer/KafkaProducer"); + + task.getKafkaDependencyJars().from(kafkaJar); + task.getClassDirs().set(project.files(classesDir)); + task.getFailOnViolation().set(true); + + assertDoesNotThrow(() -> task.checkInternalApiUsage()); + } + + // ----- helpers ----- + + /** + * Produce a "kafka-clients-like" jar containing one {@code @InterfaceAudience.Public} + * class. References to that class from a consumer should pass; references to any other + * {@code org.apache.kafka.*} class should be flagged as internal. + */ + private File synthesisedKafkaJarWithPublicClass() throws IOException { + return TempJarBuilder.jar() + .addClass(AsmClassFactory.klass("org.apache.kafka.clients.producer.KafkaProducer") + .access(Opcodes.ACC_PUBLIC) + .publicApi()) + .writeTo(tempDir, "kafka-clients.jar"); + } + + /** + * Write a single consumer .class to a fresh directory; the class loads a constant of the + * given internal-name type, which the bytecode scanner picks up as a usage reference. + */ + private File consumerClassesDir(String referencedInternalName) throws IOException { + File dir = Files.createTempDirectory(tempDir, "consumer-classes").toFile(); + Files.write(new File(dir, "Consumer.class").toPath(), + consumerBytes("com/example/Consumer", referencedInternalName)); + return dir; + } + + /** Default ctor + one method that loads a class constant of {@code referencedInternalName}. */ + private static byte[] consumerBytes(String consumerInternalName, String referencedInternalName) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC, consumerInternalName, null, "java/lang/Object", null); + + MethodVisitor ctor = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + ctor.visitCode(); + ctor.visitVarInsn(Opcodes.ALOAD, 0); + ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + ctor.visitInsn(Opcodes.RETURN); + ctor.visitMaxs(0, 0); + ctor.visitEnd(); + + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "useIt", "()V", null, null); + mv.visitCode(); + mv.visitLdcInsn(Type.getObjectType(referencedInternalName)); + mv.visitInsn(Opcodes.POP); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + + cw.visitEnd(); + return cw.toByteArray(); + } +} \ No newline at end of file diff --git a/api-checker/gradle-plugins/src/test/java/org/apache/kafka/gradle/KafkaPublicApiCheckerTaskTest.java b/api-checker/gradle-plugins/src/test/java/org/apache/kafka/gradle/KafkaPublicApiCheckerTaskTest.java new file mode 100644 index 0000000000000..43024fbf1a864 --- /dev/null +++ b/api-checker/gradle-plugins/src/test/java/org/apache/kafka/gradle/KafkaPublicApiCheckerTaskTest.java @@ -0,0 +1,188 @@ +/* + * 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.kafka.gradle; + +import org.gradle.api.GradleException; +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Tests for the enhanced KafkaPublicApiCheckerTask with dual validation. + */ +public class KafkaPublicApiCheckerTaskTest { + + @TempDir + Path tempDir; + + private Project project; + private KafkaPublicApiCheckerTask task; + + @BeforeEach + void setUp() { + project = ProjectBuilder.builder().build(); + task = project.getTasks().create("checkPublicApi", KafkaPublicApiCheckerTask.class); + } + + @Test + void testTaskConfiguration_DefaultValues() { + assertTrue(task.getCheckerEnabled().get()); + assertTrue(task.getFailOnViolation().get()); + } + + @Test + void testTaskConfiguration_CustomValues() { + task.getCheckerEnabled().set(false); + task.getFailOnViolation().set(false); + + assertFalse(task.getCheckerEnabled().get()); + assertFalse(task.getFailOnViolation().get()); + } + + @Test + void testTaskExecution_DisabledChecker() { + task.getCheckerEnabled().set(false); + + // Should not throw exception when disabled + assertDoesNotThrow(() -> task.checkPublicApi()); + } + + @Test + void testTaskExecution_MissingJavadocJar() { + task.getCheckerEnabled().set(true); + task.getJavadocJarPath().set(new File("nonexistent.jar")); + + GradleException exception = assertThrows(GradleException.class, () -> task.checkPublicApi()); + assertTrue(exception.getMessage().contains("Javadoc JAR file not found")); + } + + @Test + void testTaskExecution_WithValidJarFiles() throws IOException { + File javadocJar = createMockJavadocJar(); + File projectJar = createMockProjectJar(); + + task.getCheckerEnabled().set(true); + task.getJavadocJarPath().set(javadocJar); + task.getProjectJarFiles().from(projectJar); + task.getFailOnViolation().set(false); // Don't fail on violations for this test + + // Should not throw exception + assertDoesNotThrow(() -> task.checkPublicApi()); + } + + @Test + void testTaskExecution_FailsWhenProjectJarsMissing() throws IOException { + // Project JAR files are mandatory after the SOLID refactor — without them the scanner has + // nothing to read. The task must surface this as a configuration error rather than silently + // running on an empty surface (which would let everything appear "missing javadoc"). + File javadocJar = createMockJavadocJar(); + + task.getCheckerEnabled().set(true); + task.getJavadocJarPath().set(javadocJar); + task.getFailOnViolation().set(false); + + assertThrows(org.gradle.api.GradleException.class, () -> task.checkPublicApi()); + } + + @Test + void testTaskInputsOutputs() throws IOException { + File javadocJar = createMockJavadocJar(); + File projectJar = createMockProjectJar(); + + task.getJavadocJarPath().set(javadocJar); + task.getProjectJarFiles().from(projectJar); + + // Verify inputs are configured + assertNotNull(task.getJavadocJarPath().getOrNull()); + assertFalse(task.getProjectJarFiles().isEmpty()); + + // Verify outputs are configured + assertNotNull(task.getReportFile().getOrNull()); + } + + @Test + void testTaskDescription() { + assertEquals("Checks consistency between javadoc HTML files and @InterfaceAudience.Public annotations across project JARs", + task.getDescription()); + } + + @Test + void testTaskGroup() { + assertEquals("verification", task.getGroup()); + } + + // Helper methods for creating mock JAR files + + private File createMockJavadocJar() throws IOException { + File jarFile = tempDir.resolve("test-javadoc.jar").toFile(); + + try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile))) { + // Add valid class HTML files + addHtmlEntry(jos, "org/apache/kafka/common/Resource.html", + "Resource class documentation"); + addHtmlEntry(jos, "org/apache/kafka/clients/producer/Producer.html", + "Producer interface documentation"); + + // Add structural HTML files + addHtmlEntry(jos, "index.html", "Index"); + addHtmlEntry(jos, "overview-tree.html", "Tree"); + } + + return jarFile; + } + + private File createMockProjectJar() throws IOException { + File jarFile = tempDir.resolve("test-project.jar").toFile(); + + try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile))) { + // Add some empty entries instead of invalid class files + addEntry(jos, "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n".getBytes()); + } + + return jarFile; + } + + private void addHtmlEntry(JarOutputStream jos, String path, String content) throws IOException { + JarEntry entry = new JarEntry(path); + jos.putNextEntry(entry); + jos.write(content.getBytes()); + jos.closeEntry(); + } + + private void addEntry(JarOutputStream jos, String path, byte[] content) throws IOException { + JarEntry entry = new JarEntry(path); + jos.putNextEntry(entry); + jos.write(content); + jos.closeEntry(); + } +} \ No newline at end of file diff --git a/api-checker/maven-plugin/build.gradle b/api-checker/maven-plugin/build.gradle new file mode 100644 index 0000000000000..9508d830d3bea --- /dev/null +++ b/api-checker/maven-plugin/build.gradle @@ -0,0 +1,83 @@ +/* + * 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. + */ + +// Maven mojo for the KIP-1265 internal-api-checker. Lives in its own subproject so the +// Maven runtime dependencies (maven-plugin-api, maven-core, …) stay off the Gradle plugin's +// classpath, and so the published Gradle jar no longer carries Maven mojo classes. + +// Single source of truth for the Maven dependency versions. The version block below and the +// hand-maintained plugin.xml descriptor both read these via processResources templating, so +// the two can never drift. +def mavenApiVersion = '3.9.4' +def mavenPluginAnnotationsVersion = '3.9.0' + +dependencies { + api project(':core') + + implementation "org.apache.maven:maven-plugin-api:${mavenApiVersion}" + implementation "org.apache.maven:maven-core:${mavenApiVersion}" + implementation "org.apache.maven:maven-artifact:${mavenApiVersion}" + implementation "org.apache.maven.plugin-tools:maven-plugin-annotations:${mavenPluginAnnotationsVersion}" +} + +// Template plugin.xml at packaging time so its and the Maven dep versions resolve +// from the same source as the published artifact / dependency block above. Ant's @token@ +// delimiter is intentional — Maven's runtime substitutions inside plugin.xml use ${...}, +// so the @ delimiter can never collide. +processResources { + filesMatching('META-INF/maven/plugin.xml') { + filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [ + version: project.version.toString(), + mavenApiVersion: mavenApiVersion, + mavenPluginAnnotationsVersion: mavenPluginAnnotationsVersion, + ]) + } +} + +publishing { + publications { + mavenPlugin(MavenPublication) { + artifactId = 'kafka-internal-api-checker-maven-plugin' + from components.java + + pom { + name = 'Apache Kafka Internal API Checker Maven Plugin' + description = 'Maven plugin that flags references to non-@Public Kafka classes in a downstream project' + url = 'https://kafka.apache.org' + packaging = 'maven-plugin' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = 'apache-kafka' + name = 'Apache Kafka Team' + email = 'dev@kafka.apache.org' + } + } + scm { + connection = 'scm:git:https://github.com/apache/kafka.git' + developerConnection = 'scm:git:https://github.com/apache/kafka.git' + url = 'https://github.com/apache/kafka' + } + } + } + } +} diff --git a/api-checker/maven-plugin/src/main/java/org/apache/kafka/maven/KafkaInternalApiCheckerMojo.java b/api-checker/maven-plugin/src/main/java/org/apache/kafka/maven/KafkaInternalApiCheckerMojo.java new file mode 100644 index 0000000000000..a08a8046d8195 --- /dev/null +++ b/api-checker/maven-plugin/src/main/java/org/apache/kafka/maven/KafkaInternalApiCheckerMojo.java @@ -0,0 +1,226 @@ +/* + * 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.kafka.maven; + +import org.apache.kafka.apicheck.PublicApiChecker; +import org.apache.kafka.apicheck.PublicApiViolation; +import org.apache.kafka.apicheck.CheckResult; +import org.apache.kafka.apicheck.ViolationReporter; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Maven plugin for checking that external projects don't use internal Kafka APIs. + * + *

Scans compiled bytecode (.class files) under the project's build output directory, so it + * works uniformly for Java, Scala, Kotlin and any other JVM-language consumer. Runs during the + * verify phase after compilation has produced the bytecode it inspects. + */ +@Mojo(name = "verify", + defaultPhase = LifecyclePhase.VERIFY, + requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, + threadSafe = true) +public class KafkaInternalApiCheckerMojo extends AbstractMojo { + + /** + * The Maven project. + */ + @Parameter(defaultValue = "${project}", required = true, readonly = true) + private MavenProject project; + + /** + * Enable/disable the checker. + */ + @Parameter(property = "kafka.internal-api-checker.enabled", defaultValue = "true") + private boolean enabled; + + /** + * Fail build on violations. + */ + @Parameter(property = "kafka.internal-api-checker.failOnViolation", defaultValue = "true") + private boolean failOnViolation; + + /** + * Fail the build when no {@code org.apache.kafka:*} artifact is on the project's + * classpath. The default is {@code false} for back-compat (the mojo warns and skips), + * but on a project that's expected to depend on Kafka, turning this on catches + * classpath/config mistakes that would otherwise produce a meaningless "0 violations" + * report. + */ + @Parameter(property = "kafka.internal-api-checker.failOnNoKafkaDependency", defaultValue = "false") + private boolean failOnNoKafkaDependency; + + /** + * Compiled-class directories to scan. Defaults to the project's main and test build output + * directories. Each entry may be a directory of {@code .class} files, an individual + * {@code .class} file, or a {@code .jar} archive. + */ + @Parameter + private List classesDirectories; + + + /** + * Report file location. + */ + @Parameter(defaultValue = "${project.build.directory}/reports/kafka-internal-api-usage.txt") + private File reportFile; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + if (!enabled) { + getLog().info("KafkaInternalApiChecker is disabled, skipping..."); + return; + } + + if (classesDirectories == null || classesDirectories.isEmpty()) { + classesDirectories = getDefaultClassesDirectories(); + } + + getLog().info("Checking for internal Kafka API usage in compiled bytecode..."); + + List kafkaJars = getKafkaJarsFromDependencies(); + if (kafkaJars.isEmpty()) { + handleNoKafkaDependency(); + return; + } + + List classRoots = PublicApiChecker.collectExistingRoots(classesDirectories); + if (classRoots.isEmpty()) { + getLog().info("No class files found, skipping internal API check"); + return; + } + + runCheck(kafkaJars, classRoots); + } + + private void handleNoKafkaDependency() throws MojoFailureException { + String msg = "No org.apache.kafka:* dependencies found on the project classpath. " + + "The checker cannot derive an API surface and would produce a meaningless " + + "'0 violations' report — likely a classpath or configuration issue."; + if (failOnNoKafkaDependency) { + throw new MojoFailureException(msg); + } + getLog().warn(msg + " Skipping internal API check. " + + "Set true to make this fatal."); + } + + private void runCheck(List kafkaJars, List classRoots) + throws MojoExecutionException, MojoFailureException { + try { + getLog().info("Scanning " + classRoots.size() + " class file root(s) for internal API usage"); + CheckResult result = new PublicApiChecker(kafkaJars).checkBytecode(classRoots); + reportResults(result); + } catch (IOException e) { + throw new MojoExecutionException("Failed to check internal API usage: " + e.getMessage(), e); + } + } + + private void reportResults(CheckResult result) throws MojoFailureException, IOException { + List violations = result.violations(); + List suppressions = result.suppressions(); + + ViolationReporter reporter = new ViolationReporter(); + reporter.writeTextReport(violations, suppressions, reportFile); + reporter.printToConsole(violations, suppressions, true); + + getLog().info("Internal API usage check completed. Report written to: " + reportFile.getAbsolutePath()); + + long unjustified = suppressions.stream().filter(PublicApiViolation::lacksReason).count(); + if (unjustified > 0) { + getLog().warn(unjustified + " suppression(s) carry no reason — KIP-1265 requires a justification on every @SuppressKafkaInternalApiUsage"); + } + + if (violations.isEmpty()) { + getLog().info("No internal API usage found."); + return; + } + + String message = String.format("Found %d internal API usage violations. See report: %s", + violations.size(), reportFile.getAbsolutePath()); + if (failOnViolation) { + throw new MojoFailureException(message); + } + getLog().warn(message); + } + + /** + * Default to the project's main compiled output, matching the Gradle plugin's behaviour + * (which feeds {@code sourceSets.main.output.classesDirs}). Test code legitimately uses + * internal/test utilities, so including it by default would create noise that isn't a + * real consumer-side concern. Users who want to scan test code can opt in by setting + * {@code } explicitly. + */ + private List getDefaultClassesDirectories() { + List dirs = new ArrayList<>(); + File mainClasses = new File(project.getBuild().getOutputDirectory()); + if (mainClasses.exists()) { + dirs.add(mainClasses); + } + return dirs; + } + + private List getKafkaJarsFromDependencies() { + List kafkaJars = new ArrayList<>(); + + for (Artifact artifact : project.getArtifacts()) { + if ("org.apache.kafka".equals(artifact.getGroupId())) { + kafkaJars.add(artifact.getFile()); + getLog().debug("Found Kafka dependency: " + artifact.getFile().getName()); + } + } + + return kafkaJars; + } + + // Getters and setters for testing + public void setProject(MavenProject project) { + this.project = project; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setFailOnViolation(boolean failOnViolation) { + this.failOnViolation = failOnViolation; + } + + public void setFailOnNoKafkaDependency(boolean failOnNoKafkaDependency) { + this.failOnNoKafkaDependency = failOnNoKafkaDependency; + } + + public void setClassesDirectories(List classesDirectories) { + this.classesDirectories = classesDirectories; + } + + public void setReportFile(File reportFile) { + this.reportFile = reportFile; + } +} \ No newline at end of file diff --git a/api-checker/maven-plugin/src/main/resources/META-INF/maven/plugin.xml b/api-checker/maven-plugin/src/main/resources/META-INF/maven/plugin.xml new file mode 100644 index 0000000000000..1850e42eef915 --- /dev/null +++ b/api-checker/maven-plugin/src/main/resources/META-INF/maven/plugin.xml @@ -0,0 +1,134 @@ + + + + + Apache Kafka Internal API Checker Maven Plugin + Maven plugin to check that external projects don't use internal Kafka APIs + org.apache.kafka + kafka-internal-api-checker-maven-plugin + @version@ + kafka-internal-api-checker + false + true + + + + verify + Checks source code for usage of internal Kafka APIs + false + true + false + false + false + true + verify + org.apache.kafka.maven.KafkaInternalApiCheckerMojo + java + per-lookup + once-per-session + true + compile+runtime + + + + project + org.apache.maven.project.MavenProject + true + false + The Maven project + + + + enabled + boolean + false + true + Enable/disable the internal API checker + + + + failOnViolation + boolean + false + true + Fail build on violations + + + + failOnNoKafkaDependency + boolean + false + true + Fail the build when no org.apache.kafka:* dependency is found on the classpath (default: false, which warns and skips) + + + + classesDirectories + java.util.List + false + true + Compiled-class directories or jars to scan for internal API usage + + + + reportFile + java.io.File + false + true + Report file location + + + + + + ${kafka.internal-api-checker.enabled} + ${kafka.internal-api-checker.failOnViolation} + ${kafka.internal-api-checker.failOnNoKafkaDependency} + + + + + + + + + org.apache.maven + maven-plugin-api + jar + @mavenApiVersion@ + + + org.apache.maven + maven-core + jar + @mavenApiVersion@ + + + org.apache.maven + maven-artifact + jar + @mavenApiVersion@ + + + org.apache.maven.plugin-tools + maven-plugin-annotations + jar + @mavenPluginAnnotationsVersion@ + + + \ No newline at end of file diff --git a/api-checker/settings.gradle b/api-checker/settings.gradle new file mode 100644 index 0000000000000..8389e1cf9d6ed --- /dev/null +++ b/api-checker/settings.gradle @@ -0,0 +1,20 @@ +// 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. + +rootProject.name = 'kafka-api-checker' + +include 'core' +include 'gradle-plugins' +include 'maven-plugin' diff --git a/build.gradle b/build.gradle index 5b8c8e8c874b6..c4ef7d8544c8e 100644 --- a/build.gradle +++ b/build.gradle @@ -42,6 +42,11 @@ plugins { id 'org.scoverage' version '8.1' apply false id 'com.gradleup.shadow' version '9.4.1' apply false id 'com.diffplug.spotless' version "8.4.0" + + // Pre-register the KIP-1265 checker so `apply plugin:` resolves it inside subprojects { }. + // The plugin itself ships from the `:api-checker` included build (see settings.gradle's + // pluginManagement block). + id 'org.apache.kafka.public-api-checker' apply false } ext { @@ -335,6 +340,8 @@ subprojects { apply plugin: 'checkstyle' apply plugin: "com.github.spotbugs" + apply plugin: 'org.apache.kafka.public-api-checker' + // We use the shadow plugin for the jmh-benchmarks module and the `-all` jar can get pretty large, so // don't publish it @@ -734,6 +741,31 @@ subprojects { check.dependsOn('javadoc') +kafkaPublicApiChecker { + + // Jars produced by this project — the surface that's actually validated. + projectJarFiles.from(jar.archiveFile) + + // Sibling Kafka modules this project depends on (direct or transitive). Their classes + // are merged into the scanned surface so cross-module @InterfaceAudience.Public references + // resolve, but they don't contribute to this module's MISSING_JAVADOC or cascade + // iteration — each module checks its own surface. + referenceJarFiles.from( + configurations.compileClasspath.incoming.artifactView { + // Resolve project deps to their assembled JAR (not the classes-dir variant Gradle + // picks by default for compile-classpath), so the scanner only sees real jars. + attributes { + attribute(org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, + objects.named(org.gradle.api.attributes.LibraryElements, + org.gradle.api.attributes.LibraryElements.JAR)) + } + componentFilter { it instanceof org.gradle.api.artifacts.component.ProjectComponentIdentifier } + }.files + ) + + enabled = true + failOnViolation = true +} task systemTestLibs(dependsOn: jar) if (!sourceSets.test.allSource.isEmpty()) { @@ -2136,6 +2168,7 @@ project(':clients') { include "**/org/apache/kafka/common/annotation/*" include "**/org/apache/kafka/common/config/*" include "**/org/apache/kafka/common/config/provider/*" + include "**/org/apache/kafka/common/config/types/*" include "**/org/apache/kafka/common/errors/*" include "**/org/apache/kafka/common/header/*" include "**/org/apache/kafka/common/metrics/*" diff --git a/checkstyle/import-control-api-checker.xml b/checkstyle/import-control-api-checker.xml new file mode 100644 index 0000000000000..fc956fc428330 --- /dev/null +++ b/checkstyle/import-control-api-checker.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionOptions.java index 26674e1ccc105..577eb8da977e6 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionOptions.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class AbortTransactionOptions extends AbstractOptions { @Override diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionResult.java index 602c4f96443ca..e1501fc1bd61c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionResult.java @@ -14,16 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; /** * The result of {@link Admin#abortTransaction(AbortTransactionSpec, AbortTransactionOptions)}. */ +@InterfaceAudience.Public public class AbortTransactionResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionSpec.java b/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionSpec.java index 6af5597872638..ed55dd1709df0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionSpec.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AbortTransactionSpec.java @@ -14,12 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Objects; +@InterfaceAudience.Public public class AbortTransactionSpec { private final TopicPartition topicPartition; private final long producerId; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AbstractOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AbstractOptions.java index 12effaf4e6372..56959619ac162 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AbstractOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AbstractOptions.java @@ -17,11 +17,13 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; /* * This class implements the common APIs that are shared by Options classes for various AdminClient commands */ @SuppressWarnings("rawtypes") +@InterfaceAudience.Public public abstract class AbstractOptions { protected Integer timeoutMs = null; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AddRaftVoterOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AddRaftVoterOptions.java index 81e889db30d61..09013c36876a9 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AddRaftVoterOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AddRaftVoterOptions.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import org.apache.kafka.common.protocol.Errors; @@ -33,6 +34,7 @@ * If not provided, the cluster id check is skipped. */ @InterfaceStability.Stable +@InterfaceAudience.Public public class AddRaftVoterOptions extends AbstractOptions { private Optional clusterId = Optional.empty(); diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AddRaftVoterResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AddRaftVoterResult.java index d42204c5e4e79..04fe2de20eef5 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AddRaftVoterResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AddRaftVoterResult.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; /** @@ -25,6 +26,7 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Stable +@InterfaceAudience.Public public class AddRaftVoterResult { private final KafkaFuture result; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/Admin.java b/clients/src/main/java/org/apache/kafka/clients/admin/Admin.java index 313c29ca49ee1..942b71d64336f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/Admin.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/Admin.java @@ -29,6 +29,7 @@ import org.apache.kafka.common.Uuid; import org.apache.kafka.common.acl.AclBinding; import org.apache.kafka.common.acl.AclBindingFilter; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import org.apache.kafka.common.config.ConfigResource; import org.apache.kafka.common.errors.FeatureUpdateFailedException; @@ -122,6 +123,7 @@ * version required. *

*/ +@InterfaceAudience.Public public interface Admin extends AutoCloseable { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AdminClient.java b/clients/src/main/java/org/apache/kafka/clients/admin/AdminClient.java index 204579605bc13..0c2923bab4c67 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AdminClient.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AdminClient.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; import java.util.Properties; @@ -27,6 +29,7 @@ * * This class may be removed in a later release, but has not been marked as deprecated to avoid unnecessary noise. */ +@InterfaceAudience.Public public abstract class AdminClient implements Admin { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AdminClientConfig.java b/clients/src/main/java/org/apache/kafka/clients/admin/AdminClientConfig.java index 3908688615657..62e72bb6ba004 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AdminClientConfig.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AdminClientConfig.java @@ -20,6 +20,7 @@ import org.apache.kafka.clients.ClientDnsLookup; import org.apache.kafka.clients.CommonClientConfigs; import org.apache.kafka.clients.MetadataRecoveryStrategy; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.AbstractConfig; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; @@ -41,6 +42,7 @@ /** * The AdminClient configuration class, which also contains constants for configuration entry names. */ +@InterfaceAudience.Public public class AdminClientConfig extends AbstractConfig { private static final ConfigDef CONFIG; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterClientQuotasOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterClientQuotasOptions.java index 027ccd1e9e028..39dac2ac6b628 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterClientQuotasOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterClientQuotasOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#alterClientQuotas(Collection, AlterClientQuotasOptions)}. */ +@InterfaceAudience.Public public class AlterClientQuotasOptions extends AbstractOptions { private boolean validateOnly = false; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterClientQuotasResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterClientQuotasResult.java index 4906184b3c925..2de0158e42dcc 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterClientQuotasResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterClientQuotasResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.quota.ClientQuotaEntity; import java.util.Collection; @@ -26,6 +27,7 @@ /** * The result of the {@link Admin#alterClientQuotas(Collection, AlterClientQuotasOptions)} call. */ +@InterfaceAudience.Public public class AlterClientQuotasResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigOp.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigOp.java index 789c9f64a93aa..f3afc4dbbb191 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigOp.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigOp.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -41,6 +43,7 @@ * new AlterConfigOp(new ConfigEntry(loggerName, "DEBUG"), OpType.SET) * */ +@InterfaceAudience.Public public class AlterConfigOp { public enum OpType { diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigsOptions.java index 31812bbfc1611..689a787c97091 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Options for {@link Admin#incrementalAlterConfigs(Map)}. */ +@InterfaceAudience.Public public class AlterConfigsOptions extends AbstractOptions { private boolean validateOnly = false; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigsResult.java index cd9279300de84..51639d3b23d36 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConfigsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigResource; import java.util.Map; @@ -25,6 +26,7 @@ /** * The result of the {@link Admin#incrementalAlterConfigs(Map, AlterConfigsOptions)} call. */ +@InterfaceAudience.Public public class AlterConfigsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConsumerGroupOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConsumerGroupOffsetsOptions.java index c2428b6430a9d..ea3f80bb4a391 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConsumerGroupOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConsumerGroupOffsetsOptions.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Options for the {@link AdminClient#alterConsumerGroupOffsets(String, Map, AlterConsumerGroupOffsetsOptions)} call. */ +@InterfaceAudience.Public public class AlterConsumerGroupOffsetsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConsumerGroupOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConsumerGroupOffsetsResult.java index 8d78a16b57458..b20a55c8b1e25 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterConsumerGroupOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterConsumerGroupOffsetsResult.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.internals.KafkaFutureImpl; import org.apache.kafka.common.protocol.Errors; @@ -28,6 +29,7 @@ /** * The result of the {@link AdminClient#alterConsumerGroupOffsets(String, Map)} call. */ +@InterfaceAudience.Public public class AlterConsumerGroupOffsetsResult { private final KafkaFuture> future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterPartitionReassignmentsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterPartitionReassignmentsOptions.java index 74c9f3dcdec8a..e1659db41951c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterPartitionReassignmentsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterPartitionReassignmentsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Options for {@link AdminClient#alterPartitionReassignments(Map, AlterPartitionReassignmentsOptions)} */ +@InterfaceAudience.Public public class AlterPartitionReassignmentsOptions extends AbstractOptions { private boolean allowReplicationFactorChange = true; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterPartitionReassignmentsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterPartitionReassignmentsResult.java index f918074af77f6..8dd1c457a521f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterPartitionReassignmentsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterPartitionReassignmentsResult.java @@ -19,12 +19,14 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; /** * The result of {@link AdminClient#alterPartitionReassignments(Map, AlterPartitionReassignmentsOptions)}. */ +@InterfaceAudience.Public public class AlterPartitionReassignmentsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterReplicaLogDirsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterReplicaLogDirsOptions.java index b6cca48ec8db6..447bde4333376 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterReplicaLogDirsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterReplicaLogDirsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Options for {@link Admin#alterReplicaLogDirs(Map, AlterReplicaLogDirsOptions)}. */ +@InterfaceAudience.Public public class AlterReplicaLogDirsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterReplicaLogDirsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterReplicaLogDirsResult.java index 6b6a98e20f65d..20f89e8751a73 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterReplicaLogDirsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterReplicaLogDirsResult.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartitionReplica; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ClusterAuthorizationException; import org.apache.kafka.common.errors.InvalidTopicException; import org.apache.kafka.common.errors.KafkaStorageException; @@ -35,6 +36,7 @@ * To retrieve the detailed result per specified {@link TopicPartitionReplica}, use {@link #values()}. To retrieve the * overall result only, use {@link #all()}. */ +@InterfaceAudience.Public public class AlterReplicaLogDirsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterShareGroupOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterShareGroupOffsetsOptions.java index b032be5406091..bf0309921c0ca 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterShareGroupOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterShareGroupOffsetsOptions.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Options for {@link Admin#alterShareGroupOffsets(String, Map, AlterShareGroupOffsetsOptions)}. */ +@InterfaceAudience.Public public class AlterShareGroupOffsetsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterShareGroupOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterShareGroupOffsetsResult.java index 293ad549ea865..f2ebd526be7c6 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterShareGroupOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterShareGroupOffsetsResult.java @@ -19,6 +19,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ApiException; import org.apache.kafka.common.internals.KafkaFutureImpl; import org.apache.kafka.common.protocol.Errors; @@ -30,6 +31,7 @@ /** * The result of the {@link Admin#alterShareGroupOffsets(String, Map, AlterShareGroupOffsetsOptions)} call. */ +@InterfaceAudience.Public public class AlterShareGroupOffsetsResult { private final KafkaFuture> future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterStreamsGroupOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterStreamsGroupOffsetsOptions.java index 2eceacdf25479..f3bc28926b598 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterStreamsGroupOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterStreamsGroupOffsetsOptions.java @@ -14,18 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Map; - /** * Options for the {@link Admin#alterStreamsGroupOffsets(String, Map, AlterStreamsGroupOffsetsOptions)} call. *

* The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class AlterStreamsGroupOffsetsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterStreamsGroupOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterStreamsGroupOffsetsResult.java index 11813bf767fab..5e1249f9b2f91 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterStreamsGroupOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterStreamsGroupOffsetsResult.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Map; @@ -28,6 +29,7 @@ * The API of this class is evolving, see {@link AdminClient} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class AlterStreamsGroupOffsetsResult { private final AlterConsumerGroupOffsetsResult delegate; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterUserScramCredentialsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterUserScramCredentialsOptions.java index 9ead2ee0912a7..26f5d2f8e8099 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterUserScramCredentialsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterUserScramCredentialsOptions.java @@ -17,10 +17,13 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; /** * Options for {@link AdminClient#alterUserScramCredentials(List, AlterUserScramCredentialsOptions)} */ +@InterfaceAudience.Public public class AlterUserScramCredentialsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/AlterUserScramCredentialsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/AlterUserScramCredentialsResult.java index d61d3958863b6..4b140fe0e92f2 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/AlterUserScramCredentialsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/AlterUserScramCredentialsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collections; import java.util.List; @@ -27,6 +28,7 @@ /** * The result of the {@link Admin#alterUserScramCredentials(List)} call. */ +@InterfaceAudience.Public public class AlterUserScramCredentialsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ClassicGroupDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/ClassicGroupDescription.java index 5a59eb9698067..963d9ce884301 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ClassicGroupDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ClassicGroupDescription.java @@ -20,6 +20,7 @@ import org.apache.kafka.common.ClassicGroupState; import org.apache.kafka.common.Node; import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.List; @@ -30,6 +31,7 @@ /** * A detailed description of a single classic group in the cluster. */ +@InterfaceAudience.Public public class ClassicGroupDescription { private final String groupId; private final String protocol; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/Config.java b/clients/src/main/java/org/apache/kafka/clients/admin/Config.java index 59f6f12e2669f..454f553d6e43d 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/Config.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/Config.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -26,6 +28,7 @@ * A configuration object containing the configuration entries for a resource. *

*/ +@InterfaceAudience.Public public class Config { private final Map entries = new HashMap<>(); diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ConfigEntry.java b/clients/src/main/java/org/apache/kafka/clients/admin/ConfigEntry.java index cde99ffb85229..69134f02a8228 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ConfigEntry.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ConfigEntry.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collections; import java.util.List; import java.util.Objects; @@ -24,6 +26,7 @@ /** * A class representing a configuration entry containing name, value and additional metadata. */ +@InterfaceAudience.Public public class ConfigEntry { private final String name; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ConsumerGroupDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/ConsumerGroupDescription.java index fa9c010393e14..599ab934ad060 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ConsumerGroupDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ConsumerGroupDescription.java @@ -22,6 +22,7 @@ import org.apache.kafka.common.GroupType; import org.apache.kafka.common.Node; import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.Collections; @@ -34,6 +35,7 @@ /** * A detailed description of a single consumer group in the cluster. */ +@InterfaceAudience.Public public class ConsumerGroupDescription { private final String groupId; private final boolean isSimpleConsumerGroup; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/CreateAclsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/CreateAclsOptions.java index e9f771ebd9f25..911be059de01e 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/CreateAclsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/CreateAclsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#createAcls(Collection)}. */ +@InterfaceAudience.Public public class CreateAclsOptions extends AbstractOptions { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/CreateAclsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/CreateAclsResult.java index de57fbb8911a9..c6fa0f87eff41 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/CreateAclsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/CreateAclsResult.java @@ -19,6 +19,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.acl.AclBinding; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.Map; @@ -26,6 +27,7 @@ /** * The result of the {@link Admin#createAcls(Collection)} call. */ +@InterfaceAudience.Public public class CreateAclsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/CreateDelegationTokenOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/CreateDelegationTokenOptions.java index f7ef1d4619d44..2e5708a72a00f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/CreateDelegationTokenOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/CreateDelegationTokenOptions.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.auth.KafkaPrincipal; import java.util.LinkedList; @@ -26,6 +27,7 @@ /** * Options for {@link Admin#createDelegationToken(CreateDelegationTokenOptions)}. */ +@InterfaceAudience.Public public class CreateDelegationTokenOptions extends AbstractOptions { private long maxLifetimeMs = -1; private List renewers = new LinkedList<>(); diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/CreateDelegationTokenResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/CreateDelegationTokenResult.java index b8b1a5694f66d..76227aabd3934 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/CreateDelegationTokenResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/CreateDelegationTokenResult.java @@ -18,11 +18,13 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.token.delegation.DelegationToken; /** * The result of the {@link KafkaAdminClient#createDelegationToken(CreateDelegationTokenOptions)} call. */ +@InterfaceAudience.Public public class CreateDelegationTokenResult { private final KafkaFuture delegationToken; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/CreatePartitionsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/CreatePartitionsOptions.java index ccdbe6d52ca2a..12a68467434f0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/CreatePartitionsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/CreatePartitionsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Options for {@link Admin#createPartitions(Map)}. */ +@InterfaceAudience.Public public class CreatePartitionsOptions extends AbstractOptions { private boolean validateOnly = false; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/CreatePartitionsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/CreatePartitionsResult.java index 21d26a6246764..f60a8ae2bcd34 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/CreatePartitionsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/CreatePartitionsResult.java @@ -18,12 +18,14 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; /** * The result of the {@link Admin#createPartitions(Map)} call. */ +@InterfaceAudience.Public public class CreatePartitionsResult { private final Map> values; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/CreateTopicsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/CreateTopicsOptions.java index c81f6e41a9014..8b9f11a401fdc 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/CreateTopicsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/CreateTopicsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#createTopics(Collection)}. */ +@InterfaceAudience.Public public class CreateTopicsOptions extends AbstractOptions { private boolean validateOnly = false; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/CreateTopicsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/CreateTopicsResult.java index 6cf794c65ee0a..752afc0180b37 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/CreateTopicsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/CreateTopicsResult.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ApiException; import java.util.Collection; @@ -27,6 +28,7 @@ /** * The result of {@link Admin#createTopics(Collection)}. */ +@InterfaceAudience.Public public class CreateTopicsResult { static final int UNKNOWN = -1; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteAclsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteAclsOptions.java index 59d5ce2bb1981..dee2ceab703c5 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteAclsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteAclsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for the {@link Admin#deleteAcls(Collection)} call. */ +@InterfaceAudience.Public public class DeleteAclsOptions extends AbstractOptions { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteAclsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteAclsResult.java index db43ac3f047f0..b0909fb316ae5 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteAclsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteAclsResult.java @@ -21,6 +21,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.acl.AclBinding; import org.apache.kafka.common.acl.AclBindingFilter; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ApiException; import java.util.ArrayList; @@ -31,6 +32,7 @@ /** * The result of the {@link Admin#deleteAcls(Collection)} call. */ +@InterfaceAudience.Public public class DeleteAclsResult { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupOffsetsOptions.java index 014b9fa9d4f60..920367dc5e120 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupOffsetsOptions.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Set; /** * Options for the {@link Admin#deleteConsumerGroupOffsets(String, Set)} call. */ +@InterfaceAudience.Public public class DeleteConsumerGroupOffsetsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupOffsetsResult.java index 80aaeb2a4bc26..ffdee4a1108c8 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupOffsetsResult.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.internals.KafkaFutureImpl; import org.apache.kafka.common.protocol.Errors; @@ -27,6 +28,7 @@ /** * The result of the {@link Admin#deleteConsumerGroupOffsets(String, Set)} call. */ +@InterfaceAudience.Public public class DeleteConsumerGroupOffsetsResult { private final KafkaFuture> future; private final Set partitions; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupsOptions.java index b8bc1ecba745c..91ba4492b5932 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupsOptions.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for the {@link Admin#deleteConsumerGroups(Collection)} call. */ +@InterfaceAudience.Public public class DeleteConsumerGroupsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupsResult.java index 39f893b047bbb..355e9732a4346 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteConsumerGroupsResult.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.HashMap; @@ -26,6 +28,7 @@ * The result of the {@link Admin#deleteConsumerGroups(Collection, DeleteConsumerGroupsOptions)} call for * {@code Collection} input. */ +@InterfaceAudience.Public public class DeleteConsumerGroupsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteRecordsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteRecordsOptions.java index 320d3d8cb6c0c..9b844c227b4c5 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteRecordsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteRecordsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Options for {@link Admin#deleteRecords(Map, DeleteRecordsOptions)}. */ +@InterfaceAudience.Public public class DeleteRecordsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteRecordsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteRecordsResult.java index 061403eeb165e..586eff2e0109e 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteRecordsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteRecordsResult.java @@ -19,12 +19,14 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; /** * The result of the {@link Admin#deleteRecords(Map)} call. */ +@InterfaceAudience.Public public class DeleteRecordsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupOffsetsOptions.java index e38fdf107456f..c9497e103d6b1 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupOffsetsOptions.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Set; /** * Options for {@link Admin#deleteShareGroupOffsets(String, Set, DeleteShareGroupOffsetsOptions)}. */ +@InterfaceAudience.Public public class DeleteShareGroupOffsetsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupOffsetsResult.java index 65231d1ca0fd7..76c93aa471b85 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupOffsetsResult.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ApiException; import org.apache.kafka.common.internals.KafkaFutureImpl; @@ -26,6 +27,7 @@ /** * The result of the {@link Admin#deleteShareGroupOffsets(String, Set, DeleteShareGroupOffsetsOptions)} call. */ +@InterfaceAudience.Public public class DeleteShareGroupOffsetsResult { private final KafkaFuture> future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupsOptions.java index 1709f169cb16d..278ddb248b19f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupsOptions.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#deleteShareGroups(Collection, DeleteShareGroupsOptions)}. */ +@InterfaceAudience.Public public class DeleteShareGroupsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupsResult.java index c4831e58494f6..ebd1840cdda0b 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteShareGroupsResult.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.HashMap; @@ -25,6 +27,7 @@ /** * The result of the {@link Admin#deleteShareGroups(Collection, DeleteShareGroupsOptions)} call. */ +@InterfaceAudience.Public public class DeleteShareGroupsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupOffsetsOptions.java index 10d39075d8ac0..1861db4984c5b 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupOffsetsOptions.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Set; @@ -26,6 +27,7 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class DeleteStreamsGroupOffsetsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupOffsetsResult.java index 4966ed063a8aa..b8930d8c1c7b7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupOffsetsResult.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import org.apache.kafka.common.protocol.Errors; @@ -30,6 +31,7 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class DeleteStreamsGroupOffsetsResult { private final DeleteConsumerGroupOffsetsResult delegate; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupsOptions.java index 6ca2ec66a276e..7ee61a7491971 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupsOptions.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Collection; @@ -26,5 +27,6 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class DeleteStreamsGroupsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupsResult.java index 70debbbb5192b..300f51a8e7da0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteStreamsGroupsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Collection; @@ -29,6 +30,7 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class DeleteStreamsGroupsResult { private final DeleteConsumerGroupsResult delegate; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsOptions.java index 6f5e9f069e071..3991e68c80439 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#deleteTopics(Collection)}. */ +@InterfaceAudience.Public public class DeleteTopicsOptions extends AbstractOptions { private boolean retryOnQuotaViolation = true; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsResult.java index eefdbdf9da10f..6dfe10c44f773 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsResult.java @@ -20,6 +20,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicCollection; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.Map; @@ -27,6 +28,7 @@ /** * The result of the {@link Admin#deleteTopics(Collection)} call. */ +@InterfaceAudience.Public public class DeleteTopicsResult { private final Map> topicIdFutures; private final Map> nameFutures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DeletedRecords.java b/clients/src/main/java/org/apache/kafka/clients/admin/DeletedRecords.java index 97d83a7775813..db92cd496742c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DeletedRecords.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DeletedRecords.java @@ -17,9 +17,12 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Represents information about deleted records */ +@InterfaceAudience.Public public class DeletedRecords { private final long lowWatermark; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeAclsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeAclsOptions.java index f310b6bb73b12..a81ed630665b5 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeAclsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeAclsOptions.java @@ -18,10 +18,12 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.acl.AclBindingFilter; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Options for {@link Admin#describeAcls(AclBindingFilter)}. */ +@InterfaceAudience.Public public class DescribeAclsOptions extends AbstractOptions { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeAclsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeAclsResult.java index df86515d3ba2e..d6567a5fe08b5 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeAclsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeAclsResult.java @@ -20,12 +20,14 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.acl.AclBinding; import org.apache.kafka.common.acl.AclBindingFilter; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; /** * The result of the {@link KafkaAdminClient#describeAcls(AclBindingFilter)} call. */ +@InterfaceAudience.Public public class DescribeAclsResult { private final KafkaFuture> future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClassicGroupsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClassicGroupsOptions.java index 6422e27524ee8..95e1335077a82 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClassicGroupsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClassicGroupsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#describeClassicGroups(Collection, DescribeClassicGroupsOptions)}. */ +@InterfaceAudience.Public public class DescribeClassicGroupsOptions extends AbstractOptions { private boolean includeAuthorizedOperations; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClassicGroupsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClassicGroupsResult.java index 22d0134569b49..5bfc37d15b63c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClassicGroupsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClassicGroupsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.HashMap; @@ -27,6 +28,7 @@ /** * The result of the {@link Admin#describeClassicGroups(Collection, DescribeClassicGroupsOptions)}} call. */ +@InterfaceAudience.Public public class DescribeClassicGroupsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClientQuotasOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClientQuotasOptions.java index 9030378e2220e..6f5a11983b3b3 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClientQuotasOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClientQuotasOptions.java @@ -17,10 +17,12 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.quota.ClientQuotaFilter; /** * Options for {@link Admin#describeClientQuotas(ClientQuotaFilter, DescribeClientQuotasOptions)}. */ +@InterfaceAudience.Public public class DescribeClientQuotasOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClientQuotasResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClientQuotasResult.java index 192918a414f95..ff7fc4ff2acc5 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClientQuotasResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClientQuotasResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.quota.ClientQuotaEntity; import org.apache.kafka.common.quota.ClientQuotaFilter; @@ -26,6 +27,7 @@ /** * The result of the {@link Admin#describeClientQuotas(ClientQuotaFilter, DescribeClientQuotasOptions)} call. */ +@InterfaceAudience.Public public class DescribeClientQuotasResult { private final KafkaFuture>> entities; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClusterOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClusterOptions.java index 910b64fb42874..36a23fd8a2fa7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClusterOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClusterOptions.java @@ -17,9 +17,12 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Options for {@link Admin#describeCluster()}. */ +@InterfaceAudience.Public public class DescribeClusterOptions extends AbstractOptions { private boolean includeAuthorizedOperations; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClusterResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClusterResult.java index 69782d5c9c333..125392c20af9e 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClusterResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeClusterResult.java @@ -20,6 +20,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.Node; import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.Set; @@ -27,6 +28,7 @@ /** * The result of the {@link KafkaAdminClient#describeCluster()} call. */ +@InterfaceAudience.Public public class DescribeClusterResult { private final KafkaFuture> nodes; private final KafkaFuture controller; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConfigsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConfigsOptions.java index 6586b1ff84d50..335cff81d4f64 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConfigsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConfigsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#describeConfigs(Collection)}. */ +@InterfaceAudience.Public public class DescribeConfigsOptions extends AbstractOptions { private boolean includeSynonyms = false; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConfigsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConfigsResult.java index 72cdaf098a368..fbff4d5663c76 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConfigsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConfigsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigResource; import java.util.Collection; @@ -28,6 +29,7 @@ /** * The result of the {@link KafkaAdminClient#describeConfigs(Collection)} call. */ +@InterfaceAudience.Public public class DescribeConfigsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConsumerGroupsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConsumerGroupsOptions.java index 574a8f07fa662..493f851cffba7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConsumerGroupsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConsumerGroupsOptions.java @@ -17,12 +17,15 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#describeConsumerGroups(Collection, DescribeConsumerGroupsOptions)}. *

*/ +@InterfaceAudience.Public public class DescribeConsumerGroupsOptions extends AbstractOptions { private boolean includeAuthorizedOperations; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConsumerGroupsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConsumerGroupsResult.java index f01a6c7b81491..29cecb661af37 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConsumerGroupsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeConsumerGroupsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.HashMap; @@ -27,6 +28,7 @@ /** * The result of the {@link KafkaAdminClient#describeConsumerGroups(Collection, DescribeConsumerGroupsOptions)}} call. */ +@InterfaceAudience.Public public class DescribeConsumerGroupsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeDelegationTokenOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeDelegationTokenOptions.java index 52fad07eae6c0..5beafc0a2cac9 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeDelegationTokenOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeDelegationTokenOptions.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.auth.KafkaPrincipal; import java.util.List; @@ -24,6 +25,7 @@ /** * Options for {@link Admin#describeDelegationToken(DescribeDelegationTokenOptions)}. */ +@InterfaceAudience.Public public class DescribeDelegationTokenOptions extends AbstractOptions { private List owners; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeDelegationTokenResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeDelegationTokenResult.java index 01355c0385f52..37537869e9f67 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeDelegationTokenResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeDelegationTokenResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.token.delegation.DelegationToken; import java.util.List; @@ -25,6 +26,7 @@ /** * The result of the {@link KafkaAdminClient#describeDelegationToken(DescribeDelegationTokenOptions)} call. */ +@InterfaceAudience.Public public class DescribeDelegationTokenResult { private final KafkaFuture> delegationTokens; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeFeaturesOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeFeaturesOptions.java index d364df61dc18f..6c33b06884df1 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeFeaturesOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeFeaturesOptions.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.OptionalInt; /** * Options for {@link AdminClient#describeFeatures(DescribeFeaturesOptions)}. */ +@InterfaceAudience.Public public class DescribeFeaturesOptions extends AbstractOptions { private OptionalInt nodeId = OptionalInt.empty(); diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeFeaturesResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeFeaturesResult.java index c48dc19143077..2b8c3fa521ee0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeFeaturesResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeFeaturesResult.java @@ -14,15 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The result of the {@link Admin#describeFeatures(DescribeFeaturesOptions)} call. * * The API of this class is evolving, see {@link Admin} for details. */ +@InterfaceAudience.Public public class DescribeFeaturesResult { private final KafkaFuture future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeLogDirsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeLogDirsOptions.java index 41cbf3f6d9cbd..fd30968394a24 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeLogDirsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeLogDirsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#describeLogDirs(Collection)} */ +@InterfaceAudience.Public public class DescribeLogDirsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeLogDirsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeLogDirsResult.java index cd2e37d7c8671..999093027f782 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeLogDirsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeLogDirsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.HashMap; @@ -27,6 +28,7 @@ /** * The result of the {@link Admin#describeLogDirs(Collection)} call. */ +@InterfaceAudience.Public public class DescribeLogDirsResult { private final Map>> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeMetadataQuorumOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeMetadataQuorumOptions.java index 8f54cc81f2110..2126290591140 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeMetadataQuorumOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeMetadataQuorumOptions.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Options for {@link Admin#describeMetadataQuorum(DescribeMetadataQuorumOptions)} */ +@InterfaceAudience.Public public class DescribeMetadataQuorumOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeMetadataQuorumResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeMetadataQuorumResult.java index aa9bbe84eadd3..90209bb500cc0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeMetadataQuorumResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeMetadataQuorumResult.java @@ -14,13 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The result of {@link Admin#describeMetadataQuorum(DescribeMetadataQuorumOptions)} */ +@InterfaceAudience.Public public class DescribeMetadataQuorumResult { private final KafkaFuture quorumInfo; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeProducersOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeProducersOptions.java index 6ce4680f98610..3eff322be28df 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeProducersOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeProducersOptions.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; import java.util.Objects; import java.util.OptionalInt; @@ -23,6 +26,7 @@ /** * Options for {@link Admin#describeProducers(Collection)}. */ +@InterfaceAudience.Public public class DescribeProducersOptions extends AbstractOptions { private OptionalInt brokerId = OptionalInt.empty(); diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeProducersResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeProducersResult.java index 597c59b8fff49..d3e24f8127f1f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeProducersResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeProducersResult.java @@ -14,17 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +@InterfaceAudience.Public public class DescribeProducersResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeReplicaLogDirsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeReplicaLogDirsOptions.java index 62b665658ad84..d54488495bc9c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeReplicaLogDirsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeReplicaLogDirsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#describeReplicaLogDirs(Collection)}. */ +@InterfaceAudience.Public public class DescribeReplicaLogDirsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeReplicaLogDirsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeReplicaLogDirsResult.java index 8e01bf80a91bf..045238c47472b 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeReplicaLogDirsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeReplicaLogDirsResult.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartitionReplica; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.requests.DescribeLogDirsResponse; import java.util.Collection; @@ -28,6 +29,7 @@ /** * The result of {@link Admin#describeReplicaLogDirs(Collection)}. */ +@InterfaceAudience.Public public class DescribeReplicaLogDirsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeShareGroupsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeShareGroupsOptions.java index 47a8f008c44de..b3571f3e98afd 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeShareGroupsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeShareGroupsOptions.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#describeShareGroups(Collection, DescribeShareGroupsOptions)}. */ +@InterfaceAudience.Public public class DescribeShareGroupsOptions extends AbstractOptions { private boolean includeAuthorizedOperations; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeShareGroupsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeShareGroupsResult.java index 9ff0fcc610fe0..0b2de542ed582 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeShareGroupsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeShareGroupsResult.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.HashMap; @@ -26,6 +28,7 @@ /** * The result of the {@link KafkaAdminClient#describeShareGroups(Collection, DescribeShareGroupsOptions)}} call. */ +@InterfaceAudience.Public public class DescribeShareGroupsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeStreamsGroupsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeStreamsGroupsOptions.java index 65f11f8c362a0..1b75b71bb85dc 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeStreamsGroupsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeStreamsGroupsOptions.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Collection; @@ -27,6 +28,7 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class DescribeStreamsGroupsOptions extends AbstractOptions { private boolean includeAuthorizedOperations; private boolean includeTopologyDescription; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeStreamsGroupsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeStreamsGroupsResult.java index 1276da2de666f..4ea1d1340eb66 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeStreamsGroupsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeStreamsGroupsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Collection; @@ -31,6 +32,7 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class DescribeStreamsGroupsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsOptions.java index 189c8c17531ae..977a1e0704c4f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#describeTopics(Collection)}. */ +@InterfaceAudience.Public public class DescribeTopicsOptions extends AbstractOptions { private boolean includeAuthorizedOperations; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsResult.java index 300b67f90829f..6f410afd73e2e 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsResult.java @@ -20,6 +20,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicCollection; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.HashMap; @@ -29,6 +30,7 @@ /** * The result of the {@link KafkaAdminClient#describeTopics(Collection)} call. */ +@InterfaceAudience.Public public class DescribeTopicsResult { private final Map> topicIdFutures; private final Map> nameFutures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTransactionsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTransactionsOptions.java index 9f3bd39b8fe08..aab1ef52403aa 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTransactionsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTransactionsOptions.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#describeTransactions(Collection)}. */ +@InterfaceAudience.Public public class DescribeTransactionsOptions extends AbstractOptions { @Override diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTransactionsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTransactionsResult.java index 316c5e1c6d441..606be08ca6feb 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTransactionsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTransactionsResult.java @@ -14,16 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.clients.admin.internals.CoordinatorKey; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutionException; +@InterfaceAudience.Public public class DescribeTransactionsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeUserScramCredentialsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeUserScramCredentialsOptions.java index 34177fd7d232c..53e6789041d00 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeUserScramCredentialsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeUserScramCredentialsOptions.java @@ -17,10 +17,13 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; /** * Options for {@link AdminClient#describeUserScramCredentials(List, DescribeUserScramCredentialsOptions)} */ +@InterfaceAudience.Public public class DescribeUserScramCredentialsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeUserScramCredentialsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeUserScramCredentialsResult.java index fad56892f4596..34080f858dd40 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/DescribeUserScramCredentialsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/DescribeUserScramCredentialsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ResourceNotFoundException; import org.apache.kafka.common.internals.KafkaFutureImpl; import org.apache.kafka.common.message.DescribeUserScramCredentialsResponseData; @@ -33,6 +34,7 @@ /** * The result of the {@link Admin#describeUserScramCredentials()} call. */ +@InterfaceAudience.Public public class DescribeUserScramCredentialsResult { private final KafkaFuture dataFuture; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ElectLeadersOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ElectLeadersOptions.java index ccdc0853d980c..9acdba78d6c7c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ElectLeadersOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ElectLeadersOptions.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.ElectionType; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Set; @@ -26,5 +27,6 @@ * * The API of this class is evolving, see {@link Admin} for details. */ +@InterfaceAudience.Public public final class ElectLeadersOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ElectLeadersResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ElectLeadersResult.java index f568d78c668f8..34b8bf2dc175e 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ElectLeadersResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ElectLeadersResult.java @@ -17,10 +17,10 @@ package org.apache.kafka.clients.admin; - import org.apache.kafka.common.ElectionType; import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.internals.KafkaFutureImpl; import java.util.Map; @@ -32,6 +32,7 @@ * * The API of this class is evolving, see {@link Admin} for details. */ +@InterfaceAudience.Public public final class ElectLeadersResult { private final KafkaFuture>> electionFuture; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/EndpointType.java b/clients/src/main/java/org/apache/kafka/clients/admin/EndpointType.java index e77d88a013a72..6fe00acd1e547 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/EndpointType.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/EndpointType.java @@ -17,9 +17,12 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Identifies the endpoint type, as specified by KIP-919. */ +@InterfaceAudience.Public public enum EndpointType { UNKNOWN((byte) 0), BROKER((byte) 1), diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ExpireDelegationTokenOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ExpireDelegationTokenOptions.java index 17dfbf4f51491..d4c71d6544266 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ExpireDelegationTokenOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ExpireDelegationTokenOptions.java @@ -17,9 +17,12 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Options for {@link Admin#expireDelegationToken(byte[], ExpireDelegationTokenOptions)}. */ +@InterfaceAudience.Public public class ExpireDelegationTokenOptions extends AbstractOptions { private long expiryTimePeriodMs = -1L; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ExpireDelegationTokenResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ExpireDelegationTokenResult.java index aefeb9a9139c3..be074715e9659 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ExpireDelegationTokenResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ExpireDelegationTokenResult.java @@ -18,10 +18,12 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The result of the {@link KafkaAdminClient#expireDelegationToken(byte[], ExpireDelegationTokenOptions)} call. */ +@InterfaceAudience.Public public class ExpireDelegationTokenResult { private final KafkaFuture expiryTimestamp; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/FeatureMetadata.java b/clients/src/main/java/org/apache/kafka/clients/admin/FeatureMetadata.java index 8e2a7d594f694..80f5d236d550b 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/FeatureMetadata.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/FeatureMetadata.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -27,6 +29,7 @@ * Encapsulates details about finalized as well as supported features. This is particularly useful * to hold the result returned by the {@link Admin#describeFeatures(DescribeFeaturesOptions)} API. */ +@InterfaceAudience.Public public class FeatureMetadata { private final Map finalizedFeatures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/FeatureUpdate.java b/clients/src/main/java/org/apache/kafka/clients/admin/FeatureUpdate.java index 0b7b78ff9a0b8..c52cdb0f992fd 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/FeatureUpdate.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/FeatureUpdate.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Encapsulates details about an update to a finalized feature. */ +@InterfaceAudience.Public public class FeatureUpdate { private final short maxVersionLevel; private final UpgradeType upgradeType; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/FenceProducersOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/FenceProducersOptions.java index fe9df10f20d99..ce6d22146411d 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/FenceProducersOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/FenceProducersOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; /** * Options for {@link Admin#fenceProducers(Collection, FenceProducersOptions)} */ +@InterfaceAudience.Public public class FenceProducersOptions extends AbstractOptions { @Override diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/FenceProducersResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/FenceProducersResult.java index c1954f308accd..6d8a9ad72171c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/FenceProducersResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/FenceProducersResult.java @@ -19,6 +19,7 @@ import org.apache.kafka.clients.admin.internals.CoordinatorKey; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.ProducerIdAndEpoch; import java.util.Collection; @@ -28,6 +29,7 @@ /** * The result of the {@link Admin#fenceProducers(Collection)} call. */ +@InterfaceAudience.Public public class FenceProducersResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/FinalizedVersionRange.java b/clients/src/main/java/org/apache/kafka/clients/admin/FinalizedVersionRange.java index 189ffe8235794..3b497dc46f143 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/FinalizedVersionRange.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/FinalizedVersionRange.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Represents a range of version levels supported by every broker in a cluster for some feature. */ +@InterfaceAudience.Public public class FinalizedVersionRange { private final short minVersionLevel; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ForwardingAdmin.java b/clients/src/main/java/org/apache/kafka/clients/admin/ForwardingAdmin.java index b99e4f6587bd7..e7f8f439d51e0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ForwardingAdmin.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ForwardingAdmin.java @@ -27,6 +27,7 @@ import org.apache.kafka.common.Uuid; import org.apache.kafka.common.acl.AclBinding; import org.apache.kafka.common.acl.AclBindingFilter; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigResource; import org.apache.kafka.common.metrics.KafkaMetric; import org.apache.kafka.common.quota.ClientQuotaAlteration; @@ -46,6 +47,7 @@ * The class must have a constructor with signature {@code (Map config)} for configuring * a decorated {@link KafkaAdminClient} and any other clients needed for external resource management. */ +@InterfaceAudience.Public public class ForwardingAdmin implements Admin { private final Admin delegate; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/GroupListing.java b/clients/src/main/java/org/apache/kafka/clients/admin/GroupListing.java index 8097f91ab0b36..89e4c80a418e0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/GroupListing.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/GroupListing.java @@ -14,10 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.GroupState; import org.apache.kafka.common.GroupType; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Objects; import java.util.Optional; @@ -25,6 +27,7 @@ /** * A listing of a group in the cluster. */ +@InterfaceAudience.Public public class GroupListing { private final String groupId; private final Optional type; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java b/clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java index 5e2924e9ce9a3..c2e1a980501ef 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java @@ -88,6 +88,7 @@ import org.apache.kafka.common.acl.AclBinding; import org.apache.kafka.common.acl.AclBindingFilter; import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.config.ConfigResource; import org.apache.kafka.common.errors.ApiException; @@ -317,6 +318,7 @@ * This class is thread-safe. *

*/ +@InterfaceAudience.Public public class KafkaAdminClient extends AdminClient { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListConfigResourcesOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListConfigResourcesOptions.java index dbd8581c7953b..177c7baec2fae 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListConfigResourcesOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListConfigResourcesOptions.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Options for {@link Admin#listConfigResources()}. */ +@InterfaceAudience.Public public class ListConfigResourcesOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListConfigResourcesResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListConfigResourcesResult.java index fa9ad46a72cad..0df4409dc1c05 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListConfigResourcesResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListConfigResourcesResult.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigResource; import org.apache.kafka.common.internals.KafkaFutureImpl; @@ -26,6 +27,7 @@ * The result of the {@link Admin#listConfigResources()} call. *

*/ +@InterfaceAudience.Public public class ListConfigResourcesResult { private final KafkaFuture> future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsOptions.java index 0a9aeddfdedca..f5c548796f937 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsOptions.java @@ -17,10 +17,13 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Options for {@link Admin#listConsumerGroupOffsets(java.util.Map)} and {@link Admin#listConsumerGroupOffsets(String)}. *

*/ +@InterfaceAudience.Public public class ListConsumerGroupOffsetsOptions extends AbstractOptions { private boolean requireStable = false; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsResult.java index 13797d1e9bb86..aa2a005f27f3c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsResult.java @@ -21,6 +21,7 @@ import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.HashMap; import java.util.Map; @@ -33,6 +34,7 @@ * {@link Admin#listConsumerGroupOffsets(String)} call. *

*/ +@InterfaceAudience.Public public class ListConsumerGroupOffsetsResult { final Map>> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsSpec.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsSpec.java index f2b92627611f7..224e75a5a7ebb 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsSpec.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListConsumerGroupOffsetsSpec.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.Objects; @@ -25,6 +26,7 @@ /** * Specification of consumer group offsets to list using {@link Admin#listConsumerGroupOffsets(java.util.Map)}. */ +@InterfaceAudience.Public public class ListConsumerGroupOffsetsSpec { private Collection topicPartitions; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListGroupsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListGroupsOptions.java index 3937f6cb0356d..76d712805dbcb 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListGroupsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListGroupsOptions.java @@ -14,17 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.clients.consumer.internals.ConsumerProtocol; import org.apache.kafka.common.GroupState; import org.apache.kafka.common.GroupType; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Set; /** * Options for {@link Admin#listGroups()}. */ +@InterfaceAudience.Public public class ListGroupsOptions extends AbstractOptions { private Set groupStates = Set.of(); diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListGroupsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListGroupsResult.java index 88815bccb3c69..05581b365f713 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListGroupsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListGroupsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.internals.KafkaFutureImpl; import java.util.ArrayList; @@ -28,6 +29,7 @@ /** * The result of the {@link Admin#listGroups()} call. */ +@InterfaceAudience.Public public class ListGroupsResult { private final KafkaFutureImpl> all; private final KafkaFutureImpl> valid; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListOffsetsOptions.java index 1da66716ea4e0..691759be9f053 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListOffsetsOptions.java @@ -14,15 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.IsolationLevel; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; /** * Options for {@link AdminClient#listOffsets(Map)}. */ +@InterfaceAudience.Public public class ListOffsetsOptions extends AbstractOptions { private final IsolationLevel isolationLevel; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListOffsetsResult.java index 3d72409a72aca..b4e27d6ff5d13 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListOffsetsResult.java @@ -14,10 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.HashMap; import java.util.Map; @@ -27,6 +29,7 @@ /** * The result of the {@link AdminClient#listOffsets(Map)} call. */ +@InterfaceAudience.Public public class ListOffsetsResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListPartitionReassignmentsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListPartitionReassignmentsOptions.java index 2a456d920bfcf..ba273b3815071 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListPartitionReassignmentsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListPartitionReassignmentsOptions.java @@ -17,8 +17,11 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Options for {@link AdminClient#listPartitionReassignments(ListPartitionReassignmentsOptions)} */ +@InterfaceAudience.Public public class ListPartitionReassignmentsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListPartitionReassignmentsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListPartitionReassignmentsResult.java index bc72c0683f96b..7840e551a45a1 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListPartitionReassignmentsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListPartitionReassignmentsResult.java @@ -19,6 +19,7 @@ import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; @@ -27,6 +28,7 @@ * * The API of this class is evolving. See {@link AdminClient} for details. */ +@InterfaceAudience.Public public class ListPartitionReassignmentsResult { private final KafkaFuture> future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsOptions.java index 4d6f4096c5e21..890057c00e4ba 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsOptions.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Options for {@link Admin#listShareGroupOffsets(Map, ListShareGroupOffsetsOptions)}. */ +@InterfaceAudience.Public public class ListShareGroupOffsetsOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsResult.java index ce3fbf7b24a6f..c0cff3b83808f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsResult.java @@ -14,11 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.clients.admin.internals.CoordinatorKey; import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.HashMap; import java.util.Map; @@ -28,6 +30,7 @@ /** * The result of the {@link Admin#listShareGroupOffsets(Map, ListShareGroupOffsetsOptions)} call. */ +@InterfaceAudience.Public public class ListShareGroupOffsetsResult { private final Map>> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsSpec.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsSpec.java index 08eb50417e6fb..77488031e4db7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsSpec.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListShareGroupOffsetsSpec.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.Map; @@ -25,6 +27,7 @@ /** * Specification of share group offsets to list using {@link Admin#listShareGroupOffsets(Map, ListShareGroupOffsetsOptions)}. */ +@InterfaceAudience.Public public class ListShareGroupOffsetsSpec { private Collection topicPartitions; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsOptions.java index 08835d817e63e..b1b8837f68c52 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsOptions.java @@ -17,15 +17,16 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; - /** * Options for {@link Admin#listStreamsGroupOffsets(java.util.Map, ListStreamsGroupOffsetsOptions)}. *

* The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class ListStreamsGroupOffsetsOptions extends AbstractOptions { private boolean requireStable = false; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsResult.java index 3abf578f71a4e..fa796f5c7590d 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsResult.java @@ -21,6 +21,7 @@ import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Map; @@ -31,6 +32,7 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class ListStreamsGroupOffsetsResult { private final ListConsumerGroupOffsetsResult delegate; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsSpec.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsSpec.java index 4f5380f749101..3857c3bf709ae 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsSpec.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListStreamsGroupOffsetsSpec.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Collection; @@ -29,6 +30,7 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class ListStreamsGroupOffsetsSpec { private Collection topicPartitions; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListTopicsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListTopicsOptions.java index 62ecc2866982d..4164fecb09263 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListTopicsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListTopicsOptions.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Options for {@link Admin#listTopics()}. */ +@InterfaceAudience.Public public class ListTopicsOptions extends AbstractOptions { private boolean listInternal = false; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListTopicsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListTopicsResult.java index bf7ce6ef1a577..330383e762710 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListTopicsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListTopicsResult.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.Map; @@ -26,6 +27,7 @@ /** * The result of the {@link Admin#listTopics()} call. */ +@InterfaceAudience.Public public class ListTopicsResult { final KafkaFuture> future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListTransactionsOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListTransactionsOptions.java index 72a796308d45b..259f36d0071ef 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListTransactionsOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListTransactionsOptions.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -26,6 +28,7 @@ /** * Options for {@link Admin#listTransactions()}. */ +@InterfaceAudience.Public public class ListTransactionsOptions extends AbstractOptions { private Set filteredStates = Collections.emptySet(); private Set filteredProducerIds = Collections.emptySet(); diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ListTransactionsResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/ListTransactionsResult.java index 7c48912bb44aa..870958af00c0d 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ListTransactionsResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ListTransactionsResult.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.internals.KafkaFutureImpl; import java.util.ArrayList; @@ -31,6 +32,7 @@ * The result of the {@link Admin#listTransactions()} call. *

*/ +@InterfaceAudience.Public public class ListTransactionsResult { private final KafkaFuture>>> future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/LogDirDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/LogDirDescription.java index a541fa7e4acbf..75efbf9bb2e08 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/LogDirDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/LogDirDescription.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ApiException; import java.util.Map; @@ -28,6 +29,7 @@ /** * A description of a log directory on a particular broker. */ +@InterfaceAudience.Public public class LogDirDescription { private final Map replicaInfos; private final ApiException error; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/MemberAssignment.java b/clients/src/main/java/org/apache/kafka/clients/admin/MemberAssignment.java index ec30b83baf771..b1f8f1474c80c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/MemberAssignment.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/MemberAssignment.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collections; import java.util.Objects; @@ -26,6 +28,7 @@ /** * A description of the assignments of a specific group member. */ +@InterfaceAudience.Public public class MemberAssignment { private final Set topicPartitions; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/MemberDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/MemberDescription.java index b45abcdcd7ca2..dcb40b6349b6f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/MemberDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/MemberDescription.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.GroupType; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collections; import java.util.Objects; @@ -25,6 +27,7 @@ /** * A detailed description of a single group member in the cluster. */ +@InterfaceAudience.Public public class MemberDescription { private final String memberId; private final Optional groupInstanceId; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/MemberToRemove.java b/clients/src/main/java/org/apache/kafka/clients/admin/MemberToRemove.java index 5ca5463d3f285..006e3bf977570 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/MemberToRemove.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/MemberToRemove.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.message.LeaveGroupRequestData.MemberIdentity; import org.apache.kafka.common.requests.JoinGroupRequest; @@ -24,6 +25,7 @@ /** * A struct containing information about the member to be removed. */ +@InterfaceAudience.Public public class MemberToRemove { private final String groupInstanceId; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/NewPartitionReassignment.java b/clients/src/main/java/org/apache/kafka/clients/admin/NewPartitionReassignment.java index 0a37c012cc79a..91b123c5e5951 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/NewPartitionReassignment.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/NewPartitionReassignment.java @@ -17,12 +17,15 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; import java.util.Map; /** * A new partition reassignment, which can be applied via {@link AdminClient#alterPartitionReassignments(Map, AlterPartitionReassignmentsOptions)}. */ +@InterfaceAudience.Public public class NewPartitionReassignment { private final List targetReplicas; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/NewPartitions.java b/clients/src/main/java/org/apache/kafka/clients/admin/NewPartitions.java index 53514adcceaf2..dfadf38ada50c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/NewPartitions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/NewPartitions.java @@ -17,12 +17,15 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; import java.util.Map; /** * Describes new partitions for a particular topic in a call to {@link Admin#createPartitions(Map)}. */ +@InterfaceAudience.Public public class NewPartitions { private final int totalCount; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/NewTopic.java b/clients/src/main/java/org/apache/kafka/clients/admin/NewTopic.java index 0f1107c91c9be..f7658d6c45db1 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/NewTopic.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/NewTopic.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.message.CreateTopicsRequestData.CreatableReplicaAssignment; import org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopic; import org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopicConfig; @@ -33,6 +34,7 @@ /** * A new topic to be created via {@link Admin#createTopics(Collection)}. */ +@InterfaceAudience.Public public class NewTopic { private final String name; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/OffsetSpec.java b/clients/src/main/java/org/apache/kafka/clients/admin/OffsetSpec.java index ad73c8d51f086..32e4031c4e473 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/OffsetSpec.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/OffsetSpec.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * This class allows to specify the desired offsets when using {@link KafkaAdminClient#listOffsets(Map, ListOffsetsOptions)} */ +@InterfaceAudience.Public public class OffsetSpec { public static class EarliestSpec extends OffsetSpec { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/PartitionReassignment.java b/clients/src/main/java/org/apache/kafka/clients/admin/PartitionReassignment.java index 4a9d151f1b057..9f6144d64b8ab 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/PartitionReassignment.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/PartitionReassignment.java @@ -17,12 +17,15 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collections; import java.util.List; /** * A partition reassignment, which has been listed via {@link AdminClient#listPartitionReassignments()}. */ +@InterfaceAudience.Public public class PartitionReassignment { private final List replicas; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ProducerState.java b/clients/src/main/java/org/apache/kafka/clients/admin/ProducerState.java index 243edded6c138..3566939493ca2 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ProducerState.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ProducerState.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import java.util.OptionalInt; import java.util.OptionalLong; +@InterfaceAudience.Public public class ProducerState { private final long producerId; private final int producerEpoch; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/QuorumInfo.java b/clients/src/main/java/org/apache/kafka/clients/admin/QuorumInfo.java index 5264b6f6aae7a..39f6415c56c74 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/QuorumInfo.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/QuorumInfo.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.List; import java.util.Map; @@ -26,6 +28,7 @@ /** * This class is used to describe the state of the quorum received in DescribeQuorumResponse. */ +@InterfaceAudience.Public public class QuorumInfo { private final int leaderId; private final long leaderEpoch; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/RaftVoterEndpoint.java b/clients/src/main/java/org/apache/kafka/clients/admin/RaftVoterEndpoint.java index c137c2edae161..75cbc7862627e 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/RaftVoterEndpoint.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/RaftVoterEndpoint.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Locale; @@ -25,6 +26,7 @@ * An endpoint for a raft quorum voter. */ @InterfaceStability.Stable +@InterfaceAudience.Public public class RaftVoterEndpoint { private final String listener; private final String host; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/RecordsToDelete.java b/clients/src/main/java/org/apache/kafka/clients/admin/RecordsToDelete.java index 57421e3568b4f..128a0c619fe39 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/RecordsToDelete.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/RecordsToDelete.java @@ -17,11 +17,14 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Describe records to delete in a call to {@link Admin#deleteRecords(Map)} */ +@InterfaceAudience.Public public class RecordsToDelete { private final long offset; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/RemoveMembersFromConsumerGroupOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/RemoveMembersFromConsumerGroupOptions.java index 3cd625d823739..9e24f4394ee4c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/RemoveMembersFromConsumerGroupOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/RemoveMembersFromConsumerGroupOptions.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -25,6 +28,7 @@ * Options for {@link AdminClient#removeMembersFromConsumerGroup(String, RemoveMembersFromConsumerGroupOptions)}. * It carries the members to be removed from the consumer group. */ +@InterfaceAudience.Public public class RemoveMembersFromConsumerGroupOptions extends AbstractOptions { private final Set members; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/RemoveMembersFromConsumerGroupResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/RemoveMembersFromConsumerGroupResult.java index 3845e2f6aac62..6f55e76ce22b0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/RemoveMembersFromConsumerGroupResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/RemoveMembersFromConsumerGroupResult.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.internals.KafkaFutureImpl; import org.apache.kafka.common.message.LeaveGroupRequestData.MemberIdentity; import org.apache.kafka.common.protocol.Errors; @@ -30,6 +31,7 @@ * * The API of this class is evolving, see {@link Admin} for details. */ +@InterfaceAudience.Public public class RemoveMembersFromConsumerGroupResult { private final KafkaFuture> future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/RemoveRaftVoterOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/RemoveRaftVoterOptions.java index da6e965ebe0fe..3d1bf774485b0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/RemoveRaftVoterOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/RemoveRaftVoterOptions.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import org.apache.kafka.common.protocol.Errors; @@ -33,6 +34,7 @@ * If not provided, the cluster id check is skipped. */ @InterfaceStability.Stable +@InterfaceAudience.Public public class RemoveRaftVoterOptions extends AbstractOptions { private Optional clusterId = Optional.empty(); diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/RemoveRaftVoterResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/RemoveRaftVoterResult.java index 8e8e99ddbfc21..cbab6053dbcfe 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/RemoveRaftVoterResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/RemoveRaftVoterResult.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; /** @@ -25,6 +26,7 @@ * The API of this class is evolving, see {@link Admin} for details. */ @InterfaceStability.Stable +@InterfaceAudience.Public public class RemoveRaftVoterResult { private final KafkaFuture result; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/RenewDelegationTokenOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/RenewDelegationTokenOptions.java index 17f387cef7042..b14d5d61ecce7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/RenewDelegationTokenOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/RenewDelegationTokenOptions.java @@ -17,9 +17,12 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Options for {@link Admin#renewDelegationToken(byte[], RenewDelegationTokenOptions)}. */ +@InterfaceAudience.Public public class RenewDelegationTokenOptions extends AbstractOptions { private long renewTimePeriodMs = -1; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/RenewDelegationTokenResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/RenewDelegationTokenResult.java index 69b15fe1f01a6..615cd93a01bcd 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/RenewDelegationTokenResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/RenewDelegationTokenResult.java @@ -18,10 +18,12 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The result of the {@link KafkaAdminClient#expireDelegationToken(byte[], ExpireDelegationTokenOptions)} call. */ +@InterfaceAudience.Public public class RenewDelegationTokenResult { private final KafkaFuture expiryTimestamp; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ReplicaInfo.java b/clients/src/main/java/org/apache/kafka/clients/admin/ReplicaInfo.java index efe645b704d16..9d7b97e1eef11 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ReplicaInfo.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ReplicaInfo.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A description of a replica on a particular broker. */ +@InterfaceAudience.Public public class ReplicaInfo { private final long size; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ScramCredentialInfo.java b/clients/src/main/java/org/apache/kafka/clients/admin/ScramCredentialInfo.java index e8403b6e12823..6a6ed8f4af672 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ScramCredentialInfo.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ScramCredentialInfo.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** @@ -24,6 +26,7 @@ * * @see KIP-554: Add Broker-side SCRAM Config API */ +@InterfaceAudience.Public public class ScramCredentialInfo { private final ScramMechanism mechanism; private final int iterations; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ScramMechanism.java b/clients/src/main/java/org/apache/kafka/clients/admin/ScramMechanism.java index f5eac3718afed..89111ffa40e3f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ScramMechanism.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ScramMechanism.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; /** @@ -29,6 +31,7 @@ * is used both for passing ScramCredentialUpsertion and for the internal * UserScramCredentialRecord. Do not change the type field. */ +@InterfaceAudience.Public public enum ScramMechanism { UNKNOWN((byte) 0), SCRAM_SHA_256((byte) 1), diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ShareGroupDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/ShareGroupDescription.java index b8be6076699cb..3a7619c893603 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ShareGroupDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ShareGroupDescription.java @@ -20,6 +20,7 @@ import org.apache.kafka.common.GroupState; import org.apache.kafka.common.Node; import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.Collections; @@ -31,6 +32,7 @@ /** * A detailed description of a single share group in the cluster. */ +@InterfaceAudience.Public public class ShareGroupDescription { private final String groupId; private final Collection members; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ShareMemberAssignment.java b/clients/src/main/java/org/apache/kafka/clients/admin/ShareMemberAssignment.java index 9aa86c115ebfe..03703d9c3738f 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ShareMemberAssignment.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ShareMemberAssignment.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collections; import java.util.Objects; @@ -26,6 +28,7 @@ /** * A description of the assignments of a specific share group member. */ +@InterfaceAudience.Public public class ShareMemberAssignment { private final Set topicPartitions; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/ShareMemberDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/ShareMemberDescription.java index 12434702b8a59..cd82d2331058e 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/ShareMemberDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/ShareMemberDescription.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collections; import java.util.Objects; import java.util.Optional; @@ -23,6 +26,7 @@ /** * A detailed description of a single share group member in the cluster. */ +@InterfaceAudience.Public public class ShareMemberDescription { private final String memberId; private final Optional rackId; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/SharePartitionOffsetInfo.java b/clients/src/main/java/org/apache/kafka/clients/admin/SharePartitionOffsetInfo.java index ef564b8374767..9d56925e499c4 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/SharePartitionOffsetInfo.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/SharePartitionOffsetInfo.java @@ -17,12 +17,15 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import java.util.Optional; /** * This class is used to contain the offset and lag information for a share-partition. */ +@InterfaceAudience.Public public class SharePartitionOffsetInfo { private final long startOffset; private final Optional leaderEpoch; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupDescription.java index cb74803a61043..4955c58893640 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupDescription.java @@ -20,6 +20,7 @@ import org.apache.kafka.common.GroupState; import org.apache.kafka.common.Node; import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Collection; @@ -32,6 +33,7 @@ * A detailed description of a single streams group in the cluster. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class StreamsGroupDescription { private final String groupId; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupMemberAssignment.java b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupMemberAssignment.java index 276058143ff3d..680d85a6c0f54 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupMemberAssignment.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupMemberAssignment.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.List; @@ -26,6 +27,7 @@ * A description of the assignments of a specific group member. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class StreamsGroupMemberAssignment { private final List activeTasks; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupMemberDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupMemberDescription.java index 8f4fa126e1320..1cc77360809ff 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupMemberDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupMemberDescription.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.List; @@ -28,6 +29,7 @@ * A detailed description of a single streams groups member in the cluster. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class StreamsGroupMemberDescription { private final String memberId; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupSubtopologyDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupSubtopologyDescription.java index e01cafc98d42a..cabfed6ea33a7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupSubtopologyDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupSubtopologyDescription.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.List; @@ -27,6 +28,7 @@ * A detailed description of a subtopology in a streams group. */ @InterfaceStability.Evolving +@InterfaceAudience.Public public class StreamsGroupSubtopologyDescription { private final String subtopologyId; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupTopologyDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupTopologyDescription.java index 79d6de44e3a1f..83abba629c8f9 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupTopologyDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupTopologyDescription.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Collection; @@ -33,6 +34,7 @@ * callers do not need to depend on {@code kafka-streams}. The wire format only carries the successor relation between * nodes; the {@link Node#predecessors() predecessors} are reconstructed from the successors when this description is built. */ +@InterfaceAudience.Public @InterfaceStability.Evolving public class StreamsGroupTopologyDescription { diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupTopologyDescriptionStatus.java b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupTopologyDescriptionStatus.java index 22fcf4604a038..16cc2f042bc35 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupTopologyDescriptionStatus.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/StreamsGroupTopologyDescriptionStatus.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; /** @@ -26,6 +27,7 @@ * be retrieved. It is paired with {@link StreamsGroupDescription#topologyDescription()}: the * description is present if and only if the status is {@link #AVAILABLE}. */ +@InterfaceAudience.Public @InterfaceStability.Evolving public enum StreamsGroupTopologyDescriptionStatus { diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/SupportedVersionRange.java b/clients/src/main/java/org/apache/kafka/clients/admin/SupportedVersionRange.java index 515189a000851..8c661189a2f37 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/SupportedVersionRange.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/SupportedVersionRange.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Represents a range of versions that a particular broker supports for some feature. */ +@InterfaceAudience.Public public class SupportedVersionRange { private final short minVersion; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/TerminateTransactionOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/TerminateTransactionOptions.java index 0b8caaee93595..390f3f20a1b5b 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/TerminateTransactionOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/TerminateTransactionOptions.java @@ -17,9 +17,12 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Options for {@link Admin#forceTerminateTransaction(String, TerminateTransactionOptions)}. */ +@InterfaceAudience.Public public class TerminateTransactionOptions extends AbstractOptions { @Override diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/TerminateTransactionResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/TerminateTransactionResult.java index 18fee2477be34..ad83ef09e6e34 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/TerminateTransactionResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/TerminateTransactionResult.java @@ -18,10 +18,12 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The result of the {@link Admin#forceTerminateTransaction(String)} call. */ +@InterfaceAudience.Public public class TerminateTransactionResult { private final KafkaFuture future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/TopicDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/TopicDescription.java index c3bbaf318a25e..f8fbd52b28c58 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/TopicDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/TopicDescription.java @@ -20,6 +20,7 @@ import org.apache.kafka.common.TopicPartitionInfo; import org.apache.kafka.common.Uuid; import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collections; import java.util.List; @@ -30,6 +31,7 @@ /** * A detailed description of a single topic in the cluster. */ +@InterfaceAudience.Public public class TopicDescription { private final String name; private final boolean internal; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/TopicListing.java b/clients/src/main/java/org/apache/kafka/clients/admin/TopicListing.java index f402fa298ae2d..49ea07d94be03 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/TopicListing.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/TopicListing.java @@ -18,10 +18,12 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * A listing of a topic in the cluster. */ +@InterfaceAudience.Public public class TopicListing { private final String name; private final Uuid topicId; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/TransactionDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/TransactionDescription.java index 9139f5d344422..4b8f14e913b70 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/TransactionDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/TransactionDescription.java @@ -14,14 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Objects; import java.util.OptionalLong; import java.util.Set; +@InterfaceAudience.Public public class TransactionDescription { private final int coordinatorId; private final TransactionState state; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/TransactionListing.java b/clients/src/main/java/org/apache/kafka/clients/admin/TransactionListing.java index fab2648f9127f..60a7ce88bcad7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/TransactionListing.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/TransactionListing.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; +@InterfaceAudience.Public public class TransactionListing { private final String transactionalId; private final long producerId; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/TransactionState.java b/clients/src/main/java/org/apache/kafka/clients/admin/TransactionState.java index fc7740f8428e9..5d3875e3dd97a 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/TransactionState.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/TransactionState.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; +@InterfaceAudience.Public public enum TransactionState { ONGOING("Ongoing"), PREPARE_ABORT("PrepareAbort"), diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/UnregisterBrokerOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/UnregisterBrokerOptions.java index 63e0a06ea2486..194680391adf5 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/UnregisterBrokerOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/UnregisterBrokerOptions.java @@ -17,8 +17,11 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Options for {@link Admin#unregisterBroker(int, UnregisterBrokerOptions)}. */ +@InterfaceAudience.Public public class UnregisterBrokerOptions extends AbstractOptions { } diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/UnregisterBrokerResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/UnregisterBrokerResult.java index b44c7e08cbea9..e8a79427cbac1 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/UnregisterBrokerResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/UnregisterBrokerResult.java @@ -18,12 +18,14 @@ package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The result of the {@link Admin#unregisterBroker(int, UnregisterBrokerOptions)} call. * * The API of this class is evolving, see {@link Admin} for details. */ +@InterfaceAudience.Public public class UnregisterBrokerResult { private final KafkaFuture future; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/UpdateFeaturesOptions.java b/clients/src/main/java/org/apache/kafka/clients/admin/UpdateFeaturesOptions.java index af161fda07e05..e4e86c02bb45c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/UpdateFeaturesOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/UpdateFeaturesOptions.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * Options for {@link AdminClient#updateFeatures(Map, UpdateFeaturesOptions)}. */ +@InterfaceAudience.Public public class UpdateFeaturesOptions extends AbstractOptions { private boolean validateOnly = false; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/UpdateFeaturesResult.java b/clients/src/main/java/org/apache/kafka/clients/admin/UpdateFeaturesResult.java index 36418ecb83f5b..736210cdfe0e7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/UpdateFeaturesResult.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/UpdateFeaturesResult.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.admin; import org.apache.kafka.common.KafkaFuture; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; @@ -25,6 +27,7 @@ * * The API of this class is evolving, see {@link Admin} for details. */ +@InterfaceAudience.Public public class UpdateFeaturesResult { private final Map> futures; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialAlteration.java b/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialAlteration.java index 8293fe514df19..97ef99af591f3 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialAlteration.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialAlteration.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** @@ -24,6 +26,7 @@ * * @see KIP-554: Add Broker-side SCRAM Config API */ +@InterfaceAudience.Public public abstract class UserScramCredentialAlteration { protected final String user; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialDeletion.java b/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialDeletion.java index 633075aaf2f2b..a1c59888e5291 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialDeletion.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialDeletion.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** @@ -24,6 +26,7 @@ * * @see KIP-554: Add Broker-side SCRAM Config API */ +@InterfaceAudience.Public public class UserScramCredentialDeletion extends UserScramCredentialAlteration { private final ScramMechanism mechanism; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialUpsertion.java b/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialUpsertion.java index 5d5cf9cbad347..a89d00955de7a 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialUpsertion.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialUpsertion.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.scram.internals.ScramFormatter; import java.nio.charset.StandardCharsets; @@ -28,6 +29,7 @@ * * @see KIP-554: Add Broker-side SCRAM Config API */ +@InterfaceAudience.Public public class UserScramCredentialUpsertion extends UserScramCredentialAlteration { private final ScramCredentialInfo info; private final byte[] salt; diff --git a/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialsDescription.java b/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialsDescription.java index 03a713149be47..f6dca59b98e7d 100644 --- a/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialsDescription.java +++ b/clients/src/main/java/org/apache/kafka/clients/admin/UserScramCredentialsDescription.java @@ -17,6 +17,8 @@ package org.apache.kafka.clients.admin; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; import java.util.Objects; @@ -26,6 +28,7 @@ * * @see KIP-554: Add Broker-side SCRAM Config API */ +@InterfaceAudience.Public public class UserScramCredentialsDescription { private final String name; private final List credentialInfos; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/AcknowledgeType.java b/clients/src/main/java/org/apache/kafka/clients/consumer/AcknowledgeType.java index 74ddee17c08a8..c53863d571e71 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/AcknowledgeType.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/AcknowledgeType.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Locale; /** * The acknowledge type is used with {@link KafkaShareConsumer#acknowledge(ConsumerRecord, AcknowledgeType)} to indicate * whether the record was consumed successfully. */ +@InterfaceAudience.Public public enum AcknowledgeType { /** The record was consumed successfully. */ ACCEPT((byte) 1), diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/AcknowledgementCommitCallback.java b/clients/src/main/java/org/apache/kafka/clients/consumer/AcknowledgementCommitCallback.java index 4b61244541f41..7f3bdc50e0dce 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/AcknowledgementCommitCallback.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/AcknowledgementCommitCallback.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.TopicIdPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.AuthorizationException; import org.apache.kafka.common.errors.DisconnectException; import org.apache.kafka.common.errors.InterruptException; @@ -32,6 +33,7 @@ * A callback interface that the user can implement to trigger custom actions when an acknowledgement completes. * The callback may be executed in any thread calling {@link ShareConsumer#poll(java.time.Duration)}. */ +@InterfaceAudience.Public public interface AcknowledgementCommitCallback { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/CloseOptions.java b/clients/src/main/java/org/apache/kafka/clients/consumer/CloseOptions.java index b0862ce76b29d..db4f7ec523c41 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/CloseOptions.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/CloseOptions.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.clients.consumer.internals.ConsumerUtils; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.time.Duration; import java.util.Objects; @@ -29,6 +31,7 @@ * when a consumer is being shut down. *

*/ +@InterfaceAudience.Public public class CloseOptions { /** * Enum to specify the group membership operation upon leaving a group. diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/CommitFailedException.java b/clients/src/main/java/org/apache/kafka/clients/consumer/CommitFailedException.java index 720fc70301dcb..9983bd2b3e7c8 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/CommitFailedException.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/CommitFailedException.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * This exception is raised when an offset commit with {@link KafkaConsumer#commitSync()} fails @@ -25,6 +27,7 @@ * the commit cannot generally be retried because some of the partitions may have already been * assigned to another member in the group. */ +@InterfaceAudience.Public public class CommitFailedException extends KafkaException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/Consumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/Consumer.java index 365d19d41349a..186b137b5eb47 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/Consumer.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/Consumer.java @@ -21,6 +21,7 @@ import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.KafkaMetric; import java.io.Closeable; @@ -36,6 +37,7 @@ * @see KafkaConsumer * @see MockConsumer */ +@InterfaceAudience.Public public interface Consumer extends Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerConfig.java b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerConfig.java index 4dd6002ece595..80130cd7188fb 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerConfig.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerConfig.java @@ -23,6 +23,7 @@ import org.apache.kafka.clients.consumer.internals.ShareAcknowledgementMode; import org.apache.kafka.clients.consumer.internals.ShareAcquireMode; import org.apache.kafka.common.IsolationLevel; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.AbstractConfig; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; @@ -57,6 +58,7 @@ /** * The consumer configuration keys */ +@InterfaceAudience.Public public class ConsumerConfig extends AbstractConfig { private static final ConfigDef CONFIG; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerGroupMetadata.java b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerGroupMetadata.java index 95f4ff23fdfcd..49c1883c584f3 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerGroupMetadata.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerGroupMetadata.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.consumer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.requests.JoinGroupRequest; import java.util.Objects; @@ -25,6 +26,7 @@ * A metadata struct containing the consumer group information. * Note: Any change to this class is considered public and requires a KIP. */ +@InterfaceAudience.Public public class ConsumerGroupMetadata { private final String groupId; private final int generationId; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerInterceptor.java b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerInterceptor.java index 206e6d04a2c2b..16ba530fab33a 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerInterceptor.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerInterceptor.java @@ -14,11 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.clients.consumer; +package org.apache.kafka.clients.consumer; import org.apache.kafka.common.Configurable; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; @@ -42,6 +43,7 @@ * Implement {@link org.apache.kafka.common.metrics.Monitorable} to enable the interceptor to register metrics. The following tags are automatically added to * all metrics registered: config set to interceptor.classes, and class set to the ConsumerInterceptor class name. */ +@InterfaceAudience.Public public interface ConsumerInterceptor extends Configurable, AutoCloseable { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java index f7158a9fd8db3..9a3179969e871 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java @@ -20,6 +20,7 @@ import org.apache.kafka.common.Configurable; import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Utils; import java.nio.ByteBuffer; @@ -48,6 +49,7 @@ *

* The implementation can extend {@link Configurable} to get configs from consumer. */ +@InterfaceAudience.Public public interface ConsumerPartitionAssignor { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRebalanceListener.java b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRebalanceListener.java index 3743e5d5df158..942793a996982 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRebalanceListener.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRebalanceListener.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.time.Duration; import java.util.Collection; @@ -134,6 +136,7 @@ * @see RebalanceListener * @see RebalanceConsumer */ +@InterfaceAudience.Public public interface ConsumerRebalanceListener extends RebalanceListener { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecord.java b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecord.java index e25746c5f58af..fbdd8e0f74a95 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecord.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecord.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.consumer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; import org.apache.kafka.common.record.TimestampType; @@ -52,6 +53,7 @@ *

* Refer to the {@link KafkaConsumer} documentation for more details on multi-threaded consumption and processing strategies. */ +@InterfaceAudience.Public public class ConsumerRecord { public static final long NO_TIMESTAMP = RecordBatch.NO_TIMESTAMP; public static final int NULL_SIZE = -1; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecords.java b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecords.java index a7299a292353f..7c1260ca824eb 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecords.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRecords.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.consumer; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.internals.AbstractIterator; import org.slf4j.Logger; @@ -36,6 +37,7 @@ * particular topic. There is one {@link ConsumerRecord} list for every topic * partition returned by a {@link Consumer#poll(java.time.Duration)} operation. */ +@InterfaceAudience.Public public class ConsumerRecords implements Iterable> { private static final Logger log = LoggerFactory.getLogger(ConsumerRecords.class); diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/CooperativeStickyAssignor.java b/clients/src/main/java/org/apache/kafka/clients/consumer/CooperativeStickyAssignor.java index 80cc8c0997706..c6d5272680cd7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/CooperativeStickyAssignor.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/CooperativeStickyAssignor.java @@ -19,6 +19,8 @@ import org.apache.kafka.clients.consumer.internals.AbstractStickyAssignor; import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.protocol.types.Field; import org.apache.kafka.common.protocol.types.Schema; import org.apache.kafka.common.protocol.types.Struct; @@ -48,6 +50,8 @@ * IMPORTANT: if upgrading from 2.3 or earlier, you must follow a specific upgrade path in order to safely turn on * cooperative rebalancing. See the upgrade guide for details. */ +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: extends internal AbstractStickyAssignor — pending KIP review to promote the parent or refactor the assignor hierarchy") public class CooperativeStickyAssignor extends AbstractStickyAssignor { public static final String COOPERATIVE_STICKY_ASSIGNOR_NAME = "cooperative-sticky"; @@ -85,6 +89,9 @@ public ByteBuffer subscriptionUserData(Set topics) { } @Override + @SuppressKafkaInternalApiUsage("KIP-1265: forced override of AbstractStickyAssignor#memberData (internal) — " + + "the abstract parent declares the MemberData return type. Pending refactor to either promote MemberData " + + "or replace the hook with a public-typed equivalent.") protected MemberData memberData(Subscription subscription) { // In ConsumerProtocolSubscription v2 or higher, we can take member data from fields directly if (subscription.generationId().isPresent()) { diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/GroupProtocol.java b/clients/src/main/java/org/apache/kafka/clients/consumer/GroupProtocol.java index 7afc8b89cb2e0..2458312427f5c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/GroupProtocol.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/GroupProtocol.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Locale; /** @@ -25,6 +28,7 @@ *

  • {@link #CONSUMER} - The Consumer rebalance protocol (KIP-848)
  • * */ +@InterfaceAudience.Public public enum GroupProtocol { /** Classic group protocol. */ CLASSIC("CLASSIC"), diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/InvalidOffsetException.java b/clients/src/main/java/org/apache/kafka/clients/consumer/InvalidOffsetException.java index b1e1689290454..f646325b5edc0 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/InvalidOffsetException.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/InvalidOffsetException.java @@ -14,10 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Set; @@ -27,6 +29,7 @@ * @see NoOffsetForPartitionException * @see OffsetOutOfRangeException */ +@InterfaceAudience.Public public abstract class InvalidOffsetException extends KafkaException { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java index 514e24f48aa40..6b3af268b5f10 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java @@ -28,6 +28,7 @@ import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.InterruptException; import org.apache.kafka.common.errors.InvalidRegularExpression; import org.apache.kafka.common.errors.WakeupException; @@ -536,6 +537,7 @@ * the consumer threads can hash into these queues using the TopicPartition to ensure in-order consumption and simplify * commit. */ +@InterfaceAudience.Public public class KafkaConsumer implements Consumer { private static final ConsumerDelegateCreator CREATOR = new ConsumerDelegateCreator(); diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaShareConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaShareConsumer.java index ad716ec3bd492..53c1038667f83 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaShareConsumer.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaShareConsumer.java @@ -27,6 +27,7 @@ import org.apache.kafka.common.MetricName; import org.apache.kafka.common.TopicIdPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.AuthenticationException; import org.apache.kafka.common.errors.AuthorizationException; import org.apache.kafka.common.errors.InterruptException; @@ -390,6 +391,7 @@ * We have intentionally avoided implementing a particular threading model for processing. Various options for * multithreaded processing are possible, of which the most straightforward is to dedicate a thread to each consumer. */ +@InterfaceAudience.Public public class KafkaShareConsumer implements ShareConsumer { private static final ShareConsumerDelegateCreator CREATOR = new ShareConsumerDelegateCreator(); diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/LogTruncationException.java b/clients/src/main/java/org/apache/kafka/clients/consumer/LogTruncationException.java index ead11628c78dd..d05719417ccf7 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/LogTruncationException.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/LogTruncationException.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collections; import java.util.Map; @@ -29,6 +31,7 @@ * has been defined) with the first offset known to diverge from what the * consumer previously read. */ +@InterfaceAudience.Public public class LogTruncationException extends OffsetOutOfRangeException { private final Map divergentOffsets; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/MockConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/MockConsumer.java index 2a3e0cdc53de8..aec8781283521 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/MockConsumer.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/MockConsumer.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.clients.Metadata; @@ -25,6 +26,7 @@ import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.TimeoutException; import org.apache.kafka.common.errors.WakeupException; import org.apache.kafka.common.metrics.KafkaMetric; @@ -50,13 +52,13 @@ import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.DEFAULT_CLOSE_TIMEOUT_MS; - /** * A mock of the {@link Consumer} interface you can use for testing code that uses Kafka. This class is not * threadsafe . However, you can use the {@link #schedulePollTask(Runnable)} method to write multithreaded tests * where a driver thread waits for {@link #poll(Duration)} to be called by a background thread and then can safely perform * operations during a callback. */ +@InterfaceAudience.Public public class MockConsumer implements Consumer { private final Map> partitions; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/MockShareConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/MockShareConsumer.java index 83a9761098e2a..df9501f3ea31d 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/MockShareConsumer.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/MockShareConsumer.java @@ -24,6 +24,7 @@ import org.apache.kafka.common.TopicIdPartition; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.KafkaMetric; import org.apache.kafka.common.utils.internals.LogContext; @@ -44,6 +45,7 @@ * A mock of the {@link ShareConsumer} interface you can use for testing code that uses Kafka. This class is not * thread-safe . */ +@InterfaceAudience.Public public class MockShareConsumer implements ShareConsumer { private final SubscriptionState subscriptions; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/NoOffsetForPartitionException.java b/clients/src/main/java/org/apache/kafka/clients/consumer/NoOffsetForPartitionException.java index 9ea7abefb718b..523b3930a0ded 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/NoOffsetForPartitionException.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/NoOffsetForPartitionException.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; import java.util.Collections; @@ -26,6 +28,7 @@ * Indicates that there is no stored offset for a partition and no defined offset * reset policy. */ +@InterfaceAudience.Public public class NoOffsetForPartitionException extends InvalidOffsetException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndMetadata.java b/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndMetadata.java index 98f847df64c3c..5d4d1550c1601 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndMetadata.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndMetadata.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.consumer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.requests.OffsetFetchResponse; import java.io.Serializable; @@ -27,6 +28,7 @@ * when an offset is committed. This can be useful (for example) to store information about which * node made the commit, what time the commit was made, etc. */ +@InterfaceAudience.Public public class OffsetAndMetadata implements Serializable { private static final long serialVersionUID = 2019555404968089681L; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndTimestamp.java b/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndTimestamp.java index a62d69607da8f..83131c3af50b2 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndTimestamp.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetAndTimestamp.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import java.util.Optional; /** * A container class for offset and timestamp. */ +@InterfaceAudience.Public public final class OffsetAndTimestamp { private final long timestamp; private final long offset; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetCommitCallback.java b/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetCommitCallback.java index 1f0f1f3076478..6beffac5d8715 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetCommitCallback.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetCommitCallback.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.time.Duration; import java.util.Collection; @@ -27,6 +29,7 @@ * may be executed in any thread calling {@link Consumer#poll(java.time.Duration) poll()}. */ @FunctionalInterface +@InterfaceAudience.Public public interface OffsetCommitCallback { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetOutOfRangeException.java b/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetOutOfRangeException.java index c2d4a2d020d1b..87886581ce8dd 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetOutOfRangeException.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/OffsetOutOfRangeException.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; import java.util.Set; @@ -25,6 +27,7 @@ * No reset policy has been defined, and the offsets for these partitions are either larger or smaller * than the range of offsets the server has for the given partition. */ +@InterfaceAudience.Public public class OffsetOutOfRangeException extends InvalidOffsetException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/RangeAssignor.java b/clients/src/main/java/org/apache/kafka/clients/consumer/RangeAssignor.java index f5be90b712ee3..d2689bdd97b19 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/RangeAssignor.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/RangeAssignor.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.clients.consumer.internals.AbstractPartitionAssignor; @@ -21,6 +22,8 @@ import org.apache.kafka.common.Node; import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import java.util.ArrayList; import java.util.Arrays; @@ -94,6 +97,8 @@ * rebalancing when replicas are added or removed to improve consumer rack alignment. *

    */ +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: extends internal AbstractPartitionAssignor — pending KIP review to promote the parent or refactor the assignor hierarchy") public class RangeAssignor extends AbstractPartitionAssignor { public static final String RANGE_ASSIGNOR_NAME = "range"; private static final TopicPartitionComparator PARTITION_COMPARATOR = new TopicPartitionComparator(); diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/RebalanceConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/RebalanceConsumer.java index 67519b1df1c2e..8e55654f34bd1 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/RebalanceConsumer.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/RebalanceConsumer.java @@ -14,12 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.clients.consumer; +package org.apache.kafka.clients.consumer; import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.time.Duration; import java.util.Collection; @@ -79,6 +80,7 @@ * * @see ConsumerRebalanceListener */ +@InterfaceAudience.Public public interface RebalanceConsumer { // --- Offset management --- diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/RebalanceListener.java b/clients/src/main/java/org/apache/kafka/clients/consumer/RebalanceListener.java index d834b766a7eca..123fa3ab27e6d 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/RebalanceListener.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/RebalanceListener.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.time.Duration; import java.util.Collection; @@ -139,6 +141,7 @@ * @see RebalanceConsumer * @see ConsumerRebalanceListener */ +@InterfaceAudience.Public public interface RebalanceListener { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/RetriableCommitFailedException.java b/clients/src/main/java/org/apache/kafka/clients/consumer/RetriableCommitFailedException.java index 7729ca8abb8b4..9ffe8ac68714c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/RetriableCommitFailedException.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/RetriableCommitFailedException.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.consumer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.RetriableException; /** @@ -27,6 +28,7 @@ * can be retried. The consumer should attempt to commit the offsets again. *

    */ +@InterfaceAudience.Public public class RetriableCommitFailedException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/RoundRobinAssignor.java b/clients/src/main/java/org/apache/kafka/clients/consumer/RoundRobinAssignor.java index 7dc3a293c6cee..099d04619f0f2 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/RoundRobinAssignor.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/RoundRobinAssignor.java @@ -18,6 +18,8 @@ import org.apache.kafka.clients.consumer.internals.AbstractPartitionAssignor; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.utils.Utils; import org.apache.kafka.common.utils.internals.CircularIterator; @@ -97,6 +99,8 @@ *
  • I2: [t0p2, t1p2] * */ +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: extends internal AbstractPartitionAssignor — pending KIP review to promote the parent or refactor the assignor hierarchy") public class RoundRobinAssignor extends AbstractPartitionAssignor { public static final String ROUNDROBIN_ASSIGNOR_NAME = "roundrobin"; diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/ShareConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/ShareConsumer.java index f7725230fbb80..d64afb5ffb4d1 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/ShareConsumer.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/ShareConsumer.java @@ -21,6 +21,7 @@ import org.apache.kafka.common.MetricName; import org.apache.kafka.common.TopicIdPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.KafkaMetric; import java.io.Closeable; @@ -36,6 +37,7 @@ * @see KafkaShareConsumer * @see MockShareConsumer */ +@InterfaceAudience.Public public interface ShareConsumer extends Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/StickyAssignor.java b/clients/src/main/java/org/apache/kafka/clients/consumer/StickyAssignor.java index 4e3cc855fed62..91bb3dc822eaa 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/StickyAssignor.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/StickyAssignor.java @@ -18,6 +18,8 @@ import org.apache.kafka.clients.consumer.internals.AbstractStickyAssignor; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.protocol.types.ArrayOf; import org.apache.kafka.common.protocol.types.Field; import org.apache.kafka.common.protocol.types.Schema; @@ -174,6 +176,8 @@ * reassigned to another consumer will be revoked. That is the preferred assignor for newer cluster. See * {@link ConsumerPartitionAssignor.RebalanceProtocol} for a detailed explanation of cooperative rebalancing. */ +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: extends internal AbstractStickyAssignor — pending KIP review to promote the parent or refactor the assignor hierarchy") public class StickyAssignor extends AbstractStickyAssignor { public static final String STICKY_ASSIGNOR_NAME = "sticky"; @@ -216,6 +220,9 @@ public ByteBuffer subscriptionUserData(Set topics) { } @Override + @SuppressKafkaInternalApiUsage("KIP-1265: forced override of AbstractStickyAssignor#memberData (internal) — " + + "the abstract parent declares the MemberData return type. Pending refactor to either promote MemberData " + + "or replace the hook with a public-typed equivalent.") protected MemberData memberData(Subscription subscription) { // Always deserialize ownedPartitions and generation id from user data // since StickyAssignor is an eager rebalance protocol that will revoke all existing partitions before joining group diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/SubscriptionPattern.java b/clients/src/main/java/org/apache/kafka/clients/consumer/SubscriptionPattern.java index fbada9600265d..739517d29d1eb 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/SubscriptionPattern.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/SubscriptionPattern.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.consumer; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** @@ -23,6 +26,7 @@ * This just keeps the String representation of the pattern, and all validations to ensure * it is RE2/J compatible are delegated to the broker. */ +@InterfaceAudience.Public public class SubscriptionPattern { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/BufferExhaustedException.java b/clients/src/main/java/org/apache/kafka/clients/producer/BufferExhaustedException.java index 06b0ce1767c23..4ea666d99c0e2 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/BufferExhaustedException.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/BufferExhaustedException.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.producer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.TimeoutException; /** @@ -26,6 +27,7 @@ * this class extends TimeoutException. * */ +@InterfaceAudience.Public public class BufferExhaustedException extends TimeoutException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/Callback.java b/clients/src/main/java/org/apache/kafka/clients/producer/Callback.java index 5c8f159ac8221..a06ab6d5ca49c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/Callback.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/Callback.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.producer; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A callback interface that the user can implement to allow code to execute when the request is complete. This callback * will generally execute in the background I/O thread so it should be fast. */ @FunctionalInterface +@InterfaceAudience.Public public interface Callback { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java b/clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java index dfa72f2adad71..f49d2cda46b61 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.producer; import org.apache.kafka.clients.ApiVersions; @@ -43,6 +44,7 @@ import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.compress.Compression; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.errors.ApiException; @@ -102,7 +104,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; - /** * A Kafka client that publishes records to the Kafka cluster. *

    @@ -244,6 +245,7 @@ * UnsupportedVersionException when invoking an API that is not available in the running broker version. *

    */ +@InterfaceAudience.Public public class KafkaProducer implements Producer { private final Logger log; diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java b/clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java index eb89f88f7d913..930cdc5d6b487 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java @@ -27,6 +27,7 @@ import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ProducerFencedException; import org.apache.kafka.common.errors.TimeoutException; import org.apache.kafka.common.header.internals.RecordHeaders; @@ -52,6 +53,7 @@ * By default this mock will synchronously complete each send call successfully. However it can be configured to allow * the user to control the completion of the call and supply an optional error for the producer to throw. */ +@InterfaceAudience.Public public class MockProducer implements Producer { private final Cluster cluster; diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/Partitioner.java b/clients/src/main/java/org/apache/kafka/clients/producer/Partitioner.java index d1d1ad3ac55f1..aa27c7cd5e60a 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/Partitioner.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/Partitioner.java @@ -14,10 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.clients.producer; import org.apache.kafka.common.Cluster; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.io.Closeable; @@ -27,6 +29,7 @@ * Implement {@link org.apache.kafka.common.metrics.Monitorable} to enable the partitioner to register metrics. The following tags are automatically added to * all metrics registered: config set to partitioner.class, and class set to the Partitioner class name. */ +@InterfaceAudience.Public public interface Partitioner extends Configurable, Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/PreparedTxnState.java b/clients/src/main/java/org/apache/kafka/clients/producer/PreparedTxnState.java index 4e9ccf92ff71d..d1cf0b19cab18 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/PreparedTxnState.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/PreparedTxnState.java @@ -16,12 +16,14 @@ */ package org.apache.kafka.clients.producer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.record.internal.RecordBatch; /** * Class containing the state of a transaction after it has been prepared for a two-phase commit. * This state includes the producer ID and epoch, which are needed to commit or abort the transaction. */ +@InterfaceAudience.Public public class PreparedTxnState { private final long producerId; private final short epoch; diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/Producer.java b/clients/src/main/java/org/apache/kafka/clients/producer/Producer.java index e4e02865189ca..89b29157377e4 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/Producer.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/Producer.java @@ -23,6 +23,7 @@ import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ProducerFencedException; import org.apache.kafka.common.metrics.KafkaMetric; @@ -37,6 +38,7 @@ * @see KafkaProducer * @see MockProducer */ +@InterfaceAudience.Public public interface Producer extends Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/ProducerConfig.java b/clients/src/main/java/org/apache/kafka/clients/producer/ProducerConfig.java index 38a007b6d212b..d3673caabf63a 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/ProducerConfig.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/ProducerConfig.java @@ -19,6 +19,7 @@ import org.apache.kafka.clients.ClientDnsLookup; import org.apache.kafka.clients.CommonClientConfigs; import org.apache.kafka.clients.MetadataRecoveryStrategy; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.AbstractConfig; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; @@ -51,6 +52,7 @@ * Configuration for the Kafka Producer. Documentation for these configurations can be found in the Kafka documentation */ +@InterfaceAudience.Public public class ProducerConfig extends AbstractConfig { private static final Logger log = LoggerFactory.getLogger(ProducerConfig.class); diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/ProducerInterceptor.java b/clients/src/main/java/org/apache/kafka/clients/producer/ProducerInterceptor.java index 4a813dc96babc..1313965c8785c 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/ProducerInterceptor.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/ProducerInterceptor.java @@ -17,6 +17,7 @@ package org.apache.kafka.clients.producer; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; /** @@ -37,6 +38,7 @@ * Implement {@link org.apache.kafka.common.metrics.Monitorable} to enable the interceptor to register metrics. The following tags are automatically added to * all metrics registered: config set to interceptor.classes, and class set to the ProducerInterceptor class name. */ +@InterfaceAudience.Public public interface ProducerInterceptor extends Configurable, AutoCloseable { /** * This is called from {@link org.apache.kafka.clients.producer.KafkaProducer#send(ProducerRecord)} and diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/ProducerRecord.java b/clients/src/main/java/org/apache/kafka/clients/producer/ProducerRecord.java index 3e43f27ea2b87..b6f196a1c8696 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/ProducerRecord.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/ProducerRecord.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.clients.producer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Header; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; @@ -46,6 +47,7 @@ * In either of the cases above, the timestamp that has actually been used will be returned to user in * {@link RecordMetadata} */ +@InterfaceAudience.Public public class ProducerRecord { private final String topic; diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/RecordMetadata.java b/clients/src/main/java/org/apache/kafka/clients/producer/RecordMetadata.java index f410e25f65c6e..c35668c2ca8a3 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/RecordMetadata.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/RecordMetadata.java @@ -17,12 +17,14 @@ package org.apache.kafka.clients.producer; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.record.internal.RecordBatch; import org.apache.kafka.common.requests.ProduceResponse; /** * The metadata for a record that has been acknowledged by the server */ +@InterfaceAudience.Public public final class RecordMetadata { /** diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/RoundRobinPartitioner.java b/clients/src/main/java/org/apache/kafka/clients/producer/RoundRobinPartitioner.java index c736756ab4231..a58c34c713147 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/RoundRobinPartitioner.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/RoundRobinPartitioner.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.Cluster; import org.apache.kafka.common.PartitionInfo; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Utils; import java.util.List; @@ -34,6 +35,7 @@ * is the behaviour regardless of record key hash. * */ +@InterfaceAudience.Public public class RoundRobinPartitioner implements Partitioner { private final ConcurrentMap topicCounterMap = new ConcurrentHashMap<>(); diff --git a/clients/src/main/java/org/apache/kafka/common/ClassicGroupState.java b/clients/src/main/java/org/apache/kafka/common/ClassicGroupState.java index 65aaa1a6d3bed..4851159c22f79 100644 --- a/clients/src/main/java/org/apache/kafka/common/ClassicGroupState.java +++ b/clients/src/main/java/org/apache/kafka/common/ClassicGroupState.java @@ -17,6 +17,8 @@ package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Locale; import java.util.Map; @@ -26,6 +28,7 @@ /** * The classic group state. */ +@InterfaceAudience.Public public enum ClassicGroupState { UNKNOWN("Unknown"), PREPARING_REBALANCE("PreparingRebalance"), diff --git a/clients/src/main/java/org/apache/kafka/common/Cluster.java b/clients/src/main/java/org/apache/kafka/common/Cluster.java index b8466dd019394..afe8cdb81ca8a 100644 --- a/clients/src/main/java/org/apache/kafka/common/Cluster.java +++ b/clients/src/main/java/org/apache/kafka/common/Cluster.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Arrays; @@ -32,6 +35,7 @@ /** * An immutable representation of a subset of the nodes, topics, and partitions in the Kafka cluster. */ +@InterfaceAudience.Public public final class Cluster { private final boolean isBootstrapConfigured; diff --git a/clients/src/main/java/org/apache/kafka/common/ClusterResource.java b/clients/src/main/java/org/apache/kafka/common/ClusterResource.java index aad5c3d6d85be..c414d4ab07efc 100644 --- a/clients/src/main/java/org/apache/kafka/common/ClusterResource.java +++ b/clients/src/main/java/org/apache/kafka/common/ClusterResource.java @@ -14,14 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Objects; /** * The ClusterResource class encapsulates metadata for a Kafka cluster. */ +@InterfaceAudience.Public public class ClusterResource { private final String clusterId; diff --git a/clients/src/main/java/org/apache/kafka/common/ClusterResourceListener.java b/clients/src/main/java/org/apache/kafka/common/ClusterResourceListener.java index 63f3f6a13e309..fed91d2724c64 100644 --- a/clients/src/main/java/org/apache/kafka/common/ClusterResourceListener.java +++ b/clients/src/main/java/org/apache/kafka/common/ClusterResourceListener.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A callback interface that users can implement when they wish to get notified about changes in the Cluster metadata. *

    @@ -44,6 +47,7 @@ *

    * {@link org.apache.kafka.common.metrics.MetricsReporter} : The {@link ClusterResourceListener#onUpdate(ClusterResource)} method will be invoked during the bootup of the Kafka broker. The reporter may receive metric events from the network layer before this method is invoked. */ +@InterfaceAudience.Public public interface ClusterResourceListener { /** * A callback method that a user can implement to get updates for {@link ClusterResource}. diff --git a/clients/src/main/java/org/apache/kafka/common/Configurable.java b/clients/src/main/java/org/apache/kafka/common/Configurable.java index ecca298ef793e..e4e76ecd383b8 100644 --- a/clients/src/main/java/org/apache/kafka/common/Configurable.java +++ b/clients/src/main/java/org/apache/kafka/common/Configurable.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** * A Mix-in style interface for classes that are instantiated by reflection and need to take configuration parameters */ +@InterfaceAudience.Public public interface Configurable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/ElectionType.java b/clients/src/main/java/org/apache/kafka/common/ElectionType.java index 8de7af65e7baf..2370b5c6c4fe9 100644 --- a/clients/src/main/java/org/apache/kafka/common/ElectionType.java +++ b/clients/src/main/java/org/apache/kafka/common/ElectionType.java @@ -17,12 +17,15 @@ package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Set; /** * Options for {@link org.apache.kafka.clients.admin.Admin#electLeaders(ElectionType, Set, org.apache.kafka.clients.admin.ElectLeadersOptions)}. */ +@InterfaceAudience.Public public enum ElectionType { PREFERRED((byte) 0), UNCLEAN((byte) 1); diff --git a/clients/src/main/java/org/apache/kafka/common/Endpoint.java b/clients/src/main/java/org/apache/kafka/common/Endpoint.java index baa1045929f8e..3b0d134d3b05d 100644 --- a/clients/src/main/java/org/apache/kafka/common/Endpoint.java +++ b/clients/src/main/java/org/apache/kafka/common/Endpoint.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.auth.SecurityProtocol; import java.util.Objects; @@ -25,6 +26,7 @@ * Represents a broker endpoint. */ +@InterfaceAudience.Public public class Endpoint { private final String listener; diff --git a/clients/src/main/java/org/apache/kafka/common/GroupState.java b/clients/src/main/java/org/apache/kafka/common/GroupState.java index 34e97a15a6bae..a83c59a5d8117 100644 --- a/clients/src/main/java/org/apache/kafka/common/GroupState.java +++ b/clients/src/main/java/org/apache/kafka/common/GroupState.java @@ -17,6 +17,8 @@ package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Locale; import java.util.Map; @@ -45,6 +47,7 @@ * * */ +@InterfaceAudience.Public public enum GroupState { UNKNOWN("Unknown"), PREPARING_REBALANCE("PreparingRebalance"), diff --git a/clients/src/main/java/org/apache/kafka/common/GroupType.java b/clients/src/main/java/org/apache/kafka/common/GroupType.java index 4c3aeac93fbd6..929aa117e79c6 100644 --- a/clients/src/main/java/org/apache/kafka/common/GroupType.java +++ b/clients/src/main/java/org/apache/kafka/common/GroupType.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Locale; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; +@InterfaceAudience.Public public enum GroupType { UNKNOWN("Unknown"), CONSUMER("Consumer"), diff --git a/clients/src/main/java/org/apache/kafka/common/InvalidRecordException.java b/clients/src/main/java/org/apache/kafka/common/InvalidRecordException.java index aa13ffd9936b0..4e3c59fc53a3b 100644 --- a/clients/src/main/java/org/apache/kafka/common/InvalidRecordException.java +++ b/clients/src/main/java/org/apache/kafka/common/InvalidRecordException.java @@ -16,8 +16,10 @@ */ package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.InvalidConfigurationException; +@InterfaceAudience.Public public class InvalidRecordException extends InvalidConfigurationException { private static final long serialVersionUID = 1; diff --git a/clients/src/main/java/org/apache/kafka/common/IsolationLevel.java b/clients/src/main/java/org/apache/kafka/common/IsolationLevel.java index fd4f45f39642c..a463ce0b618fc 100644 --- a/clients/src/main/java/org/apache/kafka/common/IsolationLevel.java +++ b/clients/src/main/java/org/apache/kafka/common/IsolationLevel.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Locale; +@InterfaceAudience.Public public enum IsolationLevel { READ_UNCOMMITTED((byte) 0), READ_COMMITTED((byte) 1); diff --git a/clients/src/main/java/org/apache/kafka/common/KafkaException.java b/clients/src/main/java/org/apache/kafka/common/KafkaException.java index b77c96e4826ad..95ce0d636e3b3 100644 --- a/clients/src/main/java/org/apache/kafka/common/KafkaException.java +++ b/clients/src/main/java/org/apache/kafka/common/KafkaException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The base class of all other Kafka exceptions */ +@InterfaceAudience.Public public class KafkaException extends RuntimeException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/KafkaFuture.java b/clients/src/main/java/org/apache/kafka/common/KafkaFuture.java index 257c98e293059..5b75966b59170 100644 --- a/clients/src/main/java/org/apache/kafka/common/KafkaFuture.java +++ b/clients/src/main/java/org/apache/kafka/common/KafkaFuture.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.internals.KafkaFutureImpl; import java.util.Arrays; @@ -38,6 +39,7 @@ * {@code KafkaFuture} will fail with an {@code ExecutionException}, whereas a {@code CompletionStage} fails * with a {@code CompletionException}. */ +@InterfaceAudience.Public public abstract class KafkaFuture implements Future { /** * A function which takes objects of type A and returns objects of type B. diff --git a/clients/src/main/java/org/apache/kafka/common/MessageFormatter.java b/clients/src/main/java/org/apache/kafka/common/MessageFormatter.java index 4b04255ba384c..ee9adbe9b322b 100644 --- a/clients/src/main/java/org/apache/kafka/common/MessageFormatter.java +++ b/clients/src/main/java/org/apache/kafka/common/MessageFormatter.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.io.Closeable; import java.io.PrintStream; @@ -31,6 +33,7 @@ * __transaction_state and the MirrorMaker2 topics. * */ +@InterfaceAudience.Public public interface MessageFormatter extends Configurable, Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/Metric.java b/clients/src/main/java/org/apache/kafka/common/Metric.java index 01f8137f84199..2ed2a821c3916 100644 --- a/clients/src/main/java/org/apache/kafka/common/Metric.java +++ b/clients/src/main/java/org/apache/kafka/common/Metric.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A metric tracked for monitoring purposes. */ +@InterfaceAudience.Public public interface Metric { /** diff --git a/clients/src/main/java/org/apache/kafka/common/MetricName.java b/clients/src/main/java/org/apache/kafka/common/MetricName.java index 1f5b43104b1b6..8b9a50f55df34 100644 --- a/clients/src/main/java/org/apache/kafka/common/MetricName.java +++ b/clients/src/main/java/org/apache/kafka/common/MetricName.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; import java.util.Objects; @@ -60,6 +63,7 @@ * sensor.record(messageSize); * } */ +@InterfaceAudience.Public public final class MetricName { private final String name; diff --git a/clients/src/main/java/org/apache/kafka/common/MetricNameTemplate.java b/clients/src/main/java/org/apache/kafka/common/MetricNameTemplate.java index 239d0ce24c2cb..00fc2ba6f7c7f 100644 --- a/clients/src/main/java/org/apache/kafka/common/MetricNameTemplate.java +++ b/clients/src/main/java/org/apache/kafka/common/MetricNameTemplate.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collections; import java.util.LinkedHashSet; import java.util.Objects; @@ -28,6 +31,7 @@ * specified values. The order of the tags is maintained, if an ordered set * is provided, so that the mBean names can be compared and sorted lexicographically. */ +@InterfaceAudience.Public public class MetricNameTemplate { private final String name; private final String group; diff --git a/clients/src/main/java/org/apache/kafka/common/Node.java b/clients/src/main/java/org/apache/kafka/common/Node.java index 9467f8b2456af..5ff1234e26a4a 100644 --- a/clients/src/main/java/org/apache/kafka/common/Node.java +++ b/clients/src/main/java/org/apache/kafka/common/Node.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Information about a Kafka node */ +@InterfaceAudience.Public public class Node { private static final Node NO_NODE = new Node(-1, "", -1); diff --git a/clients/src/main/java/org/apache/kafka/common/PartitionInfo.java b/clients/src/main/java/org/apache/kafka/common/PartitionInfo.java index ba831d2fb710d..56343b01474d4 100644 --- a/clients/src/main/java/org/apache/kafka/common/PartitionInfo.java +++ b/clients/src/main/java/org/apache/kafka/common/PartitionInfo.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Objects; /** * This is used to describe per-partition state in the MetadataResponse. */ +@InterfaceAudience.Public public class PartitionInfo { private final String topic; private final int partition; diff --git a/clients/src/main/java/org/apache/kafka/common/Reconfigurable.java b/clients/src/main/java/org/apache/kafka/common/Reconfigurable.java index 8db9dc27ff35b..8d3e12b4664e4 100644 --- a/clients/src/main/java/org/apache/kafka/common/Reconfigurable.java +++ b/clients/src/main/java/org/apache/kafka/common/Reconfigurable.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import java.util.Map; @@ -24,6 +25,7 @@ /** * Interface for reconfigurable classes that support dynamic configuration. */ +@InterfaceAudience.Public public interface Reconfigurable extends Configurable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/TopicCollection.java b/clients/src/main/java/org/apache/kafka/common/TopicCollection.java index 5661e6cf36921..a20f45ebfe550 100644 --- a/clients/src/main/java/org/apache/kafka/common/TopicCollection.java +++ b/clients/src/main/java/org/apache/kafka/common/TopicCollection.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -23,6 +26,7 @@ /** * A class used to represent a collection of topics. This collection may define topics by name or ID. */ +@InterfaceAudience.Public public abstract class TopicCollection { private TopicCollection() {} diff --git a/clients/src/main/java/org/apache/kafka/common/TopicIdPartition.java b/clients/src/main/java/org/apache/kafka/common/TopicIdPartition.java index 09d861e69efbe..53937ec0197fe 100644 --- a/clients/src/main/java/org/apache/kafka/common/TopicIdPartition.java +++ b/clients/src/main/java/org/apache/kafka/common/TopicIdPartition.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * This represents universally unique identifier with topic id for a topic partition. This makes sure that topics * recreated with the same name will always have unique topic identifiers. */ +@InterfaceAudience.Public public class TopicIdPartition { private final Uuid topicId; diff --git a/clients/src/main/java/org/apache/kafka/common/TopicPartition.java b/clients/src/main/java/org/apache/kafka/common/TopicPartition.java index 7c8fe79e91193..6a29be3ff44a3 100644 --- a/clients/src/main/java/org/apache/kafka/common/TopicPartition.java +++ b/clients/src/main/java/org/apache/kafka/common/TopicPartition.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.io.Serializable; import java.util.Objects; /** * A topic name and partition number */ +@InterfaceAudience.Public public final class TopicPartition implements Serializable { private static final long serialVersionUID = -613627415771699627L; diff --git a/clients/src/main/java/org/apache/kafka/common/TopicPartitionInfo.java b/clients/src/main/java/org/apache/kafka/common/TopicPartitionInfo.java index 88fb5260d8cbf..4c6c6f070026d 100644 --- a/clients/src/main/java/org/apache/kafka/common/TopicPartitionInfo.java +++ b/clients/src/main/java/org/apache/kafka/common/TopicPartitionInfo.java @@ -17,6 +17,8 @@ package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collections; import java.util.List; import java.util.Objects; @@ -25,6 +27,7 @@ /** * A class containing leadership, replicas and ISR information for a topic partition. */ +@InterfaceAudience.Public public class TopicPartitionInfo { private final int partition; private final Node leader; diff --git a/clients/src/main/java/org/apache/kafka/common/TopicPartitionReplica.java b/clients/src/main/java/org/apache/kafka/common/TopicPartitionReplica.java index 0a7c419c933bd..2ddde97f69e64 100644 --- a/clients/src/main/java/org/apache/kafka/common/TopicPartitionReplica.java +++ b/clients/src/main/java/org/apache/kafka/common/TopicPartitionReplica.java @@ -14,15 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.io.Serializable; import java.util.Objects; - /** * The topic name, partition number and the brokerId of the replica */ +@InterfaceAudience.Public public final class TopicPartitionReplica implements Serializable { private int hash = 0; diff --git a/clients/src/main/java/org/apache/kafka/common/Uuid.java b/clients/src/main/java/org/apache/kafka/common/Uuid.java index 31478f6fed30d..f3f23ebdb56f5 100644 --- a/clients/src/main/java/org/apache/kafka/common/Uuid.java +++ b/clients/src/main/java/org/apache/kafka/common/Uuid.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; @@ -29,6 +32,7 @@ * This is the same type of UUID as the ones generated by java.util.UUID. The toString() method prints * using the base64 string encoding. Likewise, the fromString method expects a base64 string encoding. */ +@InterfaceAudience.Public public class Uuid implements Comparable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/acl/AccessControlEntry.java b/clients/src/main/java/org/apache/kafka/common/acl/AccessControlEntry.java index 9f315e1849211..da5ec6aab352d 100644 --- a/clients/src/main/java/org/apache/kafka/common/acl/AccessControlEntry.java +++ b/clients/src/main/java/org/apache/kafka/common/acl/AccessControlEntry.java @@ -17,11 +17,14 @@ package org.apache.kafka.common.acl; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Represents an access control entry. ACEs are a tuple of principal, host, operation, and permissionType. */ +@InterfaceAudience.Public public class AccessControlEntry { final AccessControlEntryData data; diff --git a/clients/src/main/java/org/apache/kafka/common/acl/AccessControlEntryFilter.java b/clients/src/main/java/org/apache/kafka/common/acl/AccessControlEntryFilter.java index d220f94b192f9..078d515a61db7 100644 --- a/clients/src/main/java/org/apache/kafka/common/acl/AccessControlEntryFilter.java +++ b/clients/src/main/java/org/apache/kafka/common/acl/AccessControlEntryFilter.java @@ -17,11 +17,14 @@ package org.apache.kafka.common.acl; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Represents a filter which matches access control entries. */ +@InterfaceAudience.Public public class AccessControlEntryFilter { private final AccessControlEntryData data; diff --git a/clients/src/main/java/org/apache/kafka/common/acl/AclBinding.java b/clients/src/main/java/org/apache/kafka/common/acl/AclBinding.java index 750066db91c74..9699b4bb8d1be 100644 --- a/clients/src/main/java/org/apache/kafka/common/acl/AclBinding.java +++ b/clients/src/main/java/org/apache/kafka/common/acl/AclBinding.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.acl; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.resource.ResourcePattern; import java.util.Objects; @@ -24,6 +25,7 @@ /** * Represents a binding between a resource pattern and an access control entry. */ +@InterfaceAudience.Public public class AclBinding { private final ResourcePattern pattern; private final AccessControlEntry entry; diff --git a/clients/src/main/java/org/apache/kafka/common/acl/AclBindingFilter.java b/clients/src/main/java/org/apache/kafka/common/acl/AclBindingFilter.java index b4fcddc55361b..b3e808c03e3b8 100644 --- a/clients/src/main/java/org/apache/kafka/common/acl/AclBindingFilter.java +++ b/clients/src/main/java/org/apache/kafka/common/acl/AclBindingFilter.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.acl; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.resource.ResourcePatternFilter; import java.util.Objects; @@ -24,6 +25,7 @@ /** * A filter which can match AclBinding objects. */ +@InterfaceAudience.Public public class AclBindingFilter { private final ResourcePatternFilter patternFilter; private final AccessControlEntryFilter entryFilter; diff --git a/clients/src/main/java/org/apache/kafka/common/acl/AclOperation.java b/clients/src/main/java/org/apache/kafka/common/acl/AclOperation.java index 485c3602d2623..17ef6da010734 100644 --- a/clients/src/main/java/org/apache/kafka/common/acl/AclOperation.java +++ b/clients/src/main/java/org/apache/kafka/common/acl/AclOperation.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.acl; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.HashMap; import java.util.Locale; @@ -37,6 +39,7 @@ *

  • ALLOW ALTER_CONFIGS implies ALLOW DESCRIBE_CONFIGS * */ +@InterfaceAudience.Public public enum AclOperation { /** * Represents any AclOperation which this client cannot understand, perhaps because this diff --git a/clients/src/main/java/org/apache/kafka/common/acl/AclPermissionType.java b/clients/src/main/java/org/apache/kafka/common/acl/AclPermissionType.java index 42a6303f97e69..aec965a443b6f 100644 --- a/clients/src/main/java/org/apache/kafka/common/acl/AclPermissionType.java +++ b/clients/src/main/java/org/apache/kafka/common/acl/AclPermissionType.java @@ -17,12 +17,15 @@ package org.apache.kafka.common.acl; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.HashMap; import java.util.Locale; /** * Represents whether an ACL grants or denies permissions. */ +@InterfaceAudience.Public public enum AclPermissionType { /** * Represents any AclPermissionType which this client cannot understand, diff --git a/clients/src/main/java/org/apache/kafka/common/annotation/InterfaceAudience.java b/clients/src/main/java/org/apache/kafka/common/annotation/InterfaceAudience.java new file mode 100644 index 0000000000000..ad0e6fe4c13e0 --- /dev/null +++ b/clients/src/main/java/org/apache/kafka/common/annotation/InterfaceAudience.java @@ -0,0 +1,56 @@ +/* + * 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.kafka.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to inform users of the intended audience of a particular package, class or method. + * Currently the audience can be {@link Public} or {@link Private}. Audience is orthogonal to + * {@link InterfaceStability}: a class may be public-audience and evolving-stability at the same + * time. + * + *

    If no audience annotation is present on a class, it is assumed to be {@link Private} + * (internal). External code must not depend on classes without an explicit {@link Public} + * annotation. + */ +@InterfaceAudience.Public +public class InterfaceAudience { + /** + * Intended for end users of Apache Kafka. Classes and members marked {@code @Public} are + * part of the Kafka public API surface; external code may depend on them subject to the + * stability guarantees declared via {@link InterfaceStability}. + */ + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface Public { } + + /** + * Intended for internal use within Apache Kafka. Classes and members marked {@code @Private} + * carry no compatibility guarantees and may change or be removed at any time without notice. + * This is also the assumed audience when no annotation is present. + */ + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface Private { } +} \ No newline at end of file diff --git a/clients/src/main/java/org/apache/kafka/common/annotation/InterfaceStability.java b/clients/src/main/java/org/apache/kafka/common/annotation/InterfaceStability.java index 9624ae8b575aa..7d8b9a03a835b 100644 --- a/clients/src/main/java/org/apache/kafka/common/annotation/InterfaceStability.java +++ b/clients/src/main/java/org/apache/kafka/common/annotation/InterfaceStability.java @@ -24,6 +24,7 @@ * Annotation to inform users of how much to rely on a particular package, class or method not changing over time. * Currently the stability can be {@link Stable}, {@link Evolving} or {@link Unstable}. */ +@InterfaceAudience.Public public class InterfaceStability { /** * Compatibility is maintained in major, minor and patch releases with one exception: compatibility may be broken diff --git a/clients/src/main/java/org/apache/kafka/common/annotation/SuppressKafkaInternalApiUsage.java b/clients/src/main/java/org/apache/kafka/common/annotation/SuppressKafkaInternalApiUsage.java new file mode 100644 index 0000000000000..bcc7d40e3d76d --- /dev/null +++ b/clients/src/main/java/org/apache/kafka/common/annotation/SuppressKafkaInternalApiUsage.java @@ -0,0 +1,46 @@ +/* + * 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.kafka.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks a class, method, field, or constructor as intentionally permitted to reference Kafka + * classes that are not part of the {@link InterfaceAudience.Public} surface. The + * {@code KafkaInternalApiChecker} build plugin honours this annotation: a reference to an + * internal Kafka class from an element (or its enclosing class) carrying this annotation is + * skipped, and the supplied {@code value()} is printed by the checker so reviewers can see why + * the exception was granted. + * + *

    Use sparingly — every suppression is a place where the consumer accepts the risk of + * Kafka-internal change. + */ +@Documented +@InterfaceAudience.Public +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR}) +public @interface SuppressKafkaInternalApiUsage { + /** + * Human-readable justification for the suppression. Printed by the checker when the + * suppression is honoured. + */ + String value() default ""; +} diff --git a/clients/src/main/java/org/apache/kafka/common/config/AbstractConfig.java b/clients/src/main/java/org/apache/kafka/common/config/AbstractConfig.java index 39d015ec82cd0..c3efd060a8a40 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/AbstractConfig.java +++ b/clients/src/main/java/org/apache/kafka/common/config/AbstractConfig.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.Configurable; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.provider.ConfigProvider; import org.apache.kafka.common.config.types.Password; import org.apache.kafka.common.utils.Utils; @@ -43,6 +44,7 @@ *

    * This class holds both the original configuration that was provided as well as the parsed */ +@InterfaceAudience.Public public class AbstractConfig { private static final Logger log = LoggerFactory.getLogger(AbstractConfig.class); diff --git a/clients/src/main/java/org/apache/kafka/common/config/Config.java b/clients/src/main/java/org/apache/kafka/common/config/Config.java index f7fa95c1de129..7b2fbdcf14094 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/Config.java +++ b/clients/src/main/java/org/apache/kafka/common/config/Config.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; +@InterfaceAudience.Public public class Config { private final List configValues; diff --git a/clients/src/main/java/org/apache/kafka/common/config/ConfigChangeCallback.java b/clients/src/main/java/org/apache/kafka/common/config/ConfigChangeCallback.java index faa7d3d87074a..293a4e77d0f3b 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/ConfigChangeCallback.java +++ b/clients/src/main/java/org/apache/kafka/common/config/ConfigChangeCallback.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.provider.ConfigProvider; /** * A callback passed to {@link ConfigProvider} for subscribing to changes. */ +@InterfaceAudience.Public public interface ConfigChangeCallback { /** diff --git a/clients/src/main/java/org/apache/kafka/common/config/ConfigData.java b/clients/src/main/java/org/apache/kafka/common/config/ConfigData.java index 8661ee16cbab1..d01d8b5b1e230 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/ConfigData.java +++ b/clients/src/main/java/org/apache/kafka/common/config/ConfigData.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.provider.ConfigProvider; import java.util.Map; @@ -23,6 +24,7 @@ /** * Configuration data from a {@link ConfigProvider}. */ +@InterfaceAudience.Public public class ConfigData { private final Map data; diff --git a/clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java b/clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java index efe7f0a1ecc1b..5efcfec246916 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java +++ b/clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.types.Password; import org.apache.kafka.common.utils.Utils; @@ -81,6 +82,7 @@ * This class can be used standalone or in combination with {@link AbstractConfig} which provides some additional * functionality for accessing configs. */ +@InterfaceAudience.Public public class ConfigDef { private static final Pattern COMMA_WITH_WHITESPACE = Pattern.compile("\\s*,\\s*"); diff --git a/clients/src/main/java/org/apache/kafka/common/config/ConfigException.java b/clients/src/main/java/org/apache/kafka/common/config/ConfigException.java index c48bfc6c07e51..657e7c780a65d 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/ConfigException.java +++ b/clients/src/main/java/org/apache/kafka/common/config/ConfigException.java @@ -14,13 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.config; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Thrown if the user supplies an invalid configuration */ +@InterfaceAudience.Public public class ConfigException extends KafkaException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/config/ConfigResource.java b/clients/src/main/java/org/apache/kafka/common/config/ConfigResource.java index 4c082aff6704d..3c112bccb6c68 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/ConfigResource.java +++ b/clients/src/main/java/org/apache/kafka/common/config/ConfigResource.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -27,6 +29,7 @@ /** * A class representing resources that have configs. */ +@InterfaceAudience.Public public final class ConfigResource { /** diff --git a/clients/src/main/java/org/apache/kafka/common/config/ConfigTransformer.java b/clients/src/main/java/org/apache/kafka/common/config/ConfigTransformer.java index dbf6c7bbfcec1..b96a489e2a382 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/ConfigTransformer.java +++ b/clients/src/main/java/org/apache/kafka/common/config/ConfigTransformer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.provider.ConfigProvider; import org.apache.kafka.common.config.provider.FileConfigProvider; @@ -52,6 +53,7 @@ * in a {@link ConfigProvider}, such as the {@link ConfigProvider#subscribe(String, Set, ConfigChangeCallback)} and * {@link ConfigProvider#unsubscribe(String, Set, ConfigChangeCallback)} methods. */ +@InterfaceAudience.Public public class ConfigTransformer { public static final Pattern DEFAULT_PATTERN = Pattern.compile("\\$\\{([^}]*?):(([^}]*?):)?([^}]*?)\\}"); private static final String EMPTY_PATH = ""; diff --git a/clients/src/main/java/org/apache/kafka/common/config/ConfigTransformerResult.java b/clients/src/main/java/org/apache/kafka/common/config/ConfigTransformerResult.java index 4539c97d6ba65..e9ef9bbfebc59 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/ConfigTransformerResult.java +++ b/clients/src/main/java/org/apache/kafka/common/config/ConfigTransformerResult.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.provider.ConfigProvider; import java.util.Map; @@ -23,6 +24,7 @@ /** * The result of a transformation from {@link ConfigTransformer}. */ +@InterfaceAudience.Public public class ConfigTransformerResult { private final Map ttls; diff --git a/clients/src/main/java/org/apache/kafka/common/config/ConfigValue.java b/clients/src/main/java/org/apache/kafka/common/config/ConfigValue.java index 2ae4b64d47596..5d86f7c501bfb 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/ConfigValue.java +++ b/clients/src/main/java/org/apache/kafka/common/config/ConfigValue.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.ArrayList; import java.util.List; import java.util.Objects; +@InterfaceAudience.Public public class ConfigValue { private final String name; diff --git a/clients/src/main/java/org/apache/kafka/common/config/LogLevelConfig.java b/clients/src/main/java/org/apache/kafka/common/config/LogLevelConfig.java index 410082d908be6..2c237dce78daf 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/LogLevelConfig.java +++ b/clients/src/main/java/org/apache/kafka/common/config/LogLevelConfig.java @@ -17,11 +17,14 @@ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Set; /** * This class holds definitions for log level configurations related to Kafka's application logging. See KIP-412 for additional information */ +@InterfaceAudience.Public public class LogLevelConfig { /* * NOTE: DO NOT CHANGE EITHER CONFIG NAMES AS THESE ARE PART OF THE PUBLIC API AND CHANGE WILL BREAK USER CODE. diff --git a/clients/src/main/java/org/apache/kafka/common/config/SaslConfigs.java b/clients/src/main/java/org/apache/kafka/common/config/SaslConfigs.java index 02704a2300d0b..3e0a0f2202376 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/SaslConfigs.java +++ b/clients/src/main/java/org/apache/kafka/common/config/SaslConfigs.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef.CaseInsensitiveValidString; import org.apache.kafka.common.config.ConfigDef.Range; import java.util.List; +@InterfaceAudience.Public public class SaslConfigs { private static final String OAUTHBEARER_NOTE = " Currently applies only to OAUTHBEARER."; diff --git a/clients/src/main/java/org/apache/kafka/common/config/SecurityConfig.java b/clients/src/main/java/org/apache/kafka/common/config/SecurityConfig.java index b4dc26c7ea5cb..b3a01403d6327 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/SecurityConfig.java +++ b/clients/src/main/java/org/apache/kafka/common/config/SecurityConfig.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Contains the common security config for SSL and SASL */ +@InterfaceAudience.Public public class SecurityConfig { public static final String SECURITY_PROVIDERS_CONFIG = "security.providers"; diff --git a/clients/src/main/java/org/apache/kafka/common/config/SslClientAuth.java b/clients/src/main/java/org/apache/kafka/common/config/SslClientAuth.java index c9552b7c44da8..016eed5662340 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/SslClientAuth.java +++ b/clients/src/main/java/org/apache/kafka/common/config/SslClientAuth.java @@ -17,12 +17,15 @@ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; import java.util.Locale; /** * Describes whether the server should require or request client authentication. */ +@InterfaceAudience.Public public enum SslClientAuth { REQUIRED, REQUESTED, diff --git a/clients/src/main/java/org/apache/kafka/common/config/SslConfigs.java b/clients/src/main/java/org/apache/kafka/common/config/SslConfigs.java index 7675f75a9ab71..7397bedcfd309 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/SslConfigs.java +++ b/clients/src/main/java/org/apache/kafka/common/config/SslConfigs.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.internals.BrokerSecurityConfigs; import java.util.List; @@ -24,6 +25,7 @@ import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; +@InterfaceAudience.Public public class SslConfigs { /* * NOTE: DO NOT CHANGE EITHER CONFIG NAMES AS THESE ARE PART OF THE PUBLIC API AND CHANGE WILL BREAK USER CODE. diff --git a/clients/src/main/java/org/apache/kafka/common/config/TopicConfig.java b/clients/src/main/java/org/apache/kafka/common/config/TopicConfig.java index a1d075ae05118..1a13a19a51103 100755 --- a/clients/src/main/java/org/apache/kafka/common/config/TopicConfig.java +++ b/clients/src/main/java/org/apache/kafka/common/config/TopicConfig.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.config; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** *

    Keys that can be used to configure a topic. These keys are useful when creating or reconfiguring a * topic using the AdminClient. @@ -27,6 +29,7 @@ */ // This is a public API, so we should not remove or alter keys without a discussion and a deprecation period. // Eventually this should replace LogConfig.scala. +@InterfaceAudience.Public public class TopicConfig { public static final String SEGMENT_BYTES_CONFIG = "segment.bytes"; public static final String SEGMENT_BYTES_DOC = "This configuration controls the segment file size for " + diff --git a/clients/src/main/java/org/apache/kafka/common/config/provider/ConfigProvider.java b/clients/src/main/java/org/apache/kafka/common/config/provider/ConfigProvider.java index 81f0aac0d72d1..7e791edb9de19 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/provider/ConfigProvider.java +++ b/clients/src/main/java/org/apache/kafka/common/config/provider/ConfigProvider.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.config.provider; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigChangeCallback; import org.apache.kafka.common.config.ConfigData; @@ -30,6 +31,7 @@ * To support this, implementations of this interface should also contain a service provider configuration file in * {@code META-INF/services/org.apache.kafka.common.config.provider.ConfigProvider}. */ +@InterfaceAudience.Public public interface ConfigProvider extends Configurable, Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/config/provider/DirectoryConfigProvider.java b/clients/src/main/java/org/apache/kafka/common/config/provider/DirectoryConfigProvider.java index aecd29be6ff09..f17774f15763c 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/provider/DirectoryConfigProvider.java +++ b/clients/src/main/java/org/apache/kafka/common/config/provider/DirectoryConfigProvider.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.config.provider; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigData; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.config.internals.AllowedPaths; @@ -32,13 +34,13 @@ import java.util.stream.Collectors; import java.util.stream.Stream; - /** * An implementation of {@link ConfigProvider} based on a directory of files. * Property keys correspond to the names of the regular (i.e. non-directory) * files in a directory given by the path parameter. * Property values are taken from the file contents corresponding to each key. */ +@InterfaceAudience.Public public class DirectoryConfigProvider implements ConfigProvider { private static final Logger log = LoggerFactory.getLogger(DirectoryConfigProvider.class); diff --git a/clients/src/main/java/org/apache/kafka/common/config/provider/EnvVarConfigProvider.java b/clients/src/main/java/org/apache/kafka/common/config/provider/EnvVarConfigProvider.java index 309811dbb38d5..70f0c9a6151ed 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/provider/EnvVarConfigProvider.java +++ b/clients/src/main/java/org/apache/kafka/common/config/provider/EnvVarConfigProvider.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.config.provider; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigData; import org.apache.kafka.common.config.ConfigException; @@ -35,6 +36,7 @@ * Using an allowlist pattern {@link EnvVarConfigProvider#ALLOWLIST_PATTERN_CONFIG} that supports regular expressions, * it is possible to limit access to specific environment variables. Default allowlist pattern is ".*". */ +@InterfaceAudience.Public public class EnvVarConfigProvider implements ConfigProvider { private static final Logger log = LoggerFactory.getLogger(EnvVarConfigProvider.class); diff --git a/clients/src/main/java/org/apache/kafka/common/config/provider/FileConfigProvider.java b/clients/src/main/java/org/apache/kafka/common/config/provider/FileConfigProvider.java index a96c761c986f1..7cae3361e0c4a 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/provider/FileConfigProvider.java +++ b/clients/src/main/java/org/apache/kafka/common/config/provider/FileConfigProvider.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.config.provider; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigData; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.config.internals.AllowedPaths; @@ -38,6 +39,7 @@ * An implementation of {@link ConfigProvider} that represents a Properties file. * All property keys and values are stored as cleartext. */ +@InterfaceAudience.Public public class FileConfigProvider implements ConfigProvider { private static final Logger log = LoggerFactory.getLogger(FileConfigProvider.class); diff --git a/clients/src/main/java/org/apache/kafka/common/config/types/Password.java b/clients/src/main/java/org/apache/kafka/common/config/types/Password.java index eafffb967f017..107e27816ebf0 100644 --- a/clients/src/main/java/org/apache/kafka/common/config/types/Password.java +++ b/clients/src/main/java/org/apache/kafka/common/config/types/Password.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.config.types; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A wrapper class for passwords to hide them while logging a config */ +@InterfaceAudience.Public public class Password { public static final String HIDDEN = "[hidden]"; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ApiException.java b/clients/src/main/java/org/apache/kafka/common/errors/ApiException.java index aa4e98c1b7b6b..46410f1b9a3af 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ApiException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ApiException.java @@ -14,14 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Any API exception that is part of the public protocol and should be a subclass of this class and be part of this * package. */ +@InterfaceAudience.Public public class ApiException extends KafkaException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ApplicationRecoverableException.java b/clients/src/main/java/org/apache/kafka/common/errors/ApplicationRecoverableException.java index c07c20e86d933..078925a5ff1b0 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ApplicationRecoverableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ApplicationRecoverableException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that the error is fatal to the producer, and the application * needs to restart the producer after handling the error. Depending on the application, * different recovery strategies (e.g., re-balancing task, restoring from checkpoints) may be employed. */ +@InterfaceAudience.Public public abstract class ApplicationRecoverableException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/AuthenticationException.java b/clients/src/main/java/org/apache/kafka/common/errors/AuthenticationException.java index ed12cf259a2d1..6d66170957386 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/AuthenticationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/AuthenticationException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + import javax.net.ssl.SSLException; /** @@ -32,6 +35,7 @@ *

  • {@link SslAuthenticationException} if SSL handshake failed due to any {@link SSLException}.
  • * */ +@InterfaceAudience.Public public class AuthenticationException extends InvalidConfigurationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/AuthorizationException.java b/clients/src/main/java/org/apache/kafka/common/errors/AuthorizationException.java index 8ff29af9597d4..151434bce8ca4 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/AuthorizationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/AuthorizationException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class AuthorizationException extends InvalidConfigurationException { public AuthorizationException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/AuthorizerNotReadyException.java b/clients/src/main/java/org/apache/kafka/common/errors/AuthorizerNotReadyException.java index 1c110ef2143cc..bb58fccccd704 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/AuthorizerNotReadyException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/AuthorizerNotReadyException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An exception that indicates that the authorizer is not ready to receive the request yet. */ +@InterfaceAudience.Public public class AuthorizerNotReadyException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/BrokerIdNotRegisteredException.java b/clients/src/main/java/org/apache/kafka/common/errors/BrokerIdNotRegisteredException.java index cc8a47aa7bd87..7ad377885bd82 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/BrokerIdNotRegisteredException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/BrokerIdNotRegisteredException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class BrokerIdNotRegisteredException extends ApiException { public BrokerIdNotRegisteredException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/BrokerNotAvailableException.java b/clients/src/main/java/org/apache/kafka/common/errors/BrokerNotAvailableException.java index 26bb803e84dd3..bfc15520f5ba0 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/BrokerNotAvailableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/BrokerNotAvailableException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class BrokerNotAvailableException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ClusterAuthorizationException.java b/clients/src/main/java/org/apache/kafka/common/errors/ClusterAuthorizationException.java index 61b892984863c..3d553dfefa1cf 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ClusterAuthorizationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ClusterAuthorizationException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class ClusterAuthorizationException extends AuthorizationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ConcurrentTransactionsException.java b/clients/src/main/java/org/apache/kafka/common/errors/ConcurrentTransactionsException.java index 118b4de50aadf..c32b0312b91ed 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ConcurrentTransactionsException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ConcurrentTransactionsException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class ConcurrentTransactionsException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ControllerMovedException.java b/clients/src/main/java/org/apache/kafka/common/errors/ControllerMovedException.java index 124e79353ff3c..3a7d40f27a505 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ControllerMovedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ControllerMovedException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class ControllerMovedException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/CoordinatorLoadInProgressException.java b/clients/src/main/java/org/apache/kafka/common/errors/CoordinatorLoadInProgressException.java index 4bdb97878353f..92ede98e628a5 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/CoordinatorLoadInProgressException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/CoordinatorLoadInProgressException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * In the context of the group coordinator, the broker returns this error code for any coordinator request if * it is still loading the group metadata (e.g. after a leader change for that group metadata topic partition). @@ -24,6 +27,7 @@ * request with the same transactional id, or if the transaction cache is currently being populated from the transaction * log. */ +@InterfaceAudience.Public public class CoordinatorLoadInProgressException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/CoordinatorNotAvailableException.java b/clients/src/main/java/org/apache/kafka/common/errors/CoordinatorNotAvailableException.java index 2bd7d911a7a03..687a52efe3391 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/CoordinatorNotAvailableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/CoordinatorNotAvailableException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * In the context of the group coordinator, the broker returns this error code for metadata or offset commit * requests if the group metadata topic has not been created yet. @@ -23,6 +26,7 @@ * In the context of the transactional coordinator, this error will be returned if the underlying transactional log * is under replicated or if an append to the log times out. */ +@InterfaceAudience.Public public class CoordinatorNotAvailableException extends RefreshRetriableException { public static final CoordinatorNotAvailableException INSTANCE = new CoordinatorNotAvailableException(); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/CorruptRecordException.java b/clients/src/main/java/org/apache/kafka/common/errors/CorruptRecordException.java index abcf516618fbd..1d809d411661b 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/CorruptRecordException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/CorruptRecordException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This exception indicates a record has failed its internal CRC check, this generally indicates network or disk * corruption. */ +@InterfaceAudience.Public public class CorruptRecordException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenAuthorizationException.java b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenAuthorizationException.java index ddc97c64cf38c..29a2ff2e4ae76 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenAuthorizationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenAuthorizationException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class DelegationTokenAuthorizationException extends AuthorizationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenDisabledException.java b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenDisabledException.java index 798611e57ee5d..47b4ced371d7f 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenDisabledException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenDisabledException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class DelegationTokenDisabledException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenExpiredException.java b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenExpiredException.java index 4dae7f3f493a6..782ac493899e3 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenExpiredException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenExpiredException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class DelegationTokenExpiredException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenNotFoundException.java index 5875edfef7ea4..f162722b04d19 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenNotFoundException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class DelegationTokenNotFoundException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenOwnerMismatchException.java b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenOwnerMismatchException.java index 5c8239ebb59a2..8d44e324fc126 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenOwnerMismatchException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DelegationTokenOwnerMismatchException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class DelegationTokenOwnerMismatchException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DisconnectException.java b/clients/src/main/java/org/apache/kafka/common/errors/DisconnectException.java index e0bc787ad55b2..cbbcdd6afc4f5 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DisconnectException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DisconnectException.java @@ -14,12 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Server disconnected before a request could be completed. */ +@InterfaceAudience.Public public class DisconnectException extends RetriableException { public static final DisconnectException INSTANCE = new DisconnectException(); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DuplicateBrokerRegistrationException.java b/clients/src/main/java/org/apache/kafka/common/errors/DuplicateBrokerRegistrationException.java index 06f382063969a..389b24c9ebb47 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DuplicateBrokerRegistrationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DuplicateBrokerRegistrationException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class DuplicateBrokerRegistrationException extends ApiException { public DuplicateBrokerRegistrationException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DuplicateResourceException.java b/clients/src/main/java/org/apache/kafka/common/errors/DuplicateResourceException.java index 1c0ec43a52c7b..39cfcf6b84a68 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DuplicateResourceException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DuplicateResourceException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Exception thrown due to a request that illegally refers to the same resource twice * (for example, trying to both create and delete the same SCRAM credential for a particular user in a single request). */ +@InterfaceAudience.Public public class DuplicateResourceException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DuplicateSequenceException.java b/clients/src/main/java/org/apache/kafka/common/errors/DuplicateSequenceException.java index 11f81af5bb868..ddefcfbc8365b 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DuplicateSequenceException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DuplicateSequenceException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class DuplicateSequenceException extends ApiException { public DuplicateSequenceException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/DuplicateVoterException.java b/clients/src/main/java/org/apache/kafka/common/errors/DuplicateVoterException.java index 11df6eaced24e..d69325a32ec6d 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/DuplicateVoterException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/DuplicateVoterException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class DuplicateVoterException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ElectionNotNeededException.java b/clients/src/main/java/org/apache/kafka/common/errors/ElectionNotNeededException.java index 74fc7d670158b..401bdd6b75865 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ElectionNotNeededException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ElectionNotNeededException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class ElectionNotNeededException extends InvalidMetadataException { public ElectionNotNeededException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/EligibleLeadersNotAvailableException.java b/clients/src/main/java/org/apache/kafka/common/errors/EligibleLeadersNotAvailableException.java index 87679652e55f1..572a14197b64b 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/EligibleLeadersNotAvailableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/EligibleLeadersNotAvailableException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class EligibleLeadersNotAvailableException extends InvalidMetadataException { public EligibleLeadersNotAvailableException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/FeatureUpdateFailedException.java b/clients/src/main/java/org/apache/kafka/common/errors/FeatureUpdateFailedException.java index 9f5e23d3104da..3e70aebe83c3d 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/FeatureUpdateFailedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/FeatureUpdateFailedException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class FeatureUpdateFailedException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/FencedInstanceIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/FencedInstanceIdException.java index ac4ae6bdcc6ef..9a4d6752a75aa 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/FencedInstanceIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/FencedInstanceIdException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class FencedInstanceIdException extends ApplicationRecoverableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/FencedLeaderEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/FencedLeaderEpochException.java index 24f0eef93924b..c93a809ee8d9c 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/FencedLeaderEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/FencedLeaderEpochException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The request contained a leader epoch which is smaller than that on the broker that received the * request. This can happen when an operation is attempted before a pending metadata update has been * received. Clients will typically refresh metadata before retrying. */ +@InterfaceAudience.Public public class FencedLeaderEpochException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/FencedMemberEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/FencedMemberEpochException.java index 69e2df9ba77ac..153071dc3be86 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/FencedMemberEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/FencedMemberEpochException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class FencedMemberEpochException extends ApiException { public FencedMemberEpochException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/FencedStateEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/FencedStateEpochException.java index 1e74bba199402..dece87a915eb0 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/FencedStateEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/FencedStateEpochException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown when the share coordinator rejected the request because the share-group state epoch did not match. */ +@InterfaceAudience.Public public class FencedStateEpochException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/FetchSessionIdNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/FetchSessionIdNotFoundException.java index 2ce5f740d6719..7bff016f619a3 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/FetchSessionIdNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/FetchSessionIdNotFoundException.java @@ -17,6 +17,9 @@ package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class FetchSessionIdNotFoundException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/FetchSessionTopicIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/FetchSessionTopicIdException.java index 11a6e1d11d5a0..d86fdcc758497 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/FetchSessionTopicIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/FetchSessionTopicIdException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class FetchSessionTopicIdException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/GroupAuthorizationException.java b/clients/src/main/java/org/apache/kafka/common/errors/GroupAuthorizationException.java index 22eae3b57b4c8..a3632928b575f 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/GroupAuthorizationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/GroupAuthorizationException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class GroupAuthorizationException extends AuthorizationException { private final String groupId; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/GroupDeletionFailedException.java b/clients/src/main/java/org/apache/kafka/common/errors/GroupDeletionFailedException.java index eaa8316052618..b853d13819dcc 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/GroupDeletionFailedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/GroupDeletionFailedException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that {@code DeleteGroups} could not complete for the affected group. The * accompanying error message describes the underlying cause; the caller may retry once * the underlying condition is resolved. */ +@InterfaceAudience.Public public class GroupDeletionFailedException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/GroupIdNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/GroupIdNotFoundException.java index a4d509d3a2074..639869f7febf2 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/GroupIdNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/GroupIdNotFoundException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class GroupIdNotFoundException extends ApiException { public GroupIdNotFoundException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/GroupMaxSizeReachedException.java b/clients/src/main/java/org/apache/kafka/common/errors/GroupMaxSizeReachedException.java index fd55289dcccea..72867f172338f 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/GroupMaxSizeReachedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/GroupMaxSizeReachedException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that a group is already at its configured maximum capacity and cannot accommodate more members */ +@InterfaceAudience.Public public class GroupMaxSizeReachedException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/GroupNotEmptyException.java b/clients/src/main/java/org/apache/kafka/common/errors/GroupNotEmptyException.java index e15b3e6d57f41..11d7d97d1f43a 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/GroupNotEmptyException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/GroupNotEmptyException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class GroupNotEmptyException extends ApiException { public GroupNotEmptyException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/GroupSubscribedToTopicException.java b/clients/src/main/java/org/apache/kafka/common/errors/GroupSubscribedToTopicException.java index a62fe325d8136..7ef1d7495d8b1 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/GroupSubscribedToTopicException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/GroupSubscribedToTopicException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class GroupSubscribedToTopicException extends ApiException { public GroupSubscribedToTopicException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/IllegalGenerationException.java b/clients/src/main/java/org/apache/kafka/common/errors/IllegalGenerationException.java index 2d739ce0290dc..45eb13883d322 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/IllegalGenerationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/IllegalGenerationException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class IllegalGenerationException extends ApplicationRecoverableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/IllegalSaslStateException.java b/clients/src/main/java/org/apache/kafka/common/errors/IllegalSaslStateException.java index 691244a7ebc9a..07c69de9da256 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/IllegalSaslStateException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/IllegalSaslStateException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This exception indicates unexpected requests prior to SASL authentication. * This could be due to misconfigured security, e.g. if PLAINTEXT protocol * is used to connect to a SASL endpoint. */ +@InterfaceAudience.Public public class IllegalSaslStateException extends AuthenticationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InconsistentClusterIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/InconsistentClusterIdException.java index 62fed41f708b7..8d58c83496ae2 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InconsistentClusterIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InconsistentClusterIdException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InconsistentClusterIdException extends ApiException { public InconsistentClusterIdException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InconsistentGroupProtocolException.java b/clients/src/main/java/org/apache/kafka/common/errors/InconsistentGroupProtocolException.java index 28bcbe5a962de..d57c303391a6f 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InconsistentGroupProtocolException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InconsistentGroupProtocolException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InconsistentGroupProtocolException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InconsistentTopicIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/InconsistentTopicIdException.java index 1dfe468564bf5..d3cffa47c2186 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InconsistentTopicIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InconsistentTopicIdException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InconsistentTopicIdException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InconsistentVoterSetException.java b/clients/src/main/java/org/apache/kafka/common/errors/InconsistentVoterSetException.java index 8a3667b76dd30..ec9206512a60c 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InconsistentVoterSetException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InconsistentVoterSetException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InconsistentVoterSetException extends ApiException { private static final long serialVersionUID = 1; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/IneligibleReplicaException.java b/clients/src/main/java/org/apache/kafka/common/errors/IneligibleReplicaException.java index 6c79add033a4e..0f0273aa6cb79 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/IneligibleReplicaException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/IneligibleReplicaException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class IneligibleReplicaException extends ApiException { public IneligibleReplicaException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InterruptException.java b/clients/src/main/java/org/apache/kafka/common/errors/InterruptException.java index fec66bb0ec821..91bae53bf25aa 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InterruptException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InterruptException.java @@ -14,13 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * An unchecked wrapper for InterruptedException */ +@InterfaceAudience.Public public class InterruptException extends KafkaException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidCommitOffsetSizeException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidCommitOffsetSizeException.java index a17a30fab8586..464f279cf372d 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidCommitOffsetSizeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidCommitOffsetSizeException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidCommitOffsetSizeException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidConfigurationException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidConfigurationException.java index 85e63c42ec398..f92dd58c32b55 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidConfigurationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidConfigurationException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidConfigurationException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidFetchSessionEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidFetchSessionEpochException.java index 3b135c0147d06..18a77b3f287b1 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidFetchSessionEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidFetchSessionEpochException.java @@ -17,6 +17,9 @@ package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidFetchSessionEpochException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidFetchSizeException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidFetchSizeException.java index 65a0aebbc3677..e711e8be1529e 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidFetchSizeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidFetchSizeException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidFetchSizeException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidGroupIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidGroupIdException.java index 95e6f36ea030b..c541093abe1b2 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidGroupIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidGroupIdException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidGroupIdException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidMetadataException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidMetadataException.java index f3485a8364acb..cb2d686e023d2 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidMetadataException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidMetadataException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An exception that may indicate the client's metadata is out of date */ +@InterfaceAudience.Public public abstract class InvalidMetadataException extends RefreshRetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidOffsetException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidOffsetException.java index 0d954f1268a9d..6fe0e9f2e3bfc 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidOffsetException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidOffsetException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown when the offset for a set of partitions is invalid (either undefined or out of range), * and no reset policy has been configured. * @see OffsetOutOfRangeException */ +@InterfaceAudience.Public public class InvalidOffsetException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidPartitionsException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidPartitionsException.java index c65ced43cf79c..84645d4b207a7 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidPartitionsException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidPartitionsException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidPartitionsException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidPidMappingException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidPidMappingException.java index 626a19507f400..548d73dffe0b2 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidPidMappingException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidPidMappingException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidPidMappingException extends ApplicationRecoverableException { public InvalidPidMappingException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidPrincipalTypeException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidPrincipalTypeException.java index a0736e976354f..fc363122adfcb 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidPrincipalTypeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidPrincipalTypeException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidPrincipalTypeException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidProducerEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidProducerEpochException.java index b65ea67aed52c..6905ff8d69bcc 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidProducerEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidProducerEpochException.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This exception indicates that the produce request sent to the partition leader * contains a non-matching producer epoch. When encountering this exception, user should abort the ongoing transaction * by calling KafkaProducer#abortTransaction which would try to send initPidRequest and reinitialize the producer * under the hood. */ +@InterfaceAudience.Public public class InvalidProducerEpochException extends ApplicationRecoverableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRecordStateException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRecordStateException.java index ae0fef5edeaef..47d7b149296c8 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRecordStateException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRecordStateException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown when the acknowledgement of delivery of a record could not be completed because the record * state is invalid. */ +@InterfaceAudience.Public public class InvalidRecordStateException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRegistrationException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRegistrationException.java index 9eef7e048bca8..874d9333f567b 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRegistrationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRegistrationException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown when a broker registration request is considered invalid by the controller. */ +@InterfaceAudience.Public public class InvalidRegistrationException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRegularExpression.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRegularExpression.java index f1ea4d19abc95..a7ff38648b2dd 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRegularExpression.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRegularExpression.java @@ -17,9 +17,12 @@ package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown when a regular expression received in a request is not valid. */ +@InterfaceAudience.Public public class InvalidRegularExpression extends ApiException { public InvalidRegularExpression(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidReplicaAssignmentException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidReplicaAssignmentException.java index 5357d9194642f..7d0959cca95de 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidReplicaAssignmentException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidReplicaAssignmentException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidReplicaAssignmentException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidReplicationFactorException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidReplicationFactorException.java index 508d73a793f5d..f477457e8f45b 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidReplicationFactorException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidReplicationFactorException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidReplicationFactorException extends InvalidConfigurationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRequestException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRequestException.java index 7470f663f4406..c212de02536f9 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRequestException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRequestException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown when a request breaks basic wire protocol rules. * This most likely occurs because of a request being malformed by the client library or * the message was sent to an incompatible broker. */ +@InterfaceAudience.Public public class InvalidRequestException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRequiredAcksException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRequiredAcksException.java index f861dbfee18bb..40805298efaad 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidRequiredAcksException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidRequiredAcksException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidRequiredAcksException extends InvalidConfigurationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidSessionTimeoutException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidSessionTimeoutException.java index a971498426f12..c9a76a1e2dd3f 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidSessionTimeoutException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidSessionTimeoutException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidSessionTimeoutException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidShareSessionEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidShareSessionEpochException.java index e261d8b7a8e88..8e55e66da3071 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidShareSessionEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidShareSessionEpochException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown when the share session epoch is invalid. */ +@InterfaceAudience.Public public class InvalidShareSessionEpochException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidTimestampException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidTimestampException.java index 0e3cd929ef77b..369e634591769 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidTimestampException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidTimestampException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicate the timestamp of a record is invalid. */ +@InterfaceAudience.Public public class InvalidTimestampException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidTopicException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidTopicException.java index cf0ed5ed5cc9b..c0971a108005d 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidTopicException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidTopicException.java @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.HashSet; import java.util.Set; - /** * The client has attempted to perform an operation on an invalid topic. * For example the topic name is too long, contains invalid characters etc. @@ -27,6 +29,7 @@ * * @see UnknownTopicOrPartitionException */ +@InterfaceAudience.Public public class InvalidTopicException extends InvalidConfigurationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidTxnStateException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidTxnStateException.java index ff069049895a0..2dee8ad79f69e 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidTxnStateException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidTxnStateException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidTxnStateException extends ApiException { public InvalidTxnStateException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidTxnTimeoutException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidTxnTimeoutException.java index b2d8428fc874f..767d036dc276a 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidTxnTimeoutException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidTxnTimeoutException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The transaction coordinator returns this error code if the timeout received via the InitProducerIdRequest is larger than * the `transaction.max.timeout.ms` config value. */ +@InterfaceAudience.Public public class InvalidTxnTimeoutException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidUpdateVersionException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidUpdateVersionException.java index e41262d59f52d..7e411d2bdd1aa 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidUpdateVersionException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidUpdateVersionException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidUpdateVersionException extends ApiException { public InvalidUpdateVersionException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/InvalidVoterKeyException.java b/clients/src/main/java/org/apache/kafka/common/errors/InvalidVoterKeyException.java index c417713e349dc..7b368f36ef935 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/InvalidVoterKeyException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/InvalidVoterKeyException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InvalidVoterKeyException extends ApiException { private static final long serialVersionUID = 1; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/KafkaStorageException.java b/clients/src/main/java/org/apache/kafka/common/errors/KafkaStorageException.java index c45afb0053dbd..7ababc4eff179 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/KafkaStorageException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/KafkaStorageException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Miscellaneous disk-related IOException occurred when handling a request. * Client should request metadata update and retry if the response shows KafkaStorageException @@ -28,6 +31,7 @@ * 3) It is preferred for IOException to be caught in Log rather than in ReplicaManager or LogSegment. * */ +@InterfaceAudience.Public public class KafkaStorageException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/LeaderNotAvailableException.java b/clients/src/main/java/org/apache/kafka/common/errors/LeaderNotAvailableException.java index 69bc624e5a82a..95593905f72c3 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/LeaderNotAvailableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/LeaderNotAvailableException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * There is no currently available leader for the given partition (either because a leadership election is in progress * or because all replicas are down). */ +@InterfaceAudience.Public public class LeaderNotAvailableException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ListenerNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/ListenerNotFoundException.java index 82c5d892f49ba..6e089ba7f6908 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ListenerNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ListenerNotFoundException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The leader does not have an endpoint corresponding to the listener on which metadata was requested. * This could indicate a broker configuration error or a transient error when listeners are updated @@ -23,6 +26,7 @@ * This is currently used only for missing listeners on leader brokers, but may be used for followers * in future. */ +@InterfaceAudience.Public public class ListenerNotFoundException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/LogDirNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/LogDirNotFoundException.java index 0a4ae1608b884..4d59d1e9753c8 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/LogDirNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/LogDirNotFoundException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown when a request is made for a log directory that is not present on the broker */ +@InterfaceAudience.Public public class LogDirNotFoundException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/MemberIdRequiredException.java b/clients/src/main/java/org/apache/kafka/common/errors/MemberIdRequiredException.java index 55393e0e286af..4bab550dfaee6 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/MemberIdRequiredException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/MemberIdRequiredException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class MemberIdRequiredException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/MismatchedEndpointTypeException.java b/clients/src/main/java/org/apache/kafka/common/errors/MismatchedEndpointTypeException.java index a9a2a5ba71c90..1ea553566cd50 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/MismatchedEndpointTypeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/MismatchedEndpointTypeException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class MismatchedEndpointTypeException extends ApiException { public MismatchedEndpointTypeException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/NetworkException.java b/clients/src/main/java/org/apache/kafka/common/errors/NetworkException.java index fadd9bd484789..37e640559fece 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/NetworkException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/NetworkException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A misc. network-related IOException occurred when making a request. This could be because the client's metadata is * out of date and it is making a request to a node that is now dead. */ +@InterfaceAudience.Public public class NetworkException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/NewLeaderElectedException.java b/clients/src/main/java/org/apache/kafka/common/errors/NewLeaderElectedException.java index 20fd869df9f0e..c7c2e87f811e1 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/NewLeaderElectedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/NewLeaderElectedException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class NewLeaderElectedException extends ApiException { public NewLeaderElectedException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/NoReassignmentInProgressException.java b/clients/src/main/java/org/apache/kafka/common/errors/NoReassignmentInProgressException.java index 9fd8a73c80916..ba81b8bec409f 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/NoReassignmentInProgressException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/NoReassignmentInProgressException.java @@ -17,9 +17,12 @@ package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown if a reassignment cannot be cancelled because none is in progress. */ +@InterfaceAudience.Public public class NoReassignmentInProgressException extends ApiException { public NoReassignmentInProgressException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/NotControllerException.java b/clients/src/main/java/org/apache/kafka/common/errors/NotControllerException.java index 1c3e01457f763..9bc8d04a82bd4 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/NotControllerException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/NotControllerException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class NotControllerException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/NotCoordinatorException.java b/clients/src/main/java/org/apache/kafka/common/errors/NotCoordinatorException.java index dc116d02c05c5..71c2f805db49f 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/NotCoordinatorException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/NotCoordinatorException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * In the context of the group coordinator, the broker returns this error code if it receives an offset fetch * or commit request for a group it's not the coordinator of. @@ -23,6 +26,7 @@ * In the context of the transactional coordinator, it returns this error when it receives a transactional * request with a transactionalId the coordinator doesn't own. */ +@InterfaceAudience.Public public class NotCoordinatorException extends RefreshRetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/NotEnoughReplicasAfterAppendException.java b/clients/src/main/java/org/apache/kafka/common/errors/NotEnoughReplicasAfterAppendException.java index 22ebc3407d5ee..5c427a9f2a5ba 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/NotEnoughReplicasAfterAppendException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/NotEnoughReplicasAfterAppendException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Number of insync replicas for the partition is lower than min.insync.replicas This exception is raised when the low * ISR size is discovered *after* the message was already appended to the log. Producer retries will cause duplicates. */ +@InterfaceAudience.Public public class NotEnoughReplicasAfterAppendException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/NotEnoughReplicasException.java b/clients/src/main/java/org/apache/kafka/common/errors/NotEnoughReplicasException.java index cb90e8690320f..b0816745f98b5 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/NotEnoughReplicasException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/NotEnoughReplicasException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Number of insync replicas for the partition is lower than min.insync.replicas */ +@InterfaceAudience.Public public class NotEnoughReplicasException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/NotLeaderOrFollowerException.java b/clients/src/main/java/org/apache/kafka/common/errors/NotLeaderOrFollowerException.java index c45f158e69988..4409fabb1524e 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/NotLeaderOrFollowerException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/NotLeaderOrFollowerException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Broker returns this error if a request could not be processed because the broker is not the leader * or follower for a topic partition. This could be a transient exception during leader elections and @@ -24,6 +27,7 @@ * satisfied by a leader or follower, this exception indicates that the broker is not a replica * of the topic partition. */ +@InterfaceAudience.Public public class NotLeaderOrFollowerException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/OffsetMetadataTooLarge.java b/clients/src/main/java/org/apache/kafka/common/errors/OffsetMetadataTooLarge.java index b77f16740b32f..ade48e5d9d9b4 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/OffsetMetadataTooLarge.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/OffsetMetadataTooLarge.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The client has tried to save its offset with associated metadata larger than the maximum size allowed by the server. */ +@InterfaceAudience.Public public class OffsetMetadataTooLarge extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/OffsetMovedToTieredStorageException.java b/clients/src/main/java/org/apache/kafka/common/errors/OffsetMovedToTieredStorageException.java index 6ea48c604d1bb..8800d6006bc33 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/OffsetMovedToTieredStorageException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/OffsetMovedToTieredStorageException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class OffsetMovedToTieredStorageException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/OffsetNotAvailableException.java b/clients/src/main/java/org/apache/kafka/common/errors/OffsetNotAvailableException.java index 97de3b3d64e96..7b0e73b63aadd 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/OffsetNotAvailableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/OffsetNotAvailableException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that the leader is not able to guarantee monotonically increasing offsets * due to the high watermark lagging behind the epoch start offset after a recent leader election */ +@InterfaceAudience.Public public class OffsetNotAvailableException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/OffsetOutOfRangeException.java b/clients/src/main/java/org/apache/kafka/common/errors/OffsetOutOfRangeException.java index 92a70fdfed3dd..a67749ef85b14 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/OffsetOutOfRangeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/OffsetOutOfRangeException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * No reset policy has been defined, and the offsets for these partitions are either larger or smaller * than the range of offsets the server has for the given partition. */ +@InterfaceAudience.Public public class OffsetOutOfRangeException extends InvalidOffsetException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/OperationNotAttemptedException.java b/clients/src/main/java/org/apache/kafka/common/errors/OperationNotAttemptedException.java index 96df3211e99e5..e25cc141f4d44 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/OperationNotAttemptedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/OperationNotAttemptedException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that the broker did not attempt to execute this operation. This may happen for batched RPCs where some * operations in the batch failed, causing the broker to respond without trying the rest. */ +@InterfaceAudience.Public public class OperationNotAttemptedException extends ApiException { public OperationNotAttemptedException(final String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/OutOfOrderSequenceException.java b/clients/src/main/java/org/apache/kafka/common/errors/OutOfOrderSequenceException.java index 462e91e326803..78db653fa0dac 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/OutOfOrderSequenceException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/OutOfOrderSequenceException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This exception indicates that the broker received an unexpected sequence number from the producer, * which means that data may have been lost. If the producer is configured for idempotence only (i.e. @@ -24,6 +27,7 @@ * of sent records. For transactional producers, this is a fatal error and you should close the * producer. */ +@InterfaceAudience.Public public class OutOfOrderSequenceException extends ApiException { public OutOfOrderSequenceException(String msg) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/PolicyViolationException.java b/clients/src/main/java/org/apache/kafka/common/errors/PolicyViolationException.java index 0316938c861c4..031d8f681a766 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/PolicyViolationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/PolicyViolationException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Exception thrown if a create topics request does not satisfy the configured policy for a topic. */ +@InterfaceAudience.Public public class PolicyViolationException extends ApiException { public PolicyViolationException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/PositionOutOfRangeException.java b/clients/src/main/java/org/apache/kafka/common/errors/PositionOutOfRangeException.java index c502d19498580..02f1769f19382 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/PositionOutOfRangeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/PositionOutOfRangeException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class PositionOutOfRangeException extends ApiException { private static final long serialVersionUID = 1; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/PreferredLeaderNotAvailableException.java b/clients/src/main/java/org/apache/kafka/common/errors/PreferredLeaderNotAvailableException.java index 73dfd64ac6d23..21a46d4227394 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/PreferredLeaderNotAvailableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/PreferredLeaderNotAvailableException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class PreferredLeaderNotAvailableException extends InvalidMetadataException { public PreferredLeaderNotAvailableException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/PrincipalDeserializationException.java b/clients/src/main/java/org/apache/kafka/common/errors/PrincipalDeserializationException.java index d0eed95c98e2e..67c3ec119179f 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/PrincipalDeserializationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/PrincipalDeserializationException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Exception used to indicate a kafka principal deserialization failure during request forwarding. */ +@InterfaceAudience.Public public class PrincipalDeserializationException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ProducerFencedException.java b/clients/src/main/java/org/apache/kafka/common/errors/ProducerFencedException.java index 4a83bcbeb87af..a528c0846ef81 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ProducerFencedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ProducerFencedException.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This fatal exception indicates that another producer with the same transactional.id has been * started. It is only possible to have one producer instance with a transactional.id at any * given time, and the latest one to be started "fences" the previous instances so that they can no longer * make transactional requests. When you encounter this exception, you must close the producer instance. */ +@InterfaceAudience.Public public class ProducerFencedException extends ApplicationRecoverableException { public ProducerFencedException(String msg) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ReassignmentInProgressException.java b/clients/src/main/java/org/apache/kafka/common/errors/ReassignmentInProgressException.java index abd624bb0eb8f..85373b1b94896 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ReassignmentInProgressException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ReassignmentInProgressException.java @@ -17,9 +17,12 @@ package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown if a request cannot be completed because a partition reassignment is in progress. */ +@InterfaceAudience.Public public class ReassignmentInProgressException extends ApiException { public ReassignmentInProgressException(String msg) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/RebalanceInProgressException.java b/clients/src/main/java/org/apache/kafka/common/errors/RebalanceInProgressException.java index 031abb7f7bb3e..88631698f7f34 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/RebalanceInProgressException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/RebalanceInProgressException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class RebalanceInProgressException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/RebootstrapRequiredException.java b/clients/src/main/java/org/apache/kafka/common/errors/RebootstrapRequiredException.java index 78a66aabd3e4a..c1b46ef61ac60 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/RebootstrapRequiredException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/RebootstrapRequiredException.java @@ -17,6 +17,9 @@ package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class RebootstrapRequiredException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/RecordBatchTooLargeException.java b/clients/src/main/java/org/apache/kafka/common/errors/RecordBatchTooLargeException.java index 24f563e1c2777..d584635de102d 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/RecordBatchTooLargeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/RecordBatchTooLargeException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This record batch is larger than the maximum allowable size */ +@InterfaceAudience.Public public class RecordBatchTooLargeException extends InvalidConfigurationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/RecordDeserializationException.java b/clients/src/main/java/org/apache/kafka/common/errors/RecordDeserializationException.java index 6ed441d444b9b..f7c0af3459073 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/RecordDeserializationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/RecordDeserializationException.java @@ -18,6 +18,7 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.record.TimestampType; @@ -27,6 +28,7 @@ * This exception is raised for any error that occurs while deserializing records received by the consumer using * the configured {@link org.apache.kafka.common.serialization.Deserializer}. */ +@InterfaceAudience.Public public class RecordDeserializationException extends SerializationException { private static final long serialVersionUID = 2L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/RecordTooLargeException.java b/clients/src/main/java/org/apache/kafka/common/errors/RecordTooLargeException.java index 9ffaa876a43c1..6fe7310906ea9 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/RecordTooLargeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/RecordTooLargeException.java @@ -14,15 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; /** * This record is larger than the maximum allowable size */ +@InterfaceAudience.Public public class RecordTooLargeException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/RefreshRetriableException.java b/clients/src/main/java/org/apache/kafka/common/errors/RefreshRetriableException.java index 480cccf77633b..2cd7317b8a60d 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/RefreshRetriableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/RefreshRetriableException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that an operation failed due to outdated or invalid metadata, * requiring a refresh (e.g., refreshing producer metadata) before retrying the request. * The request can be modified or updated with fresh metadata before being retried. */ +@InterfaceAudience.Public public abstract class RefreshRetriableException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ReplicaNotAvailableException.java b/clients/src/main/java/org/apache/kafka/common/errors/ReplicaNotAvailableException.java index 07971cd57e18a..6b256307d1a95 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ReplicaNotAvailableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ReplicaNotAvailableException.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The replica is not available for the requested topic partition. This may be * a transient exception during reassignments. From version 2.6 onwards, Fetch requests * and other requests intended only for the leader or follower of the topic partition return * {@link NotLeaderOrFollowerException} if the broker is a not a replica of the partition. */ +@InterfaceAudience.Public public class ReplicaNotAvailableException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ResourceNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/ResourceNotFoundException.java index 17dca08248e34..437dcbbd6264e 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ResourceNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ResourceNotFoundException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Exception thrown due to a request for a resource that does not exist. */ +@InterfaceAudience.Public public class ResourceNotFoundException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/RetriableException.java b/clients/src/main/java/org/apache/kafka/common/errors/RetriableException.java index 6d9a76dc739fc..1f6ace0aa55b3 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/RetriableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/RetriableException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A retriable exception is a transient exception that if retried may succeed. */ +@InterfaceAudience.Public public abstract class RetriableException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/SaslAuthenticationException.java b/clients/src/main/java/org/apache/kafka/common/errors/SaslAuthenticationException.java index c6bc8bdb57404..9a8e0b4c49ec2 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/SaslAuthenticationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/SaslAuthenticationException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + import javax.security.sasl.SaslServer; /** @@ -33,6 +36,7 @@ * security-critical information in the message that should not be leaked to unauthenticated clients. *

    */ +@InterfaceAudience.Public public class SaslAuthenticationException extends AuthenticationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/SecurityDisabledException.java b/clients/src/main/java/org/apache/kafka/common/errors/SecurityDisabledException.java index 25f3f35b5003d..4b5b2227f2cd4 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/SecurityDisabledException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/SecurityDisabledException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An error indicating that security is disabled on the broker. */ +@InterfaceAudience.Public public class SecurityDisabledException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/SerializationException.java b/clients/src/main/java/org/apache/kafka/common/errors/SerializationException.java index 02d07101a7e6d..218bf77bdf328 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/SerializationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/SerializationException.java @@ -14,13 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Any exception during serialization in the producer */ +@InterfaceAudience.Public public class SerializationException extends KafkaException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ShareSessionLimitReachedException.java b/clients/src/main/java/org/apache/kafka/common/errors/ShareSessionLimitReachedException.java index 38a774e2d9550..a938594e71780 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ShareSessionLimitReachedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ShareSessionLimitReachedException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that a new share session could not be opened because the limit of share sessions has been reached. */ +@InterfaceAudience.Public public class ShareSessionLimitReachedException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ShareSessionNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/ShareSessionNotFoundException.java index 2b2249f8a5831..44b744099ccd8 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ShareSessionNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ShareSessionNotFoundException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Thrown when the share session was not found. */ +@InterfaceAudience.Public public class ShareSessionNotFoundException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/SnapshotNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/SnapshotNotFoundException.java index 5b3e7ed1605ec..b8aaea1c420db 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/SnapshotNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/SnapshotNotFoundException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class SnapshotNotFoundException extends ApiException { private static final long serialVersionUID = 1; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/SslAuthenticationException.java b/clients/src/main/java/org/apache/kafka/common/errors/SslAuthenticationException.java index 3cdbf2a5bc67d..8de06c5b8b6b4 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/SslAuthenticationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/SslAuthenticationException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + import javax.net.ssl.SSLException; /** @@ -29,6 +32,7 @@ * authentication failure or server host name verification failure. *

    */ +@InterfaceAudience.Public public class SslAuthenticationException extends AuthenticationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/StaleBrokerEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/StaleBrokerEpochException.java index a5c0b41400757..f1b93ed64ff24 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/StaleBrokerEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/StaleBrokerEpochException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class StaleBrokerEpochException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/StaleMemberEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/StaleMemberEpochException.java index d574965e52766..d12fcfe7284c2 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/StaleMemberEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/StaleMemberEpochException.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The StaleMemberEpochException is used in the context of the new * consumer group protocol (KIP-848). This error is returned in the * OffsetCommit/Fetch APIs when the member epoch received does not * match the current member epoch. */ +@InterfaceAudience.Public public class StaleMemberEpochException extends ApiException { public StaleMemberEpochException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/StreamsInvalidTopologyEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/StreamsInvalidTopologyEpochException.java index 2c14a2d37cb87..8647ca8986670 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/StreamsInvalidTopologyEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/StreamsInvalidTopologyEpochException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class StreamsInvalidTopologyEpochException extends ApiException { public StreamsInvalidTopologyEpochException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/StreamsInvalidTopologyException.java b/clients/src/main/java/org/apache/kafka/common/errors/StreamsInvalidTopologyException.java index 28a5c8ab77de8..1ff913965177f 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/StreamsInvalidTopologyException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/StreamsInvalidTopologyException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class StreamsInvalidTopologyException extends ApiException { public StreamsInvalidTopologyException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/StreamsTopologyDescriptionUpdateFailedException.java b/clients/src/main/java/org/apache/kafka/common/errors/StreamsTopologyDescriptionUpdateFailedException.java index df981b8b5b936..5bff117af78d9 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/StreamsTopologyDescriptionUpdateFailedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/StreamsTopologyDescriptionUpdateFailedException.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that the streams group topology description plugin failed to process * a StreamsGroupTopologyDescriptionUpdate request. The accompanying error message * describes the underlying cause; the broker tracks the transient-vs-permanent * distinction internally and does not reflect it on the wire. */ +@InterfaceAudience.Public public class StreamsTopologyDescriptionUpdateFailedException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/StreamsTopologyFencedException.java b/clients/src/main/java/org/apache/kafka/common/errors/StreamsTopologyFencedException.java index 8e4120221a0f1..6b64faa202b10 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/StreamsTopologyFencedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/StreamsTopologyFencedException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class StreamsTopologyFencedException extends ApiException { public StreamsTopologyFencedException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TelemetryTooLargeException.java b/clients/src/main/java/org/apache/kafka/common/errors/TelemetryTooLargeException.java index 75c9759953767..7970eca64fd90 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TelemetryTooLargeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TelemetryTooLargeException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This exception indicates that the size of the telemetry metrics data is too large. */ +@InterfaceAudience.Public public class TelemetryTooLargeException extends ApiException { public TelemetryTooLargeException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/ThrottlingQuotaExceededException.java b/clients/src/main/java/org/apache/kafka/common/errors/ThrottlingQuotaExceededException.java index c4d1350b205dd..91d055b2afaf8 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/ThrottlingQuotaExceededException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/ThrottlingQuotaExceededException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Exception thrown if an operation on a resource exceeds the throttling quota. */ +@InterfaceAudience.Public public class ThrottlingQuotaExceededException extends RetriableException { private int throttleTimeMs = 0; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TimeoutException.java b/clients/src/main/java/org/apache/kafka/common/errors/TimeoutException.java index 47fe034701bfd..e246cfc76f4cb 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TimeoutException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TimeoutException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that a request timed out. */ +@InterfaceAudience.Public public class TimeoutException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TopicAuthorizationException.java b/clients/src/main/java/org/apache/kafka/common/errors/TopicAuthorizationException.java index 0b4b210e1f615..74b31f5d6a323 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TopicAuthorizationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TopicAuthorizationException.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Set; +@InterfaceAudience.Public public class TopicAuthorizationException extends AuthorizationException { private final Set unauthorizedTopics; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TopicDeletionDisabledException.java b/clients/src/main/java/org/apache/kafka/common/errors/TopicDeletionDisabledException.java index 41577d2a288e7..9be14d91e7e19 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TopicDeletionDisabledException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TopicDeletionDisabledException.java @@ -17,6 +17,9 @@ package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class TopicDeletionDisabledException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TopicExistsException.java b/clients/src/main/java/org/apache/kafka/common/errors/TopicExistsException.java index cc0c8f14c818b..4168c51768e2b 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TopicExistsException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TopicExistsException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class TopicExistsException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TransactionAbortableException.java b/clients/src/main/java/org/apache/kafka/common/errors/TransactionAbortableException.java index 544a5c122b2f8..6e33e5d6cd576 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TransactionAbortableException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TransactionAbortableException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class TransactionAbortableException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TransactionAbortedException.java b/clients/src/main/java/org/apache/kafka/common/errors/TransactionAbortedException.java index f61b69559c8b5..e6f5c7433fb8a 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TransactionAbortedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TransactionAbortedException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This is the Exception thrown when we are aborting any undrained batches during * a transaction which is aborted without any underlying cause - which likely means that the user chose to abort. */ +@InterfaceAudience.Public public class TransactionAbortedException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TransactionCoordinatorFencedException.java b/clients/src/main/java/org/apache/kafka/common/errors/TransactionCoordinatorFencedException.java index 583ce04873040..2bf77a1b4ad4d 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TransactionCoordinatorFencedException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TransactionCoordinatorFencedException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class TransactionCoordinatorFencedException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TransactionalIdAuthorizationException.java b/clients/src/main/java/org/apache/kafka/common/errors/TransactionalIdAuthorizationException.java index 3f85513ae72e9..2c33f342f7fdc 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TransactionalIdAuthorizationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TransactionalIdAuthorizationException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class TransactionalIdAuthorizationException extends AuthorizationException { public TransactionalIdAuthorizationException(final String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/TransactionalIdNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/TransactionalIdNotFoundException.java index 240eaa33a8474..69d1024765bf2 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/TransactionalIdNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/TransactionalIdNotFoundException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class TransactionalIdNotFoundException extends ApiException { public TransactionalIdNotFoundException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnacceptableCredentialException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnacceptableCredentialException.java index b7cffff6addd8..29ec3f464d4b2 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnacceptableCredentialException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnacceptableCredentialException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Exception thrown when attempting to define a credential that does not meet the criteria for acceptability * (for example, attempting to create a SCRAM credential with an empty username or password or too few/many iterations). */ +@InterfaceAudience.Public public class UnacceptableCredentialException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnknownControllerIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnknownControllerIdException.java index 58d0c89014b11..e8f53e477a76c 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnknownControllerIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnknownControllerIdException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class UnknownControllerIdException extends ApiException { public UnknownControllerIdException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnknownLeaderEpochException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnknownLeaderEpochException.java index 3714c364bedba..516ba9ad9122a 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnknownLeaderEpochException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnknownLeaderEpochException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The request contained a leader epoch which is larger than that on the broker that received the * request. This can happen if the client observes a metadata update before it has been propagated * to all brokers. Clients need not refresh metadata before retrying. */ +@InterfaceAudience.Public public class UnknownLeaderEpochException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnknownMemberIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnknownMemberIdException.java index 88d717c120f3a..267bb00b3f613 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnknownMemberIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnknownMemberIdException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class UnknownMemberIdException extends ApplicationRecoverableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnknownProducerIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnknownProducerIdException.java index ce1734568d7cc..e2d4ee87ee496 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnknownProducerIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnknownProducerIdException.java @@ -17,12 +17,15 @@ package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This exception is raised by the broker if it could not locate the producer metadata associated with the producerId * in question. This could happen if, for instance, the producer's records were deleted because their retention time * had elapsed. Once the last records of the producerId are removed, the producer's metadata is removed from the broker, * and future appends by the producer will return this exception. */ +@InterfaceAudience.Public public class UnknownProducerIdException extends OutOfOrderSequenceException { public UnknownProducerIdException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnknownServerException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnknownServerException.java index 37e003bfef6d1..7f4f4cc9d9036 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnknownServerException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnknownServerException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An error occurred on the server for which the client doesn't have a corresponding error code. This is generally an * unexpected error. * */ +@InterfaceAudience.Public public class UnknownServerException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnknownSubscriptionIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnknownSubscriptionIdException.java index f7aa6b07f0f93..8b3f59ae3562c 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnknownSubscriptionIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnknownSubscriptionIdException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This exception indicates that the client sent an invalid or outdated SubscriptionId */ +@InterfaceAudience.Public public class UnknownSubscriptionIdException extends ApiException { public UnknownSubscriptionIdException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnknownTopicIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnknownTopicIdException.java index e5023eb7cdbb3..642a9cf2f7937 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnknownTopicIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnknownTopicIdException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class UnknownTopicIdException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnknownTopicOrPartitionException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnknownTopicOrPartitionException.java index 6d1094590ff34..51ae12f08a7bd 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnknownTopicOrPartitionException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnknownTopicOrPartitionException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This topic/partition doesn't exist. * This exception is used in contexts where a topic doesn't seem to exist based on possibly stale metadata. @@ -23,6 +26,7 @@ * * @see InvalidTopicException */ +@InterfaceAudience.Public public class UnknownTopicOrPartitionException extends InvalidMetadataException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnreleasedInstanceIdException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnreleasedInstanceIdException.java index d62df8bd60b2d..afa7744edc89a 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnreleasedInstanceIdException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnreleasedInstanceIdException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class UnreleasedInstanceIdException extends ApiException { public UnreleasedInstanceIdException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnstableOffsetCommitException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnstableOffsetCommitException.java index c89d717e5bbcf..6f4621778bd58 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnstableOffsetCommitException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnstableOffsetCommitException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Exception thrown when there are unstable offsets for the requested topic partitions. */ +@InterfaceAudience.Public public class UnstableOffsetCommitException extends RetriableException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedAssignorException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedAssignorException.java index f16441783d3d1..e80a1896a46a5 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedAssignorException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedAssignorException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class UnsupportedAssignorException extends ApiException { public UnsupportedAssignorException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedByAuthenticationException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedByAuthenticationException.java index 40f357c5e2e0b..8e8f0d0b17fb1 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedByAuthenticationException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedByAuthenticationException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Authentication mechanism does not support the requested function. */ +@InterfaceAudience.Public public class UnsupportedByAuthenticationException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedCompressionTypeException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedCompressionTypeException.java index 29ffe1b900e23..dae897c4aa40d 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedCompressionTypeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedCompressionTypeException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The requesting client does not support the compression type of given partition. */ +@InterfaceAudience.Public public class UnsupportedCompressionTypeException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedEndpointTypeException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedEndpointTypeException.java index e786e740d9552..1e6b449761e79 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedEndpointTypeException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedEndpointTypeException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class UnsupportedEndpointTypeException extends ApiException { public UnsupportedEndpointTypeException(String message) { super(message); diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedForMessageFormatException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedForMessageFormatException.java index 03add5c4ffce8..c3e4381af6337 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedForMessageFormatException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedForMessageFormatException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The message format version does not support the requested function. For example, if idempotence is * requested and the topic is using a message format older than 0.11.0.0, then this error will be returned. */ +@InterfaceAudience.Public public class UnsupportedForMessageFormatException extends InvalidConfigurationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedSaslMechanismException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedSaslMechanismException.java index 4db4aee98c07c..93c4e6acd9b4e 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedSaslMechanismException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedSaslMechanismException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This exception indicates that the SASL mechanism requested by the client * is not enabled on the broker. */ +@InterfaceAudience.Public public class UnsupportedSaslMechanismException extends AuthenticationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedVersionException.java b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedVersionException.java index 00da3a1b2b8b2..1b9eadb2383aa 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedVersionException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/UnsupportedVersionException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** @@ -28,6 +31,7 @@ * is raised from {@link org.apache.kafka.clients.consumer.KafkaConsumer#offsetsForTimes(Map)}, it would * be possible to revert to alternative logic to set the consumer's position. */ +@InterfaceAudience.Public public class UnsupportedVersionException extends InvalidConfigurationException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/VoterNotFoundException.java b/clients/src/main/java/org/apache/kafka/common/errors/VoterNotFoundException.java index f4a172267ab4e..01871911fe50a 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/VoterNotFoundException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/VoterNotFoundException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class VoterNotFoundException extends ApiException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/errors/WakeupException.java b/clients/src/main/java/org/apache/kafka/common/errors/WakeupException.java index f8ae8403a5d9f..f8535ba03fa9a 100644 --- a/clients/src/main/java/org/apache/kafka/common/errors/WakeupException.java +++ b/clients/src/main/java/org/apache/kafka/common/errors/WakeupException.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.errors; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Exception used to indicate preemption of a blocking operation by an external thread. @@ -24,6 +26,7 @@ * can be used to break out of an active {@link org.apache.kafka.clients.consumer.KafkaConsumer#poll(java.time.Duration)}, * which would raise an instance of this exception. */ +@InterfaceAudience.Public public class WakeupException extends KafkaException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/header/Header.java b/clients/src/main/java/org/apache/kafka/common/header/Header.java index e1d0aa00a4417..bf3f8ccdfd951 100644 --- a/clients/src/main/java/org/apache/kafka/common/header/Header.java +++ b/clients/src/main/java/org/apache/kafka/common/header/Header.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.header; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A header is a key-value pair. */ +@InterfaceAudience.Public public interface Header { /** diff --git a/clients/src/main/java/org/apache/kafka/common/header/Headers.java b/clients/src/main/java/org/apache/kafka/common/header/Headers.java index 9cce54a5c5cc5..f79b12d51968d 100644 --- a/clients/src/main/java/org/apache/kafka/common/header/Headers.java +++ b/clients/src/main/java/org/apache/kafka/common/header/Headers.java @@ -14,14 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.header; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * A mutable ordered collection of {@link Header} objects. Note that multiple headers may have the same {@link Header#key() key}. *

    * The order of headers is preserved in the order they were added. */ +@InterfaceAudience.Public public interface Headers extends Iterable

    { /** diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/CompoundStat.java b/clients/src/main/java/org/apache/kafka/common/metrics/CompoundStat.java index f2a7ac63bae3e..f1d8faedc39b9 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/CompoundStat.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/CompoundStat.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.List; @@ -24,6 +26,7 @@ * A compound stat is a stat where a single measurement and associated data structure feeds many metrics. This is the * example for a histogram which has many associated percentiles. */ +@InterfaceAudience.Public public interface CompoundStat extends Stat { List stats(); diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/Gauge.java b/clients/src/main/java/org/apache/kafka/common/metrics/Gauge.java index cad640eea2b9a..fd9738ba5a588 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/Gauge.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/Gauge.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A gauge metric is an instantaneous reading of a particular value. */ @FunctionalInterface +@InterfaceAudience.Public public interface Gauge extends MetricValueProvider { } diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/JmxReporter.java b/clients/src/main/java/org/apache/kafka/common/metrics/JmxReporter.java index 017a0d39bd59c..4efd3fd4b88aa 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/JmxReporter.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/JmxReporter.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.utils.internals.Sanitizer; @@ -48,6 +49,7 @@ /** * Register metrics in JMX as dynamic mbeans based on the metric names */ +@InterfaceAudience.Public public class JmxReporter implements MetricsReporter { public static final String METRICS_CONFIG_PREFIX = "metrics.jmx."; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetric.java b/clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetric.java index 3834c8706032c..827b38978a7ff 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetric.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetric.java @@ -18,10 +18,13 @@ import org.apache.kafka.common.Metric; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.utils.Time; import java.util.Objects; +@InterfaceAudience.Public public final class KafkaMetric implements Metric { private final MetricName metricName; @@ -39,6 +42,7 @@ public final class KafkaMetric implements Metric { * @param config The configuration of the metric * @param time The time instance to use with the metrics */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public KafkaMetric(Object lock, MetricName metricName, MetricValueProvider valueProvider, MetricConfig config, Time time) { this.metricName = metricName; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetricsContext.java b/clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetricsContext.java index 5fafa144956b5..020d1bfbc916c 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetricsContext.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetricsContext.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -23,6 +26,7 @@ /** * An implementation of MetricsContext, it encapsulates required metrics context properties for Kafka services and clients */ +@InterfaceAudience.Public public class KafkaMetricsContext implements MetricsContext { /** * Client or Service's contextLabels map. diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/Measurable.java b/clients/src/main/java/org/apache/kafka/common/metrics/Measurable.java index 58b9caa06ed9e..c5709f89cda8a 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/Measurable.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/Measurable.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A measurable quantity that can be registered as a metric */ +@InterfaceAudience.Public public interface Measurable extends MetricValueProvider { /** diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/MeasurableStat.java b/clients/src/main/java/org/apache/kafka/common/metrics/MeasurableStat.java index 035449e7363a2..916d037b2b228 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/MeasurableStat.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/MeasurableStat.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A MeasurableStat is a {@link Stat} that is also {@link Measurable} (i.e. can produce a single floating point value). * This is the interface used for most of the simple statistics such as {@link org.apache.kafka.common.metrics.stats.Avg}, * {@link org.apache.kafka.common.metrics.stats.Max}, {@link org.apache.kafka.common.metrics.stats.CumulativeCount}, etc. */ +@InterfaceAudience.Public public interface MeasurableStat extends Stat, Measurable { } diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/MetricConfig.java b/clients/src/main/java/org/apache/kafka/common/metrics/MetricConfig.java index a77cc9309bd20..9681071f8d71a 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/MetricConfig.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/MetricConfig.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -23,6 +26,7 @@ /** * Configuration values for metrics */ +@InterfaceAudience.Public public class MetricConfig { public static final int DEFAULT_NUM_SAMPLES = 2; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/MetricValueProvider.java b/clients/src/main/java/org/apache/kafka/common/metrics/MetricValueProvider.java index e4d751c2bb2a0..4740fb8384c55 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/MetricValueProvider.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/MetricValueProvider.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Super-interface for {@link Measurable} or {@link Gauge} that provides * metric values. */ @FunctionalInterface +@InterfaceAudience.Public public interface MetricValueProvider { /** diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java b/clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java index 8cbd9996ed480..0cdfef3bd18b6 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java @@ -18,6 +18,8 @@ import org.apache.kafka.common.MetricName; import org.apache.kafka.common.MetricNameTemplate; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.metrics.internals.MetricsUtils; import org.apache.kafka.common.utils.Time; import org.apache.kafka.common.utils.internals.KafkaThread; @@ -67,6 +69,7 @@ * sensor.record(messageSize); * */ +@InterfaceAudience.Public public final class Metrics implements Closeable { private final MetricConfig config; @@ -90,6 +93,7 @@ public Metrics() { * Create a metrics repository with no metric reporters and default configuration. * Expiration of Sensors is disabled. */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public Metrics(Time time) { this(new MetricConfig(), new ArrayList<>(0), time); } @@ -98,6 +102,7 @@ public Metrics(Time time) { * Create a metrics repository with no metric reporters and the given default configuration. * Expiration of Sensors is disabled. */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public Metrics(MetricConfig defaultConfig, Time time) { this(defaultConfig, new ArrayList<>(0), time); } @@ -119,6 +124,7 @@ public Metrics(MetricConfig defaultConfig) { * @param reporters The metrics reporters * @param time The time instance to use with the metrics */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public Metrics(MetricConfig defaultConfig, List reporters, Time time) { this(defaultConfig, reporters, time, false); } @@ -131,6 +137,7 @@ public Metrics(MetricConfig defaultConfig, List reporters, Time * @param time The time instance to use with the metrics * @param metricsContext The metricsContext to initialize metrics reporter with */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public Metrics(MetricConfig defaultConfig, List reporters, Time time, MetricsContext metricsContext) { this(defaultConfig, reporters, time, false, metricsContext); } @@ -142,6 +149,7 @@ public Metrics(MetricConfig defaultConfig, List reporters, Time * @param time The time instance to use with the metrics * @param enableExpiration true if the metrics instance can garbage collect inactive sensors, false otherwise */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public Metrics(MetricConfig defaultConfig, List reporters, Time time, boolean enableExpiration) { this(defaultConfig, reporters, time, enableExpiration, new KafkaMetricsContext("")); } @@ -155,6 +163,7 @@ public Metrics(MetricConfig defaultConfig, List reporters, Time * @param enableExpiration true if the metrics instance can garbage collect inactive sensors, false otherwise * @param metricsContext The metricsContext to initialize metrics reporter with */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public Metrics(MetricConfig defaultConfig, List reporters, Time time, boolean enableExpiration, MetricsContext metricsContext) { this.config = defaultConfig; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/MetricsContext.java b/clients/src/main/java/org/apache/kafka/common/metrics/MetricsContext.java index f9ee6badfa05e..54b50d3233687 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/MetricsContext.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/MetricsContext.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** @@ -40,6 +43,7 @@ *
    connect.kafka.cluster.id, connect.group.id
    * */ +@InterfaceAudience.Public public interface MetricsContext { /* predefined fields */ String NAMESPACE = "_namespace"; // metrics namespace, formerly jmx prefix diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/MetricsReporter.java b/clients/src/main/java/org/apache/kafka/common/metrics/MetricsReporter.java index a46105def920c..1b90662cab0be 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/MetricsReporter.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/MetricsReporter.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.metrics; import org.apache.kafka.common.Reconfigurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import java.util.List; @@ -28,6 +29,7 @@ *

    * Implement {@link org.apache.kafka.common.ClusterResourceListener} to receive cluster metadata once it's available. Please see the class documentation for ClusterResourceListener for more information. */ +@InterfaceAudience.Public public interface MetricsReporter extends Reconfigurable, AutoCloseable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/Monitorable.java b/clients/src/main/java/org/apache/kafka/common/metrics/Monitorable.java index fa5a292bf3168..e7444ea8cda45 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/Monitorable.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/Monitorable.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Plugins can implement this interface to register their own metrics. */ +@InterfaceAudience.Public public interface Monitorable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/PluginMetrics.java b/clients/src/main/java/org/apache/kafka/common/metrics/PluginMetrics.java index 5edd9462b80fd..9633e90745f7b 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/PluginMetrics.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/PluginMetrics.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.LinkedHashMap; @@ -24,6 +26,7 @@ * This allows plugins to register metrics and sensors. * Any metrics registered by the plugin are automatically removed when the plugin closed. */ +@InterfaceAudience.Public public interface PluginMetrics { /** diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/Quota.java b/clients/src/main/java/org/apache/kafka/common/metrics/Quota.java index e4141339439f1..ac07275da1674 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/Quota.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/Quota.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An upper or lower bound for metrics */ +@InterfaceAudience.Public public final class Quota { private final boolean upper; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/QuotaViolationException.java b/clients/src/main/java/org/apache/kafka/common/metrics/QuotaViolationException.java index 7068d3115d795..51a9eda5bed1e 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/QuotaViolationException.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/QuotaViolationException.java @@ -14,13 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Thrown when a sensor records a value that causes a metric to go outside the bounds configured as its quota */ +@InterfaceAudience.Public public class QuotaViolationException extends KafkaException { private static final long serialVersionUID = 1L; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/Sensor.java b/clients/src/main/java/org/apache/kafka/common/metrics/Sensor.java index a5da5294b4d4d..0062dba1db851 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/Sensor.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/Sensor.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.metrics; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.CompoundStat.NamedMeasurable; import org.apache.kafka.common.metrics.stats.TokenBucket; import org.apache.kafka.common.utils.Time; @@ -40,6 +41,7 @@ * message size would record a sequence of message sizes using the {@link #record(double)} api and would maintain a set * of metrics about request sizes such as the average or max. */ +@InterfaceAudience.Public public final class Sensor { private final Metrics registry; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/Stat.java b/clients/src/main/java/org/apache/kafka/common/metrics/Stat.java index fa5aa1aec3bed..662ab1916d32c 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/Stat.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/Stat.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A Stat is a quantity such as average, max, etc that is computed off the stream of updates to a sensor */ +@InterfaceAudience.Public public interface Stat { /** diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Avg.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Avg.java index f7c20eb15822d..ed16f0a4662ac 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Avg.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Avg.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MetricConfig; import java.util.List; @@ -23,6 +24,7 @@ /** * A {@link SampledStat} that maintains a simple average over its samples. */ +@InterfaceAudience.Public public class Avg extends SampledStat { public Avg() { diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/CumulativeCount.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/CumulativeCount.java index 85591b5cf726f..f95c312bd018a 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/CumulativeCount.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/CumulativeCount.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MetricConfig; /** @@ -26,6 +27,7 @@ * {@link CumulativeCount#record(MetricConfig, double, long)} invocations, * instead of summing the recorded values. */ +@InterfaceAudience.Public public class CumulativeCount extends CumulativeSum { @Override public void record(final MetricConfig config, final double value, final long timeMs) { diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/CumulativeSum.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/CumulativeSum.java index 6726b9d0d5485..dcb61bf67a69e 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/CumulativeSum.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/CumulativeSum.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MeasurableStat; import org.apache.kafka.common.metrics.MetricConfig; @@ -25,6 +26,7 @@ * * See also {@link CumulativeCount} if you just want to increment the value by 1 on each recording. */ +@InterfaceAudience.Public public class CumulativeSum implements MeasurableStat { private double total; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequencies.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequencies.java index b802d3190a377..cfa9f513d82ee 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequencies.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequencies.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.metrics.stats; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.CompoundStat; import org.apache.kafka.common.metrics.MetricConfig; import org.apache.kafka.common.metrics.stats.Histogram.BinScheme; @@ -40,6 +41,7 @@ * object is a {@link CompoundStat}, and so it can be {@link org.apache.kafka.common.metrics.Sensor#add(CompoundStat) * added directly to a Sensor} so the metrics are created automatically. */ +@InterfaceAudience.Public public class Frequencies extends SampledStat implements CompoundStat { /** diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequency.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequency.java index 5222219f92e1f..6385df549404e 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequency.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Frequency.java @@ -14,14 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.common.metrics.stats; +package org.apache.kafka.common.metrics.stats; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Definition of a frequency metric used in a {@link Frequencies} compound statistic. */ +@InterfaceAudience.Public public class Frequency { private final MetricName name; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Histogram.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Histogram.java index aa7de6fa6c931..3f2a3a955866b 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Histogram.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Histogram.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; +@InterfaceAudience.Public public class Histogram { private final BinScheme binScheme; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Max.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Max.java index 6521a42324e71..0978e88819751 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Max.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Max.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MetricConfig; import java.util.List; @@ -23,6 +24,7 @@ /** * A {@link SampledStat} that gives the max over its samples. */ +@InterfaceAudience.Public public final class Max extends SampledStat { public Max() { diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Meter.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Meter.java index d97a7d39e6215..e041cb4438584 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Meter.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Meter.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics.stats; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.CompoundStat; import org.apache.kafka.common.metrics.MetricConfig; @@ -24,10 +26,10 @@ import java.util.List; import java.util.concurrent.TimeUnit; - /** * A compound stat that includes a rate metric and a cumulative total metric. */ +@InterfaceAudience.Public public class Meter implements CompoundStat { private final MetricName rateMetricName; private final MetricName totalMetricName; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Min.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Min.java index 05f20190634f5..20d9aa2892ae2 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Min.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Min.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MetricConfig; import java.util.List; @@ -23,6 +24,7 @@ /** * A {@link SampledStat} that gives the min over its samples. */ +@InterfaceAudience.Public public class Min extends SampledStat { public Min() { diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentile.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentile.java index f8ae3a17601a9..6d71796ff5cd6 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentile.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentile.java @@ -14,10 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.metrics.stats; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; +@InterfaceAudience.Public public class Percentile { private final MetricName name; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentiles.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentiles.java index 5cb1da4f65376..1655d95bc0850 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentiles.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentiles.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.CompoundStat; import org.apache.kafka.common.metrics.MetricConfig; import org.apache.kafka.common.metrics.stats.Histogram.BinScheme; @@ -31,6 +32,7 @@ /** * A compound stat that reports one or more percentiles */ +@InterfaceAudience.Public public class Percentiles extends SampledStat implements CompoundStat { private static final Logger log = LoggerFactory.getLogger(Percentiles.class); diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Rate.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Rate.java index 17a4f6b113921..b62b74d363bec 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Rate.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Rate.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MeasurableStat; import org.apache.kafka.common.metrics.MetricConfig; @@ -30,6 +31,7 @@ * however, to record the rate of occurrences (e.g. the count of values measured over the time interval) or other such * values. */ +@InterfaceAudience.Public public class Rate implements MeasurableStat { protected final TimeUnit unit; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/SampledStat.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/SampledStat.java index 2cc6777c33371..e04727b736819 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/SampledStat.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/SampledStat.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MeasurableStat; import org.apache.kafka.common.metrics.MetricConfig; @@ -33,6 +34,7 @@ * * Subclasses of this class define different statistics measured using this basic pattern. */ +@InterfaceAudience.Public public abstract class SampledStat implements MeasurableStat { private final double initialValue; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/SimpleRate.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/SimpleRate.java index a632f0254d6b0..074ea7e789e9d 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/SimpleRate.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/SimpleRate.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MetricConfig; /** @@ -28,6 +29,7 @@ * an artificially high rate when the gap between readings * is close to 0. */ +@InterfaceAudience.Public public class SimpleRate extends Rate { @Override diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/TokenBucket.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/TokenBucket.java index b2fe5a6983a16..9f6de5c2a3e97 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/TokenBucket.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/TokenBucket.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MeasurableStat; import org.apache.kafka.common.metrics.MetricConfig; import org.apache.kafka.common.metrics.Quota; @@ -56,6 +57,7 @@ * A burst of 560 brings the amount of credits to -60. One must wait 12s (-(-60)/5) to refill the * bucket to zero. */ +@InterfaceAudience.Public public class TokenBucket implements MeasurableStat { private final TimeUnit unit; private double tokens; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Value.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Value.java index deb81c7b7cb9a..1acf257f96445 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Value.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/Value.java @@ -16,12 +16,14 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MeasurableStat; import org.apache.kafka.common.metrics.MetricConfig; /** * An instantaneous value. */ +@InterfaceAudience.Public public class Value implements MeasurableStat { private double value = 0; diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/WindowedCount.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/WindowedCount.java index 825f404ef02d1..a7bb8f1283345 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/WindowedCount.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/WindowedCount.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MetricConfig; /** @@ -27,6 +28,7 @@ * * See also {@link CumulativeCount} for a non-sampled version of this metric. */ +@InterfaceAudience.Public public class WindowedCount extends WindowedSum { @Override protected void update(Sample sample, MetricConfig config, double value, long now) { diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/stats/WindowedSum.java b/clients/src/main/java/org/apache/kafka/common/metrics/stats/WindowedSum.java index 14aa5620fcc44..5a8067c0e815d 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/stats/WindowedSum.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/stats/WindowedSum.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.metrics.stats; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MetricConfig; import java.util.List; @@ -26,6 +27,7 @@ * * See also {@link WindowedCount} if you want to increment the value by 1 on each recording. */ +@InterfaceAudience.Public public class WindowedSum extends SampledStat { public WindowedSum() { diff --git a/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaAlteration.java b/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaAlteration.java index 88670ce8ddc05..43af2f33c5b56 100644 --- a/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaAlteration.java +++ b/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaAlteration.java @@ -17,12 +17,15 @@ package org.apache.kafka.common.quota; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; import java.util.Objects; /** * Describes a configuration alteration to be made to a client quota entity. */ +@InterfaceAudience.Public public class ClientQuotaAlteration { public static class Op { diff --git a/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaEntity.java b/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaEntity.java index d6dffdbeb049c..e882861aff930 100644 --- a/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaEntity.java +++ b/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaEntity.java @@ -17,12 +17,15 @@ package org.apache.kafka.common.quota; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; import java.util.Objects; /** * Describes a client quota entity, which is a mapping of entity types to their names. */ +@InterfaceAudience.Public public class ClientQuotaEntity { private final Map entries; diff --git a/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaFilter.java b/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaFilter.java index 0532c66580ab5..f394ede0f0895 100644 --- a/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaFilter.java +++ b/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaFilter.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.quota; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; import java.util.List; import java.util.Objects; @@ -24,6 +26,7 @@ /** * Describes a client quota entity filter. */ +@InterfaceAudience.Public public class ClientQuotaFilter { private final Collection components; diff --git a/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaFilterComponent.java b/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaFilterComponent.java index 9fc8f72fa9f23..28b221d83d5b2 100644 --- a/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaFilterComponent.java +++ b/clients/src/main/java/org/apache/kafka/common/quota/ClientQuotaFilterComponent.java @@ -17,12 +17,15 @@ package org.apache.kafka.common.quota; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import java.util.Optional; /** * Describes a component for applying a client quota filter. */ +@InterfaceAudience.Public public class ClientQuotaFilterComponent { private final String entityType; diff --git a/clients/src/main/java/org/apache/kafka/common/record/TimestampType.java b/clients/src/main/java/org/apache/kafka/common/record/TimestampType.java index becde9dc8530f..c1742594812b2 100644 --- a/clients/src/main/java/org/apache/kafka/common/record/TimestampType.java +++ b/clients/src/main/java/org/apache/kafka/common/record/TimestampType.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.record; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.NoSuchElementException; /** * The timestamp type of the records. */ +@InterfaceAudience.Public public enum TimestampType { NO_TIMESTAMP_TYPE(-1, "NoTimestampType"), CREATE_TIME(0, "CreateTime"), LOG_APPEND_TIME(1, "LogAppendTime"); diff --git a/clients/src/main/java/org/apache/kafka/common/resource/PatternType.java b/clients/src/main/java/org/apache/kafka/common/resource/PatternType.java index 74d9ad1f0fc87..adc22ded3c3c7 100644 --- a/clients/src/main/java/org/apache/kafka/common/resource/PatternType.java +++ b/clients/src/main/java/org/apache/kafka/common/resource/PatternType.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.resource; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -26,6 +28,7 @@ /** * Resource pattern type. */ +@InterfaceAudience.Public public enum PatternType { /** * Represents any PatternType which this client cannot understand, perhaps because this client is too old. diff --git a/clients/src/main/java/org/apache/kafka/common/resource/Resource.java b/clients/src/main/java/org/apache/kafka/common/resource/Resource.java index 9b9ca27935592..33731e3e7af90 100644 --- a/clients/src/main/java/org/apache/kafka/common/resource/Resource.java +++ b/clients/src/main/java/org/apache/kafka/common/resource/Resource.java @@ -17,11 +17,14 @@ package org.apache.kafka.common.resource; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Represents a cluster resource with a tuple of (type, name). */ +@InterfaceAudience.Public public class Resource { private final ResourceType resourceType; private final String name; diff --git a/clients/src/main/java/org/apache/kafka/common/resource/ResourcePattern.java b/clients/src/main/java/org/apache/kafka/common/resource/ResourcePattern.java index 70c479588a856..ad4a6357a9c9a 100644 --- a/clients/src/main/java/org/apache/kafka/common/resource/ResourcePattern.java +++ b/clients/src/main/java/org/apache/kafka/common/resource/ResourcePattern.java @@ -17,12 +17,15 @@ package org.apache.kafka.common.resource; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Represents a pattern that is used by ACLs to match zero or more * {@link org.apache.kafka.common.resource.Resource Resources}. */ +@InterfaceAudience.Public public class ResourcePattern { /** * A special literal resource name that corresponds to 'all resources of a certain type'. diff --git a/clients/src/main/java/org/apache/kafka/common/resource/ResourcePatternFilter.java b/clients/src/main/java/org/apache/kafka/common/resource/ResourcePatternFilter.java index 93f3061cc46bf..5374bf8916c79 100644 --- a/clients/src/main/java/org/apache/kafka/common/resource/ResourcePatternFilter.java +++ b/clients/src/main/java/org/apache/kafka/common/resource/ResourcePatternFilter.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.resource; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import static org.apache.kafka.common.resource.ResourcePattern.WILDCARD_RESOURCE; @@ -24,6 +26,7 @@ /** * Represents a filter that can match {@link ResourcePattern}. */ +@InterfaceAudience.Public public class ResourcePatternFilter { /** * Matches any resource pattern. diff --git a/clients/src/main/java/org/apache/kafka/common/resource/ResourceType.java b/clients/src/main/java/org/apache/kafka/common/resource/ResourceType.java index 289000e99e87a..8d110ca1af886 100644 --- a/clients/src/main/java/org/apache/kafka/common/resource/ResourceType.java +++ b/clients/src/main/java/org/apache/kafka/common/resource/ResourceType.java @@ -17,12 +17,15 @@ package org.apache.kafka.common.resource; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.HashMap; import java.util.Locale; /** * Represents a type of resource which an ACL can be applied to. */ +@InterfaceAudience.Public public enum ResourceType { /** * Represents any ResourceType which this client cannot understand, diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/AuthenticateCallbackHandler.java b/clients/src/main/java/org/apache/kafka/common/security/auth/AuthenticateCallbackHandler.java index 8951d3a589367..6409c088acd6d 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/AuthenticateCallbackHandler.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/AuthenticateCallbackHandler.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; import java.util.Map; @@ -26,6 +28,7 @@ /* * Callback handler for SASL-based authentication */ +@InterfaceAudience.Public public interface AuthenticateCallbackHandler extends CallbackHandler { /** diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/AuthenticationContext.java b/clients/src/main/java/org/apache/kafka/common/security/auth/AuthenticationContext.java index a8abea858960d..d1bbf7914241d 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/AuthenticationContext.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/AuthenticationContext.java @@ -14,16 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; -import java.net.InetAddress; +import org.apache.kafka.common.annotation.InterfaceAudience; +import java.net.InetAddress; /** * An object representing contextual information from the authentication session. See * {@link PlaintextAuthenticationContext}, {@link SaslAuthenticationContext} * and {@link SslAuthenticationContext}. This class is only used in the broker. */ +@InterfaceAudience.Public public interface AuthenticationContext { /** * Underlying security protocol of the authentication session. diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipal.java b/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipal.java index 6f074c2cec4cf..4b3ae84624230 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipal.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipal.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.security.Principal; import static java.util.Objects.requireNonNull; @@ -40,6 +42,7 @@ * authorizer which is capable of using the additional group information. * */ +@InterfaceAudience.Public public class KafkaPrincipal implements Principal { public static final String USER_TYPE = "User"; public static final KafkaPrincipal ANONYMOUS = new KafkaPrincipal(KafkaPrincipal.USER_TYPE, "ANONYMOUS"); diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipalBuilder.java b/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipalBuilder.java index 92be58ea2dcf0..38b1c50e42508 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipalBuilder.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipalBuilder.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Pluggable principal builder interface which supports both SSL authentication through * {@link SslAuthenticationContext} and SASL through {@link SaslAuthenticationContext}. @@ -24,6 +27,7 @@ * interfaces are respected if implemented. Additionally, implementations must provide a * default no-arg constructor. */ +@InterfaceAudience.Public public interface KafkaPrincipalBuilder extends KafkaPrincipalSerde { /** * Build a kafka principal from the authentication context. diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipalSerde.java b/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipalSerde.java index c32f7f5a1d8da..0b16238ef3f8e 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipalSerde.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/KafkaPrincipalSerde.java @@ -16,12 +16,14 @@ */ package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; /** * Serializer/Deserializer interface for {@link KafkaPrincipal} for the purpose of inter-broker forwarding. * Any serialization/deserialization failure should raise a {@link SerializationException} to be consistent. */ +@InterfaceAudience.Public public interface KafkaPrincipalSerde { /** diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/Login.java b/clients/src/main/java/org/apache/kafka/common/security/auth/Login.java index eda5e7a225af1..8e5026c59341b 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/Login.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/Login.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; import javax.security.auth.Subject; @@ -26,6 +29,7 @@ /** * Login interface for authentication. */ +@InterfaceAudience.Public public interface Login { /** diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/PlaintextAuthenticationContext.java b/clients/src/main/java/org/apache/kafka/common/security/auth/PlaintextAuthenticationContext.java index a111f21ec1302..c9970ef1ed615 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/PlaintextAuthenticationContext.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/PlaintextAuthenticationContext.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.net.InetAddress; +@InterfaceAudience.Public public class PlaintextAuthenticationContext implements AuthenticationContext { private final InetAddress clientAddress; private final String listenerName; diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/SaslAuthenticationContext.java b/clients/src/main/java/org/apache/kafka/common/security/auth/SaslAuthenticationContext.java index db67b4bac4046..c74ba106a33d9 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/SaslAuthenticationContext.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/SaslAuthenticationContext.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.net.InetAddress; import java.util.Optional; import javax.net.ssl.SSLSession; import javax.security.sasl.SaslServer; +@InterfaceAudience.Public public class SaslAuthenticationContext implements AuthenticationContext { private final SaslServer server; private final SecurityProtocol securityProtocol; diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/SaslExtensions.java b/clients/src/main/java/org/apache/kafka/common/security/auth/SaslExtensions.java index 3210c859baa27..b16f320816146 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/SaslExtensions.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/SaslExtensions.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collections; import java.util.Map; import java.util.Set; @@ -46,6 +49,7 @@ * * See KAFKA-14062 for more detail. */ +@InterfaceAudience.Public public class SaslExtensions { private final Map extensionsMap; diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/SaslExtensionsCallback.java b/clients/src/main/java/org/apache/kafka/common/security/auth/SaslExtensionsCallback.java index f2010afda67e4..d0eccfadb2d99 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/SaslExtensionsCallback.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/SaslExtensionsCallback.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import javax.security.auth.callback.Callback; @@ -25,6 +27,7 @@ * Optional callback used for SASL mechanisms if any extensions need to be set * in the SASL exchange. */ +@InterfaceAudience.Public public class SaslExtensionsCallback implements Callback { private SaslExtensions extensions = SaslExtensions.empty(); diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/SecurityProtocol.java b/clients/src/main/java/org/apache/kafka/common/security/auth/SecurityProtocol.java index f48a1943d2e37..a299044df5b9f 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/SecurityProtocol.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/SecurityProtocol.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -23,6 +26,7 @@ import java.util.Locale; import java.util.Map; +@InterfaceAudience.Public public enum SecurityProtocol { /** Un-authenticated, non-encrypted channel */ PLAINTEXT(0, "PLAINTEXT"), diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/SecurityProviderCreator.java b/clients/src/main/java/org/apache/kafka/common/security/auth/SecurityProviderCreator.java index a22e4dbb2c942..3b7abb9fb6f43 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/SecurityProviderCreator.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/SecurityProviderCreator.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.security.Provider; import java.util.Map; @@ -24,6 +26,7 @@ /** * An interface for generating security providers. */ +@InterfaceAudience.Public public interface SecurityProviderCreator extends Configurable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/SslAuthenticationContext.java b/clients/src/main/java/org/apache/kafka/common/security/auth/SslAuthenticationContext.java index df98173292d0a..d9cfcc82a7ec0 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/SslAuthenticationContext.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/SslAuthenticationContext.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.net.InetAddress; import javax.net.ssl.SSLSession; +@InterfaceAudience.Public public class SslAuthenticationContext implements AuthenticationContext { private final SSLSession session; private final InetAddress clientAddress; diff --git a/clients/src/main/java/org/apache/kafka/common/security/auth/SslEngineFactory.java b/clients/src/main/java/org/apache/kafka/common/security/auth/SslEngineFactory.java index 42e0ab6401cb2..989ceb48292d6 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/auth/SslEngineFactory.java +++ b/clients/src/main/java/org/apache/kafka/common/security/auth/SslEngineFactory.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.auth; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.io.Closeable; import java.security.KeyStore; @@ -32,6 +34,7 @@ * to be replaced with a custom provider. In scenarios where only the configuration mechanism for SSL engines * need to be updated, this interface provides a convenient method for overriding the default implementation. */ +@InterfaceAudience.Public public interface SslEngineFactory extends Configurable, Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/BrokerJwtValidator.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/BrokerJwtValidator.java index 9a3c6810640d1..e0c84cd30a0bf 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/BrokerJwtValidator.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/BrokerJwtValidator.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.security.oauthbearer.internals.secured.BasicOAuthBearerToken; import org.apache.kafka.common.security.oauthbearer.internals.secured.ClaimValidationUtils; @@ -93,6 +94,7 @@ * * */ +@InterfaceAudience.Public public class BrokerJwtValidator implements JwtValidator { private static final Logger log = LoggerFactory.getLogger(BrokerJwtValidator.class); diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/ClientCredentialsJwtRetriever.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/ClientCredentialsJwtRetriever.java index ab6655c4e2de7..f5a825b055136 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/ClientCredentialsJwtRetriever.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/ClientCredentialsJwtRetriever.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.security.oauthbearer.internals.secured.ClientCredentialsRequestFormatterFactory; import org.apache.kafka.common.security.oauthbearer.internals.secured.ConfigurationUtils; import org.apache.kafka.common.security.oauthbearer.internals.secured.HttpJwtRetriever; @@ -92,6 +94,7 @@ * sasl.oauthbearer.token.endpoint.url=https://example.com/oauth2/v1/token * */ +@InterfaceAudience.Public public class ClientCredentialsJwtRetriever implements JwtRetriever { private static final Logger LOG = LoggerFactory.getLogger(ClientCredentialsJwtRetriever.class); @@ -103,6 +106,7 @@ public ClientCredentialsJwtRetriever() { this(Time.SYSTEM); } + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public ClientCredentialsJwtRetriever(Time time) { this.time = time; } diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/ClientJwtValidator.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/ClientJwtValidator.java index 6d3ce1a807993..cf68019e50a68 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/ClientJwtValidator.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/ClientJwtValidator.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.oauthbearer.internals.secured.BasicOAuthBearerToken; import org.apache.kafka.common.security.oauthbearer.internals.secured.ClaimValidationUtils; import org.apache.kafka.common.security.oauthbearer.internals.secured.ConfigurationUtils; @@ -57,6 +58,7 @@ * */ +@InterfaceAudience.Public public class ClientJwtValidator implements JwtValidator { private static final Logger log = LoggerFactory.getLogger(ClientJwtValidator.class); diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/DefaultJwtRetriever.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/DefaultJwtRetriever.java index 67de3703883bd..94bc8df365de1 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/DefaultJwtRetriever.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/DefaultJwtRetriever.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.oauthbearer.internals.secured.ClientAssertionRequestFormatter; import org.apache.kafka.common.security.oauthbearer.internals.secured.ClientSecretRequestFormatter; import org.apache.kafka.common.security.oauthbearer.internals.secured.ConfigurationUtils; @@ -52,6 +53,7 @@ * The configuration required by the individual {@code JwtRetriever} classes will likely differ. Please refer to the * official Apache Kafka documentation for more information on these, and related configuration. */ +@InterfaceAudience.Public public class DefaultJwtRetriever implements JwtRetriever { private static final Logger LOG = LoggerFactory.getLogger(DefaultJwtRetriever.class); diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/DefaultJwtValidator.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/DefaultJwtValidator.java index 3d5710fb64c2e..13d886648da75 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/DefaultJwtValidator.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/DefaultJwtValidator.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.config.SaslConfigs; import org.apache.kafka.common.security.oauthbearer.internals.secured.CloseableVerificationKeyResolver; import org.apache.kafka.common.security.oauthbearer.internals.secured.ConfigurationUtils; @@ -37,6 +39,7 @@ * of the {@link VerificationKeyResolver}: if it's present, a {@link BrokerJwtValidator} is * created, otherwise a {@link ClientJwtValidator} is created. */ +@InterfaceAudience.Public public class DefaultJwtValidator implements JwtValidator { private final Optional verificationKeyResolver; @@ -47,6 +50,7 @@ public DefaultJwtValidator() { this.verificationKeyResolver = Optional.empty(); } + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal CloseableVerificationKeyResolver — pending KIP review to promote the type or refactor") public DefaultJwtValidator(CloseableVerificationKeyResolver verificationKeyResolver) { this.verificationKeyResolver = Optional.of(verificationKeyResolver); } diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/FileJwtRetriever.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/FileJwtRetriever.java index eeaee1cfb53e3..5c01e245ab1cf 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/FileJwtRetriever.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/FileJwtRetriever.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.oauthbearer.internals.secured.CachedFile; import org.apache.kafka.common.security.oauthbearer.internals.secured.ConfigurationUtils; @@ -34,6 +35,7 @@ * FileJwtRetriever is an {@link JwtRetriever} that will load the contents * of a file, interpreting them as a JWT access key in the serialized form. */ +@InterfaceAudience.Public public class FileJwtRetriever implements JwtRetriever { private CachedFile jwtFile; diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtBearerJwtRetriever.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtBearerJwtRetriever.java index 210625f78cd2a..9ee29e3dd3eb8 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtBearerJwtRetriever.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtBearerJwtRetriever.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.security.oauthbearer.internals.secured.ConfigurationUtils; import org.apache.kafka.common.security.oauthbearer.internals.secured.HttpJwtRetriever; import org.apache.kafka.common.security.oauthbearer.internals.secured.HttpRequestFormatter; @@ -106,6 +108,7 @@ * sasl.oauthbearer.token.endpoint.url=https://example.com/oauth2/v1/token * */ +@InterfaceAudience.Public public class JwtBearerJwtRetriever implements JwtRetriever { private static final Logger LOG = LoggerFactory.getLogger(JwtBearerJwtRetriever.class); @@ -118,6 +121,7 @@ public JwtBearerJwtRetriever() { this(Time.SYSTEM); } + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public JwtBearerJwtRetriever(Time time) { this.time = time; } diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtRetriever.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtRetriever.java index 7510a27883c4c..61e08d201941d 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtRetriever.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtRetriever.java @@ -17,10 +17,11 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.security.oauthbearer.internals.secured.HttpJwtRetriever; import org.apache.kafka.common.security.oauthbearer.internals.secured.OAuthBearerConfigurable; - /** * A JwtRetriever is the internal API by which the login module will * retrieve an access token for use in authorization by the broker. The implementation may @@ -35,6 +36,8 @@ * @see FileJwtRetriever */ +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: extends internal OAuthBearerConfigurable — pending KIP review to promote the parent or refactor the OAuthBearer interface hierarchy") public interface JwtRetriever extends OAuthBearerConfigurable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtRetrieverException.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtRetrieverException.java index a83844fb4150a..7e516786f32fc 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtRetrieverException.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtRetrieverException.java @@ -18,12 +18,14 @@ package org.apache.kafka.common.security.oauthbearer; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * A {@code JwtRetrieverException} is thrown in cases where the JWT cannot be retrieved. * * @see JwtRetriever#retrieve() */ +@InterfaceAudience.Public public class JwtRetrieverException extends KafkaException { public JwtRetrieverException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtValidator.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtValidator.java index 2d74e414913d7..b9ea7d3a2bdd0 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtValidator.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtValidator.java @@ -17,9 +17,10 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.security.oauthbearer.internals.secured.OAuthBearerConfigurable; - /** * An instance of JwtValidator acts as a function object that, given an access * token in base-64 encoded JWT format, can parse the data, perform validation, and construct an @@ -46,6 +47,8 @@ * contents and verify the signature */ +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: extends internal OAuthBearerConfigurable — pending KIP review to promote the parent or refactor the OAuthBearer interface hierarchy") public interface JwtValidator extends OAuthBearerConfigurable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtValidatorException.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtValidatorException.java index 6aef68aaf4b40..9c658a16e86f0 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtValidatorException.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/JwtValidatorException.java @@ -18,6 +18,7 @@ package org.apache.kafka.common.security.oauthbearer; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; @@ -30,6 +31,7 @@ * * @see JwtValidator#validate(String) */ +@InterfaceAudience.Public public class JwtValidatorException extends KafkaException { public JwtValidatorException(String message) { diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerExtensionsValidatorCallback.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerExtensionsValidatorCallback.java index 7874833e27ae1..a32cf69440748 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerExtensionsValidatorCallback.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerExtensionsValidatorCallback.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.auth.SaslExtensions; import java.util.Collections; @@ -42,6 +43,7 @@ * It is very important that token validation is done in its own {@link OAuthBearerValidatorCallback} * irregardless of provided extensions, as they are inherently insecure. */ +@InterfaceAudience.Public public class OAuthBearerExtensionsValidatorCallback implements Callback { private final OAuthBearerToken token; private final SaslExtensions inputExtensions; diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerLoginCallbackHandler.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerLoginCallbackHandler.java index 6afd31df273f9..38aeb54920a25 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerLoginCallbackHandler.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerLoginCallbackHandler.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.config.SaslConfigs; @@ -146,6 +147,7 @@ *

    */ +@InterfaceAudience.Public public class OAuthBearerLoginCallbackHandler implements AuthenticateCallbackHandler { private static final Logger log = LoggerFactory.getLogger(OAuthBearerLoginCallbackHandler.class); diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerLoginModule.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerLoginModule.java index d8cbe777458b2..4844271eb98bc 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerLoginModule.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerLoginModule.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.SaslConfigs; import org.apache.kafka.common.security.auth.AuthenticateCallbackHandler; import org.apache.kafka.common.security.auth.Login; @@ -235,6 +236,7 @@ * @see SaslConfigs#SASL_LOGIN_REFRESH_MIN_PERIOD_SECONDS_DOC * @see SaslConfigs#SASL_LOGIN_REFRESH_BUFFER_SECONDS_DOC */ +@InterfaceAudience.Public public class OAuthBearerLoginModule implements LoginModule { /** diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerToken.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerToken.java index 6e9dd84cd4cf0..598df32f66577 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerToken.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerToken.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Set; /** @@ -39,6 +42,7 @@ * RFC 6750 * Section 2.1 */ +@InterfaceAudience.Public public interface OAuthBearerToken { /** * The b64token value as defined in diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerTokenCallback.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerTokenCallback.java index c72a5d5471974..15c9fe8d644df 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerTokenCallback.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerTokenCallback.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import javax.security.auth.callback.Callback; @@ -29,6 +32,7 @@ * 2.0 Authorization Framework. Callback handlers should communicate other * problems by raising an {@code IOException}. */ +@InterfaceAudience.Public public class OAuthBearerTokenCallback implements Callback { private OAuthBearerToken token = null; private String errorCode = null; diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerValidatorCallback.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerValidatorCallback.java index 1b8e50c909a2d..1a275397b612a 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerValidatorCallback.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerValidatorCallback.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import javax.security.auth.callback.Callback; @@ -32,6 +35,7 @@ * OAuth Extensions Error Registry. Callback handlers should communicate * other problems by raising an {@code IOException}. */ +@InterfaceAudience.Public public class OAuthBearerValidatorCallback implements Callback { private final String tokenValue; private OAuthBearerToken token = null; diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerValidatorCallbackHandler.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerValidatorCallbackHandler.java index 2d03fa469e11c..1144b84fa2905 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerValidatorCallbackHandler.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/OAuthBearerValidatorCallbackHandler.java @@ -17,6 +17,7 @@ package org.apache.kafka.common.security.oauthbearer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.config.SaslConfigs; import org.apache.kafka.common.security.auth.AuthenticateCallbackHandler; @@ -95,6 +96,7 @@ *

    */ +@InterfaceAudience.Public public class OAuthBearerValidatorCallbackHandler implements AuthenticateCallbackHandler { private static final Logger log = LoggerFactory.getLogger(OAuthBearerValidatorCallbackHandler.class); diff --git a/clients/src/main/java/org/apache/kafka/common/security/plain/PlainAuthenticateCallback.java b/clients/src/main/java/org/apache/kafka/common/security/plain/PlainAuthenticateCallback.java index 7f42645e487fb..1867f2507bc87 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/plain/PlainAuthenticateCallback.java +++ b/clients/src/main/java/org/apache/kafka/common/security/plain/PlainAuthenticateCallback.java @@ -17,6 +17,8 @@ package org.apache.kafka.common.security.plain; +import org.apache.kafka.common.annotation.InterfaceAudience; + import javax.security.auth.callback.Callback; /* @@ -24,6 +26,7 @@ * set authenticated flag to true if the client provided password in the callback * matches the expected password. */ +@InterfaceAudience.Public public class PlainAuthenticateCallback implements Callback { private final char[] password; private boolean authenticated; diff --git a/clients/src/main/java/org/apache/kafka/common/security/plain/PlainLoginModule.java b/clients/src/main/java/org/apache/kafka/common/security/plain/PlainLoginModule.java index 40851681ba63f..76a5f316113bb 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/plain/PlainLoginModule.java +++ b/clients/src/main/java/org/apache/kafka/common/security/plain/PlainLoginModule.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.security.plain; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.plain.internals.PlainSaslServerProvider; import java.util.Map; @@ -24,6 +25,7 @@ import javax.security.auth.callback.CallbackHandler; import javax.security.auth.spi.LoginModule; +@InterfaceAudience.Public public class PlainLoginModule implements LoginModule { private static final String USERNAME_CONFIG = "username"; diff --git a/clients/src/main/java/org/apache/kafka/common/security/scram/ScramCredential.java b/clients/src/main/java/org/apache/kafka/common/security/scram/ScramCredential.java index dfbfef15b4f74..7702d0a5dca1f 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/scram/ScramCredential.java +++ b/clients/src/main/java/org/apache/kafka/common/security/scram/ScramCredential.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.scram; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * SCRAM credential class that encapsulates the credential data persisted for each user that is * accessible to the server. See RFC rfc5802 * for details. */ +@InterfaceAudience.Public public class ScramCredential { private final byte[] salt; diff --git a/clients/src/main/java/org/apache/kafka/common/security/scram/ScramCredentialCallback.java b/clients/src/main/java/org/apache/kafka/common/security/scram/ScramCredentialCallback.java index d5988cbeb8905..0025e45e21217 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/scram/ScramCredentialCallback.java +++ b/clients/src/main/java/org/apache/kafka/common/security/scram/ScramCredentialCallback.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.scram; +import org.apache.kafka.common.annotation.InterfaceAudience; + import javax.security.auth.callback.Callback; /** * Callback used for SCRAM mechanisms. */ +@InterfaceAudience.Public public class ScramCredentialCallback implements Callback { private ScramCredential scramCredential; diff --git a/clients/src/main/java/org/apache/kafka/common/security/scram/ScramExtensionsCallback.java b/clients/src/main/java/org/apache/kafka/common/security/scram/ScramExtensionsCallback.java index 69350b7f464ce..c4a17c3904948 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/scram/ScramExtensionsCallback.java +++ b/clients/src/main/java/org/apache/kafka/common/security/scram/ScramExtensionsCallback.java @@ -14,17 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.scram; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; import javax.security.auth.callback.Callback; - /** * Optional callback used for SCRAM mechanisms if any extensions need to be set * in the SASL/SCRAM exchange. */ +@InterfaceAudience.Public public class ScramExtensionsCallback implements Callback { private Map extensions = Map.of(); diff --git a/clients/src/main/java/org/apache/kafka/common/security/scram/ScramLoginModule.java b/clients/src/main/java/org/apache/kafka/common/security/scram/ScramLoginModule.java index 3bf60161a0472..23185c0525032 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/scram/ScramLoginModule.java +++ b/clients/src/main/java/org/apache/kafka/common/security/scram/ScramLoginModule.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.security.scram; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.scram.internals.ScramSaslClientProvider; import org.apache.kafka.common.security.scram.internals.ScramSaslServerProvider; @@ -25,6 +26,7 @@ import javax.security.auth.callback.CallbackHandler; import javax.security.auth.spi.LoginModule; +@InterfaceAudience.Public public class ScramLoginModule implements LoginModule { private static final String USERNAME_CONFIG = "username"; diff --git a/clients/src/main/java/org/apache/kafka/common/security/token/delegation/DelegationToken.java b/clients/src/main/java/org/apache/kafka/common/security/token/delegation/DelegationToken.java index 27f0f65c3a9b1..bddfd15ada444 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/token/delegation/DelegationToken.java +++ b/clients/src/main/java/org/apache/kafka/common/security/token/delegation/DelegationToken.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.security.token.delegation; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.security.MessageDigest; import java.util.Arrays; import java.util.Base64; @@ -25,6 +28,7 @@ * A class representing a delegation token. * */ +@InterfaceAudience.Public public class DelegationToken { private final TokenInformation tokenInformation; private final byte[] hmac; diff --git a/clients/src/main/java/org/apache/kafka/common/security/token/delegation/TokenInformation.java b/clients/src/main/java/org/apache/kafka/common/security/token/delegation/TokenInformation.java index 0b639d345c7f6..844280c1084c0 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/token/delegation/TokenInformation.java +++ b/clients/src/main/java/org/apache/kafka/common/security/token/delegation/TokenInformation.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.security.token.delegation; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.auth.KafkaPrincipal; import java.util.ArrayList; @@ -26,6 +27,7 @@ * A class representing a delegation token details. * */ +@InterfaceAudience.Public public class TokenInformation { private final KafkaPrincipal owner; diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/BooleanDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/BooleanDeserializer.java index 1add7ed3388b4..c8e0ab8574379 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/BooleanDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/BooleanDeserializer.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; import java.nio.ByteBuffer; +@InterfaceAudience.Public public class BooleanDeserializer implements Deserializer { private static final byte TRUE = 0x01; private static final byte FALSE = 0x00; diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/BooleanSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/BooleanSerializer.java index ad4722a8d8074..898951286efd2 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/BooleanSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/BooleanSerializer.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class BooleanSerializer implements Serializer { private static final byte TRUE = 0x01; diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/ByteArrayDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/ByteArrayDeserializer.java index 1147f45534f26..c151d9d25c814 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/ByteArrayDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/ByteArrayDeserializer.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class ByteArrayDeserializer implements Deserializer { @Override diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/ByteArraySerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/ByteArraySerializer.java index 6bebaa6531fc1..38e0aca1245b4 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/ByteArraySerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/ByteArraySerializer.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class ByteArraySerializer implements Serializer { @Override public byte[] serialize(String topic, byte[] data) { diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/ByteBufferDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/ByteBufferDeserializer.java index 6ef05af16fc2d..130386e8d3bcb 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/ByteBufferDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/ByteBufferDeserializer.java @@ -16,10 +16,12 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import java.nio.ByteBuffer; +@InterfaceAudience.Public public class ByteBufferDeserializer implements Deserializer { @Override diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/ByteBufferSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/ByteBufferSerializer.java index 43b3d6e38a76e..33f6bd5634960 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/ByteBufferSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/ByteBufferSerializer.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.nio.ByteBuffer; /** @@ -27,6 +30,7 @@ * The position is also rewound back to zero before {@link #serialize(String, ByteBuffer)} * returns. */ +@InterfaceAudience.Public public class ByteBufferSerializer implements Serializer { public byte[] serialize(String topic, ByteBuffer data) { if (data == null) diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/BytesDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/BytesDeserializer.java index 1350dca21dd01..df314ea596385 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/BytesDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/BytesDeserializer.java @@ -16,8 +16,10 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; +@InterfaceAudience.Public public class BytesDeserializer implements Deserializer { public Bytes deserialize(String topic, byte[] data) { if (data == null) diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/BytesSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/BytesSerializer.java index f19305da63713..0135c4900221d 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/BytesSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/BytesSerializer.java @@ -16,8 +16,10 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; +@InterfaceAudience.Public public class BytesSerializer implements Serializer { public byte[] serialize(String topic, Bytes data) { if (data == null) diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/Deserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/Deserializer.java index d48574b54fabf..cf24d858e5865 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/Deserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/Deserializer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.utils.Utils; @@ -35,6 +36,7 @@ * * @param Type to be deserialized into. */ +@InterfaceAudience.Public public interface Deserializer extends Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/DoubleDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/DoubleDeserializer.java index 8b3d8b6988724..c03ec10c16e5b 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/DoubleDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/DoubleDeserializer.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; import java.nio.ByteBuffer; +@InterfaceAudience.Public public class DoubleDeserializer implements Deserializer { @Override diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/DoubleSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/DoubleSerializer.java index 99781b53d0e01..0524585cc4dc2 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/DoubleSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/DoubleSerializer.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class DoubleSerializer implements Serializer { @Override public byte[] serialize(String topic, Double data) { diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/FloatDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/FloatDeserializer.java index 0389cacdcf883..565bb6a925cc0 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/FloatDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/FloatDeserializer.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; import java.nio.ByteBuffer; +@InterfaceAudience.Public public class FloatDeserializer implements Deserializer { @Override public Float deserialize(final String topic, final byte[] data) { diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/FloatSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/FloatSerializer.java index 6f74a573a5f10..94f70351d9477 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/FloatSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/FloatSerializer.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class FloatSerializer implements Serializer { @Override public byte[] serialize(final String topic, final Float data) { diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/IntegerDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/IntegerDeserializer.java index f9ac21374d7c8..d385f41935747 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/IntegerDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/IntegerDeserializer.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; import java.nio.ByteBuffer; +@InterfaceAudience.Public public class IntegerDeserializer implements Deserializer { @Override public Integer deserialize(String topic, byte[] data) { diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/IntegerSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/IntegerSerializer.java index 8ab531046006a..ad43e30a232fd 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/IntegerSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/IntegerSerializer.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class IntegerSerializer implements Serializer { public byte[] serialize(String topic, Integer data) { if (data == null) diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/ListDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/ListDeserializer.java index 42e7c48dde87b..905279b620038 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/ListDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/ListDeserializer.java @@ -18,6 +18,7 @@ import org.apache.kafka.clients.CommonClientConfigs; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; @@ -39,6 +40,7 @@ import static org.apache.kafka.common.serialization.Serdes.ListSerde.SerializationStrategy; +@InterfaceAudience.Public public class ListDeserializer implements Deserializer> { final Logger log = LoggerFactory.getLogger(ListDeserializer.class); diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/ListSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/ListSerializer.java index d56d9414d7271..edc91a126f3cd 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/ListSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/ListSerializer.java @@ -18,6 +18,7 @@ import org.apache.kafka.clients.CommonClientConfigs; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; @@ -37,6 +38,7 @@ import static org.apache.kafka.common.serialization.Serdes.ListSerde.SerializationStrategy; +@InterfaceAudience.Public public class ListSerializer implements Serializer> { final Logger log = LoggerFactory.getLogger(ListSerializer.class); diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/LongDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/LongDeserializer.java index 38cbfd9827073..e0f11cd842eb1 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/LongDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/LongDeserializer.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; import java.nio.ByteBuffer; +@InterfaceAudience.Public public class LongDeserializer implements Deserializer { @Override public Long deserialize(String topic, byte[] data) { diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/LongSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/LongSerializer.java index 436f0e01095ca..a0a7e7c9d6157 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/LongSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/LongSerializer.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class LongSerializer implements Serializer { public byte[] serialize(String topic, Long data) { if (data == null) diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/Serde.java b/clients/src/main/java/org/apache/kafka/common/serialization/Serde.java index 5b052e69f6969..3767a7a1564dc 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/Serde.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/Serde.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.io.Closeable; import java.util.Map; @@ -26,6 +29,7 @@ * * A class that implements this interface is expected to have a constructor with no parameter. */ +@InterfaceAudience.Public public interface Serde extends Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/Serdes.java b/clients/src/main/java/org/apache/kafka/common/serialization/Serdes.java index 600d046a61c3b..9d8510114d5b2 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/Serdes.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/Serdes.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; import java.nio.ByteBuffer; @@ -26,6 +27,7 @@ /** * Factory for creating serializers / deserializers. */ +@InterfaceAudience.Public public class Serdes { public static class WrapperSerde implements Serde { diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/Serializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/Serializer.java index 0730b71bcade1..18ecedbdad4d0 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/Serializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/Serializer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import java.io.Closeable; @@ -33,6 +34,7 @@ * * @param Type to be serialized from. */ +@InterfaceAudience.Public public interface Serializer extends Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/ShortDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/ShortDeserializer.java index 3bca2c977cb88..50789a7bd5370 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/ShortDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/ShortDeserializer.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; import java.nio.ByteBuffer; +@InterfaceAudience.Public public class ShortDeserializer implements Deserializer { @Override diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/ShortSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/ShortSerializer.java index e54354b4dea05..953f05a7f9ff8 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/ShortSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/ShortSerializer.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class ShortSerializer implements Serializer { public byte[] serialize(String topic, Short data) { if (data == null) diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/StringDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/StringDeserializer.java index ae3cad199082c..db90709448046 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/StringDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/StringDeserializer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.utils.Utils; @@ -31,6 +32,7 @@ * String encoding defaults to UTF8 and can be customized by setting the property key.deserializer.encoding, * value.deserializer.encoding or deserializer.encoding. The first two take precedence over the last. */ +@InterfaceAudience.Public public class StringDeserializer implements Deserializer { private Charset encoding = StandardCharsets.UTF_8; diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/StringSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/StringSerializer.java index af7b04be231ef..3580f10737e85 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/StringSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/StringSerializer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import java.nio.charset.Charset; @@ -28,6 +29,7 @@ * String encoding defaults to UTF8 and can be customized by setting the property key.serializer.encoding, * value.serializer.encoding or serializer.encoding. The first two take precedence over the last. */ +@InterfaceAudience.Public public class StringSerializer implements Serializer { private Charset encoding = StandardCharsets.UTF_8; diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/UUIDDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/UUIDDeserializer.java index f1f1403cc925f..dca2019dc82b4 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/UUIDDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/UUIDDeserializer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.utils.Utils; @@ -30,6 +31,7 @@ * We are converting the byte array to String before deserializing to UUID. String encoding defaults to UTF8 and can be customized by setting * the property key.deserializer.encoding, value.deserializer.encoding or deserializer.encoding. The first two take precedence over the last. */ +@InterfaceAudience.Public public class UUIDDeserializer implements Deserializer { private String encoding = StandardCharsets.UTF_8.name(); diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/UUIDSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/UUIDSerializer.java index 1477546fdf996..46929ad9a9c83 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/UUIDSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/UUIDSerializer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.SerializationException; import java.io.UnsupportedEncodingException; @@ -27,6 +28,7 @@ * We are converting UUID to String before serializing. String encoding defaults to UTF8 and can be customized by setting * the property key.deserializer.encoding, value.deserializer.encoding or deserializer.encoding. The first two take precedence over the last. */ +@InterfaceAudience.Public public class UUIDSerializer implements Serializer { private String encoding = StandardCharsets.UTF_8.name(); diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/VoidDeserializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/VoidDeserializer.java index 1f0d3b0c29620..96f02154e99f9 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/VoidDeserializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/VoidDeserializer.java @@ -16,10 +16,12 @@ */ package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import java.nio.ByteBuffer; +@InterfaceAudience.Public public class VoidDeserializer implements Deserializer { @Override public Void deserialize(String topic, byte[] data) { diff --git a/clients/src/main/java/org/apache/kafka/common/serialization/VoidSerializer.java b/clients/src/main/java/org/apache/kafka/common/serialization/VoidSerializer.java index f1f2c6071a832..be204eed61e87 100644 --- a/clients/src/main/java/org/apache/kafka/common/serialization/VoidSerializer.java +++ b/clients/src/main/java/org/apache/kafka/common/serialization/VoidSerializer.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.common.serialization; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class VoidSerializer implements Serializer { @Override public byte[] serialize(String topic, Void data) { diff --git a/clients/src/main/java/org/apache/kafka/common/utils/Bytes.java b/clients/src/main/java/org/apache/kafka/common/utils/Bytes.java index 24cfe3c8079df..0fef7e48d769a 100644 --- a/clients/src/main/java/org/apache/kafka/common/utils/Bytes.java +++ b/clients/src/main/java/org/apache/kafka/common/utils/Bytes.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.common.utils; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.internals.ByteUtils; import java.io.Serializable; @@ -33,6 +34,7 @@ *

    The class caches the hashCode for improved performance when used as keys * in hash-based data structures. */ +@InterfaceAudience.Public public class Bytes implements Comparable { public static final byte[] EMPTY = new byte[0]; diff --git a/clients/src/main/java/org/apache/kafka/server/authorizer/AclCreateResult.java b/clients/src/main/java/org/apache/kafka/server/authorizer/AclCreateResult.java index 34f7f2f4d3be5..ff258bfe73d82 100644 --- a/clients/src/main/java/org/apache/kafka/server/authorizer/AclCreateResult.java +++ b/clients/src/main/java/org/apache/kafka/server/authorizer/AclCreateResult.java @@ -17,10 +17,12 @@ package org.apache.kafka.server.authorizer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ApiException; import java.util.Optional; +@InterfaceAudience.Public public class AclCreateResult { public static final AclCreateResult SUCCESS = new AclCreateResult(); diff --git a/clients/src/main/java/org/apache/kafka/server/authorizer/AclDeleteResult.java b/clients/src/main/java/org/apache/kafka/server/authorizer/AclDeleteResult.java index e3ff64d61098f..a288cfcf0939a 100644 --- a/clients/src/main/java/org/apache/kafka/server/authorizer/AclDeleteResult.java +++ b/clients/src/main/java/org/apache/kafka/server/authorizer/AclDeleteResult.java @@ -18,12 +18,14 @@ package org.apache.kafka.server.authorizer; import org.apache.kafka.common.acl.AclBinding; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ApiException; import java.util.Collection; import java.util.Collections; import java.util.Optional; +@InterfaceAudience.Public public class AclDeleteResult { private final ApiException exception; private final Collection aclBindingDeleteResults; diff --git a/clients/src/main/java/org/apache/kafka/server/authorizer/Action.java b/clients/src/main/java/org/apache/kafka/server/authorizer/Action.java index d80dce52ac39e..5b9bcd63b5f11 100644 --- a/clients/src/main/java/org/apache/kafka/server/authorizer/Action.java +++ b/clients/src/main/java/org/apache/kafka/server/authorizer/Action.java @@ -18,10 +18,12 @@ package org.apache.kafka.server.authorizer; import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.resource.ResourcePattern; import java.util.Objects; +@InterfaceAudience.Public public class Action { private final ResourcePattern resourcePattern; diff --git a/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizableRequestContext.java b/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizableRequestContext.java index 2508fd7f78950..535d3e64f19d7 100644 --- a/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizableRequestContext.java +++ b/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizableRequestContext.java @@ -17,6 +17,7 @@ package org.apache.kafka.server.authorizer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.auth.KafkaPrincipal; import org.apache.kafka.common.security.auth.SecurityProtocol; @@ -26,6 +27,7 @@ * Request context interface that provides data from request header as well as connection * and authentication information to plugins. */ +@InterfaceAudience.Public public interface AuthorizableRequestContext { /** diff --git a/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizationResult.java b/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizationResult.java index 1e066c366bb56..42b0eee65dbac 100644 --- a/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizationResult.java +++ b/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizationResult.java @@ -17,6 +17,9 @@ package org.apache.kafka.server.authorizer; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public enum AuthorizationResult { ALLOWED, DENIED diff --git a/clients/src/main/java/org/apache/kafka/server/authorizer/Authorizer.java b/clients/src/main/java/org/apache/kafka/server/authorizer/Authorizer.java index c938dd7c44950..db61421de9421 100644 --- a/clients/src/main/java/org/apache/kafka/server/authorizer/Authorizer.java +++ b/clients/src/main/java/org/apache/kafka/server/authorizer/Authorizer.java @@ -24,6 +24,7 @@ import org.apache.kafka.common.acl.AclBindingFilter; import org.apache.kafka.common.acl.AclOperation; import org.apache.kafka.common.acl.AclPermissionType; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.resource.PatternType; import org.apache.kafka.common.resource.ResourcePattern; import org.apache.kafka.common.resource.ResourcePatternFilter; @@ -78,6 +79,7 @@ * *

    */ +@InterfaceAudience.Public public interface Authorizer extends Configurable, Closeable { /** diff --git a/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizerServerInfo.java b/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizerServerInfo.java index d9923c604eed1..352dc27b48161 100644 --- a/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizerServerInfo.java +++ b/clients/src/main/java/org/apache/kafka/server/authorizer/AuthorizerServerInfo.java @@ -19,12 +19,14 @@ import org.apache.kafka.common.ClusterResource; import org.apache.kafka.common.Endpoint; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; /** * Runtime broker configuration metadata provided to authorizers during start up. */ +@InterfaceAudience.Public public interface AuthorizerServerInfo { /** diff --git a/clients/src/main/java/org/apache/kafka/server/policy/AlterConfigPolicy.java b/clients/src/main/java/org/apache/kafka/server/policy/AlterConfigPolicy.java index 7f2c4905c9a73..2ca358e0cbfe6 100644 --- a/clients/src/main/java/org/apache/kafka/server/policy/AlterConfigPolicy.java +++ b/clients/src/main/java/org/apache/kafka/server/policy/AlterConfigPolicy.java @@ -17,6 +17,7 @@ package org.apache.kafka.server.policy; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigResource; import org.apache.kafka.common.errors.PolicyViolationException; @@ -33,6 +34,7 @@ * using the default constructor and will then pass the broker configs to its configure() method. During * broker shutdown, the close() method will be invoked so that resources can be released (if necessary). */ +@InterfaceAudience.Public public interface AlterConfigPolicy extends Configurable, AutoCloseable { /** diff --git a/clients/src/main/java/org/apache/kafka/server/policy/CreateTopicPolicy.java b/clients/src/main/java/org/apache/kafka/server/policy/CreateTopicPolicy.java index 4d8c7ad2706c9..0a6bb312fc6f6 100644 --- a/clients/src/main/java/org/apache/kafka/server/policy/CreateTopicPolicy.java +++ b/clients/src/main/java/org/apache/kafka/server/policy/CreateTopicPolicy.java @@ -17,6 +17,7 @@ package org.apache.kafka.server.policy; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.PolicyViolationException; import java.util.Collections; @@ -34,6 +35,7 @@ * using the default constructor and will then pass the broker configs to its configure() method. During * broker shutdown, the close() method will be invoked so that resources can be released (if necessary). */ +@InterfaceAudience.Public public interface CreateTopicPolicy extends Configurable, AutoCloseable { /** diff --git a/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaCallback.java b/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaCallback.java index dbb4641f03fb9..8acc813cfc949 100644 --- a/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaCallback.java +++ b/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaCallback.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.Cluster; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.security.auth.KafkaPrincipal; import java.util.Map; @@ -32,6 +33,7 @@ *
  • role set to broker/controller, which indicates the role of the server
  • * */ +@InterfaceAudience.Public public interface ClientQuotaCallback extends Configurable { /** diff --git a/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaEntity.java b/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaEntity.java index 0f0eb6253c828..103c0e664ef3e 100644 --- a/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaEntity.java +++ b/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaEntity.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.quota; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; /** @@ -23,6 +26,7 @@ * different levels and `configEntities` gives the list of config entities that define * the level of this quota entity. */ +@InterfaceAudience.Public public interface ClientQuotaEntity { /** diff --git a/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaType.java b/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaType.java index 5b0828a08211f..5ff961874af2e 100644 --- a/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaType.java +++ b/clients/src/main/java/org/apache/kafka/server/quota/ClientQuotaType.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.quota; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Types of quotas that may be configured on brokers for client requests. */ +@InterfaceAudience.Public public enum ClientQuotaType { PRODUCE, FETCH, diff --git a/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryContext.java b/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryContext.java index b62e34426a362..7e2239b0a0c10 100644 --- a/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryContext.java +++ b/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryContext.java @@ -17,12 +17,14 @@ package org.apache.kafka.server.telemetry; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.server.authorizer.AuthorizableRequestContext; /** * {@code ClientTelemetryContext} provides context information for client telemetry requests, * including the push interval. */ +@InterfaceAudience.Public public interface ClientTelemetryContext { /** diff --git a/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryExporter.java b/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryExporter.java index 8c8bf55d518c6..cdfa06a26259c 100644 --- a/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryExporter.java +++ b/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryExporter.java @@ -17,11 +17,14 @@ package org.apache.kafka.server.telemetry; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * {@code ClientTelemetryExporter} defines the behavior for telemetry exporters on the broker side * which receive and export client telemetry metrics and provides additional context including the * push interval. */ +@InterfaceAudience.Public public interface ClientTelemetryExporter { /** diff --git a/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryExporterProvider.java b/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryExporterProvider.java index 39d01cb08a4e1..86cae788da375 100644 --- a/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryExporterProvider.java +++ b/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryExporterProvider.java @@ -17,12 +17,14 @@ package org.apache.kafka.server.telemetry; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.MetricsReporter; /** * A {@link MetricsReporter} may implement this interface to indicate support for collecting client * telemetry on the server side using the new exporter API. */ +@InterfaceAudience.Public public interface ClientTelemetryExporterProvider { /** diff --git a/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryPayload.java b/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryPayload.java index 6d3259f87e8d0..e76c30b97369c 100644 --- a/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryPayload.java +++ b/clients/src/main/java/org/apache/kafka/server/telemetry/ClientTelemetryPayload.java @@ -18,6 +18,7 @@ package org.apache.kafka.server.telemetry; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.nio.ByteBuffer; @@ -25,6 +26,7 @@ * A client telemetry payload as sent by the client to the telemetry exporter. The payload is * exported using a {@link ClientTelemetryExporter}. */ +@InterfaceAudience.Public public interface ClientTelemetryPayload { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/components/ConnectPlugin.java b/connect/api/src/main/java/org/apache/kafka/connect/components/ConnectPlugin.java index d538df4505bc8..8f5836b0c8b96 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/components/ConnectPlugin.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/components/ConnectPlugin.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.components; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; /** @@ -30,6 +31,7 @@ * including their names, types, default values, validators, and documentation. * */ +@InterfaceAudience.Public public interface ConnectPlugin extends Versioned { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/components/Versioned.java b/connect/api/src/main/java/org/apache/kafka/connect/components/Versioned.java index 00fb0d3c44f3c..3a4d9de4cea44 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/components/Versioned.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/components/Versioned.java @@ -17,9 +17,12 @@ package org.apache.kafka.connect.components; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Connect requires some components implement this interface to define a version string. */ +@InterfaceAudience.Public public interface Versioned { /** * Get the version of this component. diff --git a/connect/api/src/main/java/org/apache/kafka/connect/connector/ConnectRecord.java b/connect/api/src/main/java/org/apache/kafka/connect/connector/ConnectRecord.java index 9cee99d8115f2..e0da697e13b2f 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/connector/ConnectRecord.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/connector/ConnectRecord.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.connector; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.data.Schema; import org.apache.kafka.connect.header.ConnectHeaders; import org.apache.kafka.connect.header.Header; @@ -31,6 +32,7 @@ * notion of offset, it is not included here because they differ in type. *

    */ +@InterfaceAudience.Public public abstract class ConnectRecord> { private final String topic; private final Integer kafkaPartition; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/connector/Connector.java b/connect/api/src/main/java/org/apache/kafka/connect/connector/Connector.java index a618ce072b0c7..537a23323eba8 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/connector/Connector.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/connector/Connector.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.connector; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.Config; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigValue; @@ -43,6 +44,7 @@ * Tasks. *

    */ +@InterfaceAudience.Public public abstract class Connector implements ConnectPlugin { protected ConnectorContext context; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/connector/ConnectorContext.java b/connect/api/src/main/java/org/apache/kafka/connect/connector/ConnectorContext.java index 09d1a71eb2a13..23d4cd10cf2e3 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/connector/ConnectorContext.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/connector/ConnectorContext.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.connect.connector; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.PluginMetrics; /** * ConnectorContext allows {@link Connector}s to proactively interact with the Kafka Connect runtime. */ +@InterfaceAudience.Public public interface ConnectorContext { /** * Requests that the runtime reconfigure the Tasks for this source. This should be used to diff --git a/connect/api/src/main/java/org/apache/kafka/connect/connector/Task.java b/connect/api/src/main/java/org/apache/kafka/connect/connector/Task.java index 2cef9de8aa5e5..42e81b426215e 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/connector/Task.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/connector/Task.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.connector; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; /** @@ -31,6 +34,7 @@ * {@link org.apache.kafka.connect.sink.SinkTask}. *

    */ +@InterfaceAudience.Public public interface Task { /** * Get the version of this task. Usually this should be the same as the corresponding {@link Connector} class's version. diff --git a/connect/api/src/main/java/org/apache/kafka/connect/connector/policy/ConnectorClientConfigOverridePolicy.java b/connect/api/src/main/java/org/apache/kafka/connect/connector/policy/ConnectorClientConfigOverridePolicy.java index beb758273b61a..3b2cef44b5c9c 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/connector/policy/ConnectorClientConfigOverridePolicy.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/connector/policy/ConnectorClientConfigOverridePolicy.java @@ -18,6 +18,7 @@ package org.apache.kafka.connect.connector.policy; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigValue; import org.apache.kafka.connect.components.ConnectPlugin; @@ -38,6 +39,7 @@ * connector.client.config.override.policy, and class set to the * ConnectorClientConfigOverridePolicy class name. */ +@InterfaceAudience.Public public interface ConnectorClientConfigOverridePolicy extends Configurable, AutoCloseable, ConnectPlugin { diff --git a/connect/api/src/main/java/org/apache/kafka/connect/connector/policy/ConnectorClientConfigRequest.java b/connect/api/src/main/java/org/apache/kafka/connect/connector/policy/ConnectorClientConfigRequest.java index df962504130cc..29a1a3a98cb34 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/connector/policy/ConnectorClientConfigRequest.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/connector/policy/ConnectorClientConfigRequest.java @@ -17,11 +17,13 @@ package org.apache.kafka.connect.connector.policy; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.connector.Connector; import org.apache.kafka.connect.health.ConnectorType; import java.util.Map; +@InterfaceAudience.Public public class ConnectorClientConfigRequest { private final Map clientProps; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/ConnectSchema.java b/connect/api/src/main/java/org/apache/kafka/connect/data/ConnectSchema.java index b8e10c3dbde18..ae336730cfc39 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/ConnectSchema.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/ConnectSchema.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.DataException; import java.math.BigDecimal; @@ -28,6 +29,7 @@ import java.util.Objects; import java.util.stream.Collectors; +@InterfaceAudience.Public public class ConnectSchema implements Schema { /** * Maps {@link Schema.Type}s to a list of Java classes that can be used to represent them. diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/Date.java b/connect/api/src/main/java/org/apache/kafka/connect/data/Date.java index 24e0615be5390..2690e97b63088 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/Date.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/Date.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.DataException; import java.util.Calendar; @@ -29,6 +30,7 @@ * 1000 milliseconds/second with n) since Unix epoch. *

    */ +@InterfaceAudience.Public public class Date { public static final String LOGICAL_NAME = "org.apache.kafka.connect.data.Date"; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/Decimal.java b/connect/api/src/main/java/org/apache/kafka/connect/data/Decimal.java index b6ec6905b2845..683fbe93d2271 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/Decimal.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/Decimal.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.DataException; import java.math.BigDecimal; @@ -37,6 +38,7 @@ * The underlying representation of this type is bytes containing a two's complement integer *

    */ +@InterfaceAudience.Public public class Decimal { public static final String LOGICAL_NAME = "org.apache.kafka.connect.data.Decimal"; public static final String SCALE_FIELD = "scale"; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/Field.java b/connect/api/src/main/java/org/apache/kafka/connect/data/Field.java index b5d3f027968cb..decbb25c4a0f3 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/Field.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/Field.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** @@ -23,6 +26,7 @@ * A field in a {@link Struct}, consisting of a field name, index, and {@link Schema} for the field value. *

    */ +@InterfaceAudience.Public public class Field { private final String name; private final int index; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/Schema.java b/connect/api/src/main/java/org/apache/kafka/connect/data/Schema.java index 4f25e3611a099..301cde56760ec 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/Schema.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/Schema.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.DataException; import java.util.List; @@ -40,6 +41,7 @@ * Schemas can be created directly, but in most cases using {@link SchemaBuilder} will be simpler. *

    */ +@InterfaceAudience.Public public interface Schema { /** * The type of a schema. These only include the core types; logical types must be determined by checking the schema name. diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaAndValue.java b/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaAndValue.java index 6011ad73694b6..30f7bb1084fa9 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaAndValue.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaAndValue.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * A composite containing a {@link Schema} and associated value */ +@InterfaceAudience.Public public class SchemaAndValue { private final Schema schema; private final Object value; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaBuilder.java b/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaBuilder.java index d8c55573e5c6f..c1f3526f1daa0 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaBuilder.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaBuilder.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.DataException; import org.apache.kafka.connect.errors.SchemaBuilderException; @@ -51,6 +52,7 @@ * *

    */ +@InterfaceAudience.Public public class SchemaBuilder implements Schema { private static final String TYPE_FIELD = "type"; private static final String OPTIONAL_FIELD = "optional"; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaProjector.java b/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaProjector.java index ed096504e09a2..b810718b9e530 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaProjector.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/SchemaProjector.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.data.Schema.Type; import org.apache.kafka.connect.errors.SchemaProjectorException; @@ -35,6 +36,7 @@ *

    */ +@InterfaceAudience.Public public class SchemaProjector { private static final Set> PROMOTABLE = new HashSet<>(); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/Struct.java b/connect/api/src/main/java/org/apache/kafka/connect/data/Struct.java index 6e5b81ab11537..5969490664fe5 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/Struct.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/Struct.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.DataException; import java.nio.ByteBuffer; @@ -39,6 +40,7 @@ * *

    */ +@InterfaceAudience.Public public class Struct { private final Schema schema; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/Time.java b/connect/api/src/main/java/org/apache/kafka/connect/data/Time.java index 6badee4598eab..c681ca98dd928 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/Time.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/Time.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.DataException; import java.util.Calendar; @@ -29,6 +30,7 @@ * representing the number of milliseconds after midnight. *

    */ +@InterfaceAudience.Public public class Time { public static final String LOGICAL_NAME = "org.apache.kafka.connect.data.Time"; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/Timestamp.java b/connect/api/src/main/java/org/apache/kafka/connect/data/Timestamp.java index 9ac9ff481db5f..197ca22445767 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/Timestamp.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/Timestamp.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.DataException; /** @@ -24,6 +25,7 @@ * {@link java.util.Date}. The underlying representation is a long representing the number of milliseconds since Unix epoch. *

    */ +@InterfaceAudience.Public public class Timestamp { public static final String LOGICAL_NAME = "org.apache.kafka.connect.data.Timestamp"; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/data/Values.java b/connect/api/src/main/java/org/apache/kafka/connect/data/Values.java index 266d31534a81c..3525ea91dd907 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/data/Values.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/data/Values.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.data; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Utils; import org.apache.kafka.connect.data.Schema.Type; import org.apache.kafka.connect.errors.DataException; @@ -58,6 +59,7 @@ *

    This class is able to convert any value to a string representation as well as parse those string representations back into most of * the types. The only exception is {@link Struct} values that require a schema and thus cannot be parsed from a simple string. */ +@InterfaceAudience.Public public class Values { private static final TimeZone UTC = TimeZone.getTimeZone("UTC"); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/errors/AlreadyExistsException.java b/connect/api/src/main/java/org/apache/kafka/connect/errors/AlreadyExistsException.java index a37f6157e7ca2..a805b8b8a1f88 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/errors/AlreadyExistsException.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/errors/AlreadyExistsException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates the operation tried to create an entity that already exists. */ +@InterfaceAudience.Public public class AlreadyExistsException extends ConnectException { public AlreadyExistsException(String s) { super(s); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/errors/ConnectException.java b/connect/api/src/main/java/org/apache/kafka/connect/errors/ConnectException.java index 3cbde36032edb..a6707d8c5a6ee 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/errors/ConnectException.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/errors/ConnectException.java @@ -14,13 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.errors; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * ConnectException is the top-level exception type generated by Kafka Connect and connector implementations. */ +@InterfaceAudience.Public public class ConnectException extends KafkaException { public ConnectException(String s) { diff --git a/connect/api/src/main/java/org/apache/kafka/connect/errors/DataException.java b/connect/api/src/main/java/org/apache/kafka/connect/errors/DataException.java index a850347b2bbf7..635c61fff2ec0 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/errors/DataException.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/errors/DataException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Base class for all Kafka Connect data API exceptions. */ +@InterfaceAudience.Public public class DataException extends ConnectException { public DataException(String s) { super(s); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/errors/IllegalWorkerStateException.java b/connect/api/src/main/java/org/apache/kafka/connect/errors/IllegalWorkerStateException.java index be9cd34e4e83d..bf83af733dc42 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/errors/IllegalWorkerStateException.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/errors/IllegalWorkerStateException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that a method has been invoked illegally or at an invalid time by a connector or task. */ +@InterfaceAudience.Public public class IllegalWorkerStateException extends ConnectException { public IllegalWorkerStateException(String s) { super(s); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/errors/NotFoundException.java b/connect/api/src/main/java/org/apache/kafka/connect/errors/NotFoundException.java index 90f017903cab1..ef130b83a95f1 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/errors/NotFoundException.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/errors/NotFoundException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that an operation attempted to modify or delete a connector or task that is not present on the worker. */ +@InterfaceAudience.Public public class NotFoundException extends ConnectException { public NotFoundException(String s) { super(s); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/errors/RetriableException.java b/connect/api/src/main/java/org/apache/kafka/connect/errors/RetriableException.java index 0b34bd0e14986..6740f87519fe5 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/errors/RetriableException.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/errors/RetriableException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An exception that indicates the operation can be reattempted. */ +@InterfaceAudience.Public public class RetriableException extends ConnectException { public RetriableException(String s) { super(s); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/errors/SchemaBuilderException.java b/connect/api/src/main/java/org/apache/kafka/connect/errors/SchemaBuilderException.java index d1037ad15878f..d3dd46536e0a1 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/errors/SchemaBuilderException.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/errors/SchemaBuilderException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates an error while building a schema via {@link org.apache.kafka.connect.data.SchemaBuilder} */ +@InterfaceAudience.Public public class SchemaBuilderException extends DataException { public SchemaBuilderException(String s) { super(s); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/errors/SchemaProjectorException.java b/connect/api/src/main/java/org/apache/kafka/connect/errors/SchemaProjectorException.java index dd27733c9ede2..292a37b4a66ec 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/errors/SchemaProjectorException.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/errors/SchemaProjectorException.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates an error while projecting a schema via {@link org.apache.kafka.connect.data.SchemaProjector} */ +@InterfaceAudience.Public public class SchemaProjectorException extends DataException { public SchemaProjectorException(String s) { super(s); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/header/ConnectHeaders.java b/connect/api/src/main/java/org/apache/kafka/connect/header/ConnectHeaders.java index 19afc137c323c..53f7b6cfc6d9d 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/header/ConnectHeaders.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/header/ConnectHeaders.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.header; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.internals.AbstractIterator; import org.apache.kafka.connect.data.Date; import org.apache.kafka.connect.data.Decimal; @@ -42,6 +43,7 @@ /** * A basic {@link Headers} implementation. */ +@InterfaceAudience.Public public class ConnectHeaders implements Headers { private static final int EMPTY_HASH = Objects.hash(new LinkedList<>()); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/header/Header.java b/connect/api/src/main/java/org/apache/kafka/connect/header/Header.java index a70d1dc77ea6d..1c92086a0d5c4 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/header/Header.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/header/Header.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.header; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.data.Schema; /** @@ -24,6 +25,7 @@ *

    * This is an immutable interface. */ +@InterfaceAudience.Public public interface Header { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/header/Headers.java b/connect/api/src/main/java/org/apache/kafka/connect/header/Headers.java index d7bd77952cf24..42e8eb77e581e 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/header/Headers.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/header/Headers.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.header; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.data.Schema; import org.apache.kafka.connect.data.SchemaAndValue; import org.apache.kafka.connect.data.Struct; @@ -29,6 +30,7 @@ /** * A mutable ordered collection of {@link Header} objects. Note that multiple headers may have the same {@link Header#key() key}. */ +@InterfaceAudience.Public public interface Headers extends Iterable

    { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/health/AbstractState.java b/connect/api/src/main/java/org/apache/kafka/connect/health/AbstractState.java index 2dac451a1cd3f..c2b8ebbd24d1d 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/health/AbstractState.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/health/AbstractState.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.health; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Utils; import java.util.Objects; @@ -24,6 +25,7 @@ /** * Provides the current status for a connector or a task, along with an identifier for its Connect worker */ +@InterfaceAudience.Public public abstract class AbstractState { private final String state; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectClusterDetails.java b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectClusterDetails.java index ced9122ae6cc8..67a9c22351eb3 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectClusterDetails.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectClusterDetails.java @@ -17,10 +17,13 @@ package org.apache.kafka.connect.health; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Provides immutable Connect cluster information, such as the ID of the backing Kafka cluster. The * Connect framework provides the implementation for this interface. */ +@InterfaceAudience.Public public interface ConnectClusterDetails { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectClusterState.java b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectClusterState.java index e42564ca457ac..39bde2a513cff 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectClusterState.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectClusterState.java @@ -17,6 +17,8 @@ package org.apache.kafka.connect.health; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; import java.util.Map; @@ -26,6 +28,7 @@ * {@link org.apache.kafka.connect.rest.ConnectRestExtension} implementations. The Connect framework * provides the implementation for this interface. */ +@InterfaceAudience.Public public interface ConnectClusterState { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorHealth.java b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorHealth.java index 876a0b3e3b94c..81af6142033b0 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorHealth.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorHealth.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.health; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Utils; import java.util.Map; @@ -24,6 +25,7 @@ /** * Provides basic health information about the connector and its tasks. */ +@InterfaceAudience.Public public class ConnectorHealth { private final String name; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorState.java b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorState.java index 63044265bb999..65579453952f7 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorState.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorState.java @@ -17,9 +17,12 @@ package org.apache.kafka.connect.health; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Describes the status, worker ID, and any errors associated with a connector. */ +@InterfaceAudience.Public public class ConnectorState extends AbstractState { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorType.java b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorType.java index fa9db6f6b60b6..6b9dce8b61cb1 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorType.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/health/ConnectorType.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.health; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Locale; /** * Enum definition that identifies the type of the connector. */ +@InterfaceAudience.Public public enum ConnectorType { /** * Identifies a source connector diff --git a/connect/api/src/main/java/org/apache/kafka/connect/health/TaskState.java b/connect/api/src/main/java/org/apache/kafka/connect/health/TaskState.java index ae78a5f3af990..62c4cffed9131 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/health/TaskState.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/health/TaskState.java @@ -17,11 +17,14 @@ package org.apache.kafka.connect.health; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Describes the state, IDs, and any errors of a connector task. */ +@InterfaceAudience.Public public class TaskState extends AbstractState { private final int taskId; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/rest/ConnectRestExtension.java b/connect/api/src/main/java/org/apache/kafka/connect/rest/ConnectRestExtension.java index eed69f861d4b0..cc10d207855e7 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/rest/ConnectRestExtension.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/rest/ConnectRestExtension.java @@ -18,6 +18,7 @@ package org.apache.kafka.connect.rest; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.connect.components.ConnectPlugin; import org.apache.kafka.connect.health.ConnectClusterState; @@ -49,6 +50,7 @@ * The following tags are automatically added to all metrics registered: config set to * rest.extension.classes, and class set to the ConnectRestExtension class name. */ +@InterfaceAudience.Public public interface ConnectRestExtension extends Configurable, ConnectPlugin, Closeable { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/rest/ConnectRestExtensionContext.java b/connect/api/src/main/java/org/apache/kafka/connect/rest/ConnectRestExtensionContext.java index 0bfcee678b1aa..0fa445102d497 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/rest/ConnectRestExtensionContext.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/rest/ConnectRestExtensionContext.java @@ -17,16 +17,17 @@ package org.apache.kafka.connect.rest; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.health.ConnectClusterState; import jakarta.ws.rs.core.Configurable; - /** * The interface provides the ability for {@link ConnectRestExtension} implementations to access the JAX-RS * {@link jakarta.ws.rs.core.Configurable} and cluster state {@link ConnectClusterState}. The implementation for the interface is provided * by the Connect framework. */ +@InterfaceAudience.Public public interface ConnectRestExtensionContext { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/sink/ErrantRecordReporter.java b/connect/api/src/main/java/org/apache/kafka/connect/sink/ErrantRecordReporter.java index 81b74a58f8ea2..dcbc2890e7f10 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/sink/ErrantRecordReporter.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/sink/ErrantRecordReporter.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.sink; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.ConnectException; import java.util.concurrent.Future; @@ -26,6 +27,7 @@ * * @since 2.6 */ +@InterfaceAudience.Public public interface ErrantRecordReporter { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkConnector.java b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkConnector.java index b230b7dee4fc7..069cec1ef4825 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkConnector.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkConnector.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.sink; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.connector.Connector; import java.util.Map; @@ -27,6 +28,7 @@ * To support this, implementations of this interface should also contain a service provider configuration file in * {@code META-INF/services/org.apache.kafka.connect.sink.SinkConnector}. */ +@InterfaceAudience.Public public abstract class SinkConnector extends Connector { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkConnectorContext.java b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkConnectorContext.java index 5e2b07a9fbb99..b0c989bb46243 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkConnectorContext.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkConnectorContext.java @@ -16,10 +16,12 @@ */ package org.apache.kafka.connect.sink; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.connector.ConnectorContext; /** * A context to allow a {@link SinkConnector} to interact with the Kafka Connect runtime. */ +@InterfaceAudience.Public public interface SinkConnectorContext extends ConnectorContext { } diff --git a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkRecord.java b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkRecord.java index 33e5d84389a1b..c7b7c9db79a1f 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkRecord.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkRecord.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.sink; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.record.TimestampType; import org.apache.kafka.connect.connector.ConnectRecord; import org.apache.kafka.connect.data.Schema; @@ -34,6 +35,7 @@ * It also includes the {@link TimestampType}, which may be {@link TimestampType#NO_TIMESTAMP_TYPE}, and the relevant * timestamp, which may be {@code null}. */ +@InterfaceAudience.Public public class SinkRecord extends ConnectRecord { private final long kafkaOffset; private final TimestampType timestampType; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkTask.java b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkTask.java index 655c89ac670fe..2d4a08e20f581 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkTask.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkTask.java @@ -18,6 +18,7 @@ import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.connector.Task; import org.apache.kafka.connect.transforms.Transformation; @@ -52,6 +53,7 @@ * * */ +@InterfaceAudience.Public public abstract class SinkTask implements Task { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkTaskContext.java b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkTaskContext.java index 5f392ada8fd2a..9a61aa0e57ccf 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkTaskContext.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/sink/SinkTaskContext.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.sink; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.PluginMetrics; import java.util.Map; @@ -25,6 +26,7 @@ /** * Context passed to {@link SinkTask}s, allowing them to access utilities in the Kafka Connect runtime. */ +@InterfaceAudience.Public public interface SinkTaskContext { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/source/ConnectorTransactionBoundaries.java b/connect/api/src/main/java/org/apache/kafka/connect/source/ConnectorTransactionBoundaries.java index 73746ba0993f3..6b0997fd2e31b 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/source/ConnectorTransactionBoundaries.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/source/ConnectorTransactionBoundaries.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.source; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An enum to represent the level of support for connector-defined transaction boundaries. */ +@InterfaceAudience.Public public enum ConnectorTransactionBoundaries { /** * Signals that a connector can define its own transaction boundaries. diff --git a/connect/api/src/main/java/org/apache/kafka/connect/source/ExactlyOnceSupport.java b/connect/api/src/main/java/org/apache/kafka/connect/source/ExactlyOnceSupport.java index 73f9917c6329f..acabdb194d87f 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/source/ExactlyOnceSupport.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/source/ExactlyOnceSupport.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.source; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An enum to represent the level of support for exactly-once semantics from a source connector. */ +@InterfaceAudience.Public public enum ExactlyOnceSupport { /** * Signals that a connector supports exactly-once semantics. diff --git a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceConnector.java b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceConnector.java index a211ca02adef9..77ab1ff861339 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceConnector.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceConnector.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.source; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.connector.Connector; import java.util.Map; @@ -27,6 +28,7 @@ * To support this, implementations of this interface should also contain a service provider configuration file in * {@code META-INF/services/org.apache.kafka.connect.source.SourceConnector}. */ +@InterfaceAudience.Public public abstract class SourceConnector extends Connector { @Override diff --git a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceConnectorContext.java b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceConnectorContext.java index 417fbddd08d46..23809f82ff662 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceConnectorContext.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceConnectorContext.java @@ -16,12 +16,14 @@ */ package org.apache.kafka.connect.source; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.connector.ConnectorContext; import org.apache.kafka.connect.storage.OffsetStorageReader; /** * A context to allow a {@link SourceConnector} to interact with the Kafka Connect runtime. */ +@InterfaceAudience.Public public interface SourceConnectorContext extends ConnectorContext { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceRecord.java b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceRecord.java index 7f0162f021d59..18549bf65fd5f 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceRecord.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceRecord.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.source; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.connector.ConnectRecord; import org.apache.kafka.connect.data.Schema; import org.apache.kafka.connect.header.Header; @@ -41,6 +42,7 @@ * "table_name"} and the sourceOffset as a Long containing the timestamp of the row. *

    */ +@InterfaceAudience.Public public class SourceRecord extends ConnectRecord { private final Map sourcePartition; private final Map sourceOffset; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceTask.java b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceTask.java index c8dd4db6d37a1..9b963b3912884 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceTask.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceTask.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.source; import org.apache.kafka.clients.producer.RecordMetadata; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.connector.Task; import java.util.List; @@ -27,6 +28,7 @@ /** * SourceTask is a Task that pulls records from another system for storage in Kafka. */ +@InterfaceAudience.Public public abstract class SourceTask implements Task { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceTaskContext.java b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceTaskContext.java index 66879d303ceed..613df62077162 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/source/SourceTaskContext.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/source/SourceTaskContext.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.source; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.PluginMetrics; import org.apache.kafka.connect.storage.OffsetStorageReader; @@ -25,6 +26,7 @@ * SourceTaskContext is provided to SourceTasks to allow them to interact with the underlying * runtime. */ +@InterfaceAudience.Public public interface SourceTaskContext { /** * Get the Task configuration. This is the latest configuration and may differ from that passed on startup. diff --git a/connect/api/src/main/java/org/apache/kafka/connect/source/TransactionContext.java b/connect/api/src/main/java/org/apache/kafka/connect/source/TransactionContext.java index 7fd5930a0faf8..8555c9369f69e 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/source/TransactionContext.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/source/TransactionContext.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.source; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Provided to source tasks to allow them to define their own producer transaction boundaries when * exactly-once support is enabled. */ +@InterfaceAudience.Public public interface TransactionContext { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/storage/Converter.java b/connect/api/src/main/java/org/apache/kafka/connect/storage/Converter.java index 2dfc2cb96d207..a4b73bfcdaf4c 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/storage/Converter.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/storage/Converter.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.header.Headers; import org.apache.kafka.connect.components.ConnectPlugin; @@ -38,6 +39,7 @@ * The following tags are automatically added to all metrics registered: connector set to connector name, * task set to the task id and converter set to either key or value. */ +@InterfaceAudience.Public public interface Converter extends Closeable, ConnectPlugin { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/storage/ConverterConfig.java b/connect/api/src/main/java/org/apache/kafka/connect/storage/ConverterConfig.java index cea69959fc89c..5a98f67466e0e 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/storage/ConverterConfig.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/storage/ConverterConfig.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.AbstractConfig; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; @@ -28,6 +29,7 @@ /** * Abstract class that defines the configuration options for {@link Converter} and {@link HeaderConverter} instances. */ +@InterfaceAudience.Public public abstract class ConverterConfig extends AbstractConfig { public static final String TYPE_CONFIG = "converter.type"; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/storage/ConverterType.java b/connect/api/src/main/java/org/apache/kafka/connect/storage/ConverterType.java index 2da2bd8d07e16..722923f711093 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/storage/ConverterType.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/storage/ConverterType.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Locale; import java.util.Map; @@ -24,6 +27,7 @@ /** * The type of {@link Converter} and {@link HeaderConverter}. */ +@InterfaceAudience.Public public enum ConverterType { KEY, VALUE, diff --git a/connect/api/src/main/java/org/apache/kafka/connect/storage/HeaderConverter.java b/connect/api/src/main/java/org/apache/kafka/connect/storage/HeaderConverter.java index af99800431c32..cdd2623f985c4 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/storage/HeaderConverter.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/storage/HeaderConverter.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.storage; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.components.ConnectPlugin; import org.apache.kafka.connect.data.Schema; import org.apache.kafka.connect.data.SchemaAndValue; @@ -36,6 +37,7 @@ * The following tags are automatically added to all metrics registered: connector set to connector name, * task set to the task id and converter set to header. */ +@InterfaceAudience.Public public interface HeaderConverter extends Configurable, Closeable, ConnectPlugin { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/storage/OffsetStorageReader.java b/connect/api/src/main/java/org/apache/kafka/connect/storage/OffsetStorageReader.java index 7f94b888965f6..da1de673f590b 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/storage/OffsetStorageReader.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/storage/OffsetStorageReader.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Collection; import java.util.Map; @@ -30,6 +33,7 @@ * {@link org.apache.kafka.connect.data.Schema} other than Array, Map, and Struct. *

    */ +@InterfaceAudience.Public public interface OffsetStorageReader { /** * Get the offset for the specified partition. If the data isn't already available locally, this diff --git a/connect/api/src/main/java/org/apache/kafka/connect/storage/SimpleHeaderConverter.java b/connect/api/src/main/java/org/apache/kafka/connect/storage/SimpleHeaderConverter.java index 209af997fc871..4b77d62fa6b81 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/storage/SimpleHeaderConverter.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/storage/SimpleHeaderConverter.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.utils.internals.AppInfoParser; import org.apache.kafka.connect.data.Schema; @@ -36,6 +37,7 @@ * A {@link HeaderConverter} that serializes header values as strings and that deserializes header values to the most appropriate * numeric, boolean, array, or map representation. Schemas are not serialized, but are inferred upon deserialization when possible. */ +@InterfaceAudience.Public public class SimpleHeaderConverter implements HeaderConverter { private static final Logger LOG = LoggerFactory.getLogger(SimpleHeaderConverter.class); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/storage/StringConverter.java b/connect/api/src/main/java/org/apache/kafka/connect/storage/StringConverter.java index d48f1aa2b25b9..0557752c065dd 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/storage/StringConverter.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/storage/StringConverter.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.serialization.StringDeserializer; @@ -41,6 +42,7 @@ *

    * This implementation currently does nothing with the topic names or header keys. */ +@InterfaceAudience.Public public class StringConverter implements Converter, HeaderConverter { private final StringSerializer serializer = new StringSerializer(); diff --git a/connect/api/src/main/java/org/apache/kafka/connect/storage/StringConverterConfig.java b/connect/api/src/main/java/org/apache/kafka/connect/storage/StringConverterConfig.java index a98b3bf233403..a5312cfbc6b80 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/storage/StringConverterConfig.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/storage/StringConverterConfig.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; import org.apache.kafka.common.config.ConfigDef.Type; @@ -27,6 +28,7 @@ /** * Configuration options for {@link StringConverter} instances. */ +@InterfaceAudience.Public public class StringConverterConfig extends ConverterConfig { public static final String ENCODING_CONFIG = "converter.encoding"; diff --git a/connect/api/src/main/java/org/apache/kafka/connect/transforms/Transformation.java b/connect/api/src/main/java/org/apache/kafka/connect/transforms/Transformation.java index ce05318d42195..94e48af4236c4 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/transforms/Transformation.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/transforms/Transformation.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.transforms; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.components.ConnectPlugin; import org.apache.kafka.connect.connector.ConnectRecord; @@ -36,6 +37,7 @@ * * @param The type of record (must be an implementation of {@link ConnectRecord}) */ +@InterfaceAudience.Public public interface Transformation> extends Configurable, Closeable, ConnectPlugin { /** diff --git a/connect/api/src/main/java/org/apache/kafka/connect/transforms/predicates/Predicate.java b/connect/api/src/main/java/org/apache/kafka/connect/transforms/predicates/Predicate.java index c957364690f14..0961f452dfc65 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/transforms/predicates/Predicate.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/transforms/predicates/Predicate.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.transforms.predicates; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.components.ConnectPlugin; import org.apache.kafka.connect.connector.ConnectRecord; @@ -37,6 +38,7 @@ * * @param The type of record. */ +@InterfaceAudience.Public public interface Predicate> extends Configurable, AutoCloseable, ConnectPlugin { diff --git a/connect/api/src/main/java/org/apache/kafka/connect/util/ConnectorUtils.java b/connect/api/src/main/java/org/apache/kafka/connect/util/ConnectorUtils.java index 7c09093a31626..9d97a8e7b9fb8 100644 --- a/connect/api/src/main/java/org/apache/kafka/connect/util/ConnectorUtils.java +++ b/connect/api/src/main/java/org/apache/kafka/connect/util/ConnectorUtils.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.util; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.ArrayList; import java.util.List; @@ -23,6 +26,7 @@ * Utilities that connector implementations might find useful. Contains common building blocks * for writing connectors. */ +@InterfaceAudience.Public public class ConnectorUtils { /** * Given a list of elements and a target number of groups, generates list of groups of diff --git a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/Checkpoint.java b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/Checkpoint.java index 3bfbca81bbca1..459d61a56d1ea 100644 --- a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/Checkpoint.java +++ b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/Checkpoint.java @@ -19,6 +19,8 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.errors.UnsupportedVersionException; import org.apache.kafka.common.protocol.types.Field; import org.apache.kafka.common.protocol.types.Schema; @@ -33,6 +35,7 @@ /** * Checkpoint records emitted by MirrorCheckpointConnector. */ +@InterfaceAudience.Public public class Checkpoint { public static final String TOPIC_KEY = "topic"; public static final String PARTITION_KEY = "partition"; @@ -43,16 +46,19 @@ public class Checkpoint { public static final String VERSION_KEY = "version"; public static final short VERSION = 0; + @SuppressKafkaInternalApiUsage("KIP-1265: public field exposes internal Schema type for the historical MirrorMaker wire format — pending KIP review to promote the type or refactor") public static final Schema VALUE_SCHEMA_V0 = new Schema( new Field(UPSTREAM_OFFSET_KEY, Type.INT64), new Field(DOWNSTREAM_OFFSET_KEY, Type.INT64), new Field(METADATA_KEY, Type.STRING)); + @SuppressKafkaInternalApiUsage("KIP-1265: public field exposes internal Schema type for the historical MirrorMaker wire format — pending KIP review to promote the type or refactor") public static final Schema KEY_SCHEMA = new Schema( new Field(CONSUMER_GROUP_ID_KEY, Type.STRING), new Field(TOPIC_KEY, Type.STRING), new Field(PARTITION_KEY, Type.INT32)); + @SuppressKafkaInternalApiUsage("KIP-1265: public field exposes internal Schema type for the historical MirrorMaker wire format — pending KIP review to promote the type or refactor") public static final Schema HEADER_SCHEMA = new Schema( new Field(VERSION_KEY, Type.INT16)); diff --git a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/DefaultReplicationPolicy.java b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/DefaultReplicationPolicy.java index ae273c36849a7..878eff5012215 100644 --- a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/DefaultReplicationPolicy.java +++ b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/DefaultReplicationPolicy.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.mirror; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,6 +31,7 @@ * For example, if the source cluster alias is "us-west", topics created in the target cluster will be named * us-west.<TOPIC>. The separator is customizable by setting {@link #SEPARATOR_CONFIG} and defaults to a period. */ +@InterfaceAudience.Public public class DefaultReplicationPolicy implements ReplicationPolicy, Configurable { private static final Logger log = LoggerFactory.getLogger(DefaultReplicationPolicy.class); diff --git a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/Heartbeat.java b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/Heartbeat.java index 42bc666fdd7e2..0b82c7f1ba310 100644 --- a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/Heartbeat.java +++ b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/Heartbeat.java @@ -17,6 +17,8 @@ package org.apache.kafka.connect.mirror; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.errors.UnsupportedVersionException; import org.apache.kafka.common.protocol.types.Field; import org.apache.kafka.common.protocol.types.Schema; @@ -30,6 +32,7 @@ /** * Heartbeat records emitted by MirrorHeartbeatConnector. */ +@InterfaceAudience.Public public class Heartbeat { public static final String SOURCE_CLUSTER_ALIAS_KEY = "sourceClusterAlias"; public static final String TARGET_CLUSTER_ALIAS_KEY = "targetClusterAlias"; @@ -37,13 +40,16 @@ public class Heartbeat { public static final String VERSION_KEY = "version"; public static final short VERSION = 0; + @SuppressKafkaInternalApiUsage("KIP-1265: public field exposes internal Schema type for the historical MirrorMaker wire format — pending KIP review to promote the type or refactor") public static final Schema VALUE_SCHEMA_V0 = new Schema( new Field(TIMESTAMP_KEY, Type.INT64)); + @SuppressKafkaInternalApiUsage("KIP-1265: public field exposes internal Schema type for the historical MirrorMaker wire format — pending KIP review to promote the type or refactor") public static final Schema KEY_SCHEMA = new Schema( new Field(SOURCE_CLUSTER_ALIAS_KEY, Type.STRING), new Field(TARGET_CLUSTER_ALIAS_KEY, Type.STRING)); + @SuppressKafkaInternalApiUsage("KIP-1265: public field exposes internal Schema type for the historical MirrorMaker wire format — pending KIP review to promote the type or refactor") public static final Schema HEADER_SCHEMA = new Schema( new Field(VERSION_KEY, Type.INT16)); diff --git a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/IdentityReplicationPolicy.java b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/IdentityReplicationPolicy.java index 1206becd5ee55..8c14ea81d7b64 100644 --- a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/IdentityReplicationPolicy.java +++ b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/IdentityReplicationPolicy.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.connect.mirror; +import org.apache.kafka.common.annotation.InterfaceAudience; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,6 +30,7 @@ * N.B. MirrorMaker is not able to prevent cycles when using this replication policy, so take care that * your replication topology is acyclic. If migrating from legacy MirrorMaker, this will likely already be the case. */ +@InterfaceAudience.Public public class IdentityReplicationPolicy extends DefaultReplicationPolicy { private static final Logger log = LoggerFactory.getLogger(IdentityReplicationPolicy.class); diff --git a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/MirrorClient.java b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/MirrorClient.java index 7275ce7202091..98200a7535287 100644 --- a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/MirrorClient.java +++ b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/MirrorClient.java @@ -25,6 +25,7 @@ import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.protocol.types.SchemaException; import org.apache.kafka.common.serialization.ByteArrayDeserializer; @@ -46,6 +47,7 @@ * Client to interact with MirrorMaker internal topics (checkpoints, heartbeats) on a given cluster. * Whenever possible use the methods from {@link RemoteClusterUtils} instead of directly using MirrorClient. */ +@InterfaceAudience.Public public class MirrorClient implements AutoCloseable { private static final Logger log = LoggerFactory.getLogger(MirrorClient.class); diff --git a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/MirrorClientConfig.java b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/MirrorClientConfig.java index cb42f5fe654ba..92629a3e7c5f5 100644 --- a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/MirrorClientConfig.java +++ b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/MirrorClientConfig.java @@ -21,6 +21,7 @@ import org.apache.kafka.clients.admin.ForwardingAdmin; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.AbstractConfig; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; @@ -48,6 +49,7 @@ * *

    */ +@InterfaceAudience.Public public class MirrorClientConfig extends AbstractConfig { public static final String REPLICATION_POLICY_CLASS = "replication.policy.class"; private static final String REPLICATION_POLICY_CLASS_DOC = "Class which defines the remote topic naming convention."; diff --git a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/RemoteClusterUtils.java b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/RemoteClusterUtils.java index 470d027dff581..658984d74d0bc 100644 --- a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/RemoteClusterUtils.java +++ b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/RemoteClusterUtils.java @@ -21,6 +21,7 @@ import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.time.Duration; import java.util.Map; @@ -28,7 +29,6 @@ import java.util.concurrent.TimeoutException; import java.util.regex.Pattern; - /** * Convenience tool for multi-cluster environments. Wraps {@link MirrorClient} *

    @@ -40,6 +40,7 @@ * * @see MirrorClientConfig for additional properties used by the internal MirrorClient. */ +@InterfaceAudience.Public public final class RemoteClusterUtils { // utility class diff --git a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/ReplicationPolicy.java b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/ReplicationPolicy.java index cb0fbe9910d3b..ef218137092e3 100644 --- a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/ReplicationPolicy.java +++ b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/ReplicationPolicy.java @@ -17,9 +17,12 @@ package org.apache.kafka.connect.mirror; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An interface used by the MirrorMaker connectors to manage topics names between source and target clusters. */ +@InterfaceAudience.Public public interface ReplicationPolicy { /** diff --git a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/SourceAndTarget.java b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/SourceAndTarget.java index 874d2ecde1656..e5aed32975f64 100644 --- a/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/SourceAndTarget.java +++ b/connect/mirror-client/src/main/java/org/apache/kafka/connect/mirror/SourceAndTarget.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.connect.mirror; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Directional pair of clusters, where source is mirrored to target. */ +@InterfaceAudience.Public public class SourceAndTarget { private final String source; private final String target; diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockConnector.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockConnector.java index f3a1b75439829..e8c49df3fdac7 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockConnector.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockConnector.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.tools; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.utils.internals.AppInfoParser; import org.apache.kafka.connect.connector.Connector; @@ -42,6 +43,7 @@ * @see MockSinkConnector * @see MockSourceConnector */ +@InterfaceAudience.Public public class MockConnector extends Connector { public static final String MOCK_MODE_KEY = "mock_mode"; public static final String DELAY_MS_KEY = "delay_ms"; diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSinkConnector.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSinkConnector.java index 84ceaf966fc41..9501b056bf082 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSinkConnector.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSinkConnector.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.tools; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.Config; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.connect.connector.ConnectorContext; @@ -28,6 +29,7 @@ /** * Mock sink implementation which delegates to {@link MockConnector}. */ +@InterfaceAudience.Public public class MockSinkConnector extends SinkConnector { private final MockConnector delegate = new MockConnector(); diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSinkTask.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSinkTask.java index 96c6beaab8a9e..cb94ed9a4cdac 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSinkTask.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSinkTask.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.tools; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.internals.AppInfoParser; import org.apache.kafka.connect.sink.SinkRecord; import org.apache.kafka.connect.sink.SinkTask; @@ -29,6 +30,7 @@ /** * Task implementation for {@link MockSinkConnector}. */ +@InterfaceAudience.Public public class MockSinkTask extends SinkTask { private static final Logger log = LoggerFactory.getLogger(MockSinkTask.class); diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSourceConnector.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSourceConnector.java index 1b6fc64dc369d..93a05f69003a3 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSourceConnector.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSourceConnector.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.tools; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.Config; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.connect.connector.ConnectorContext; @@ -28,6 +29,7 @@ /** * Mock source implementation which delegates to {@link MockConnector}. */ +@InterfaceAudience.Public public class MockSourceConnector extends SourceConnector { private final MockConnector delegate = new MockConnector(); diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSourceTask.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSourceTask.java index c5b83fe4b111b..d94042e8250bc 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSourceTask.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/MockSourceTask.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.tools; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.internals.AppInfoParser; import org.apache.kafka.connect.source.SourceRecord; import org.apache.kafka.connect.source.SourceTask; @@ -29,6 +30,7 @@ /** * Task implementation for {@link MockSourceConnector}. */ +@InterfaceAudience.Public public class MockSourceTask extends SourceTask { private static final Logger log = LoggerFactory.getLogger(MockSourceTask.class); diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/SchemaSourceConnector.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/SchemaSourceConnector.java index 0426ed26af8a9..c3b13423d2658 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/SchemaSourceConnector.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/SchemaSourceConnector.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.tools; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.utils.internals.AppInfoParser; import org.apache.kafka.connect.connector.Task; @@ -30,6 +31,7 @@ * A simple source connector that is capable of producing static data with * {@link org.apache.kafka.connect.data.Struct Struct} schemas. */ +@InterfaceAudience.Public public class SchemaSourceConnector extends SourceConnector { private Map config; diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/SchemaSourceTask.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/SchemaSourceTask.java index d79c133f67383..67dfb101f1ce4 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/SchemaSourceTask.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/SchemaSourceTask.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.tools; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.data.Schema; import org.apache.kafka.connect.data.SchemaBuilder; import org.apache.kafka.connect.data.Struct; @@ -33,6 +34,7 @@ /** * Task implementation for {@link SchemaSourceConnector}. */ +@InterfaceAudience.Public public class SchemaSourceTask extends SourceTask { private static final Logger log = LoggerFactory.getLogger(SchemaSourceTask.class); diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSinkConnector.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSinkConnector.java index e88ab7943315f..ea4095e17f663 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSinkConnector.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSinkConnector.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.tools; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.utils.internals.AppInfoParser; import org.apache.kafka.connect.connector.Task; @@ -30,6 +31,7 @@ * A connector primarily intended for system tests. * @see VerifiableSinkTask */ +@InterfaceAudience.Public public class VerifiableSinkConnector extends SinkConnector { private Map config; diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSinkTask.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSinkTask.java index 303e2a2ee0011..cbea6a588ae4e 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSinkTask.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSinkTask.java @@ -18,6 +18,7 @@ import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.errors.ConnectException; import org.apache.kafka.connect.sink.SinkRecord; import org.apache.kafka.connect.sink.SinkTask; @@ -37,6 +38,7 @@ * and failures. This task relies on the offset management provided by the Kafka Connect framework and therefore can detect * bugs in its implementation. */ +@InterfaceAudience.Public public class VerifiableSinkTask extends SinkTask { public static final String NAME_CONFIG = "name"; public static final String ID_CONFIG = "id"; diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSourceConnector.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSourceConnector.java index 002abb6e4a4d1..b2d31c6a7f876 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSourceConnector.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSourceConnector.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.connect.tools; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.utils.internals.AppInfoParser; import org.apache.kafka.connect.connector.Task; @@ -30,6 +31,7 @@ * A connector primarily intended for system tests. * @see VerifiableSourceTask */ +@InterfaceAudience.Public public class VerifiableSourceConnector extends SourceConnector { private Map config; diff --git a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSourceTask.java b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSourceTask.java index 1fe2bd318023c..8189422bb0965 100644 --- a/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSourceTask.java +++ b/connect/test-plugins/src/main/java/org/apache/kafka/connect/tools/VerifiableSourceTask.java @@ -17,6 +17,7 @@ package org.apache.kafka.connect.tools; import org.apache.kafka.clients.producer.RecordMetadata; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.connect.data.Schema; import org.apache.kafka.connect.data.SchemaBuilder; import org.apache.kafka.connect.data.Struct; @@ -45,6 +46,7 @@ *

    * If logging is left enabled, log output on stdout can be easily ignored by checking whether a given line is valid JSON. */ +@InterfaceAudience.Public public class VerifiableSourceTask extends SourceTask { private static final Logger log = LoggerFactory.getLogger(VerifiableSourceTask.class); diff --git a/docs/apis/internal-api-checker.md b/docs/apis/internal-api-checker.md new file mode 100644 index 0000000000000..7f1e5c47fcf8a --- /dev/null +++ b/docs/apis/internal-api-checker.md @@ -0,0 +1,181 @@ +--- +title: Internal API Checker +description: Detect references to non-public Kafka classes in your project's compiled bytecode. +weight: 7 +tags: ['kafka', 'docs'] +aliases: +keywords: +type: docs +--- + + + +# Internal API Checker + +[KIP-1265](https://cwiki.apache.org/confluence/display/KAFKA/KIP-1265%3A+Mechanism+for+automatic+detection+of+internal+API+usage) +ships a build-time checker that flags references from your compiled bytecode to Kafka classes +that are **not** marked `@InterfaceAudience.Public`. Apply it to your connector, Streams +application, or any project that depends on `org.apache.kafka:*` to catch internal-API usage +that would otherwise silently break when you upgrade Kafka. + +Bytecode scanning works uniformly for Java, Scala, Kotlin, and any other JVM language — +unlike a source-level grep on `import` lines, the checker catches fully-qualified references, +wildcard-imported types, and references introduced by code generators or compiler intrinsics. + +## Gradle + +```groovy +plugins { + id 'org.apache.kafka.internal-api-checker' version '{{< param fullDotVersion >}}' +} +``` + +The plugin registers a `kafkaInternalApiChecker` task in the `verification` group and hooks +it onto `check`, so `./gradlew check` will fail the build on any unsuppressed reference to an +internal Kafka class. + +Defaults are derived from the `java` plugin: the scan targets `sourceSets.main.output.classesDirs` +(works for Java, Scala, and Kotlin projects uniformly), and the `@InterfaceAudience.Public` +surface is built from the `org.apache.kafka:*` artifacts on `compileClasspath` and +`testCompileClasspath`. A Kafka version bump invalidates the task, so the check re-runs against +the new surface. + +Override only when the defaults don't fit: + +```groovy +kafkaInternalApiChecker { + enabled = true // default + failOnViolation = true // default + classDirs.from(files('extra-classes')) // extend the bytecode roots + // Replace if you keep Kafka jars on a non-standard configuration: + // kafkaDependencyJars.setFrom(configurations.myKafkaBundle) +} +``` + +### Skipping the check for one invocation + +Pass `-PkafkaInternalApiChecker.skip` (any truthy value, or no value at all) to disable the +check for that Gradle invocation without editing the build script: + +```bash +./gradlew check -PkafkaInternalApiChecker.skip +``` + +## Maven + +```xml + + org.apache.kafka + kafka-internal-api-checker-maven-plugin + {{< param fullDotVersion >}} + + + verify + verify + + + +``` + +The mojo binds to the `verify` phase and reads `${project.build.outputDirectory}` by default. + +## Reports + +Each run writes a text report to `build/reports/kafka-internal-api-usage.txt` +(`target/` for Maven). The report groups violations by type and by class, and lists any +suppressions separately so they can be audited. + +## Suppressing known references + +When a reference to an internal class is intentional — typically because the public-API +alternative is still being designed — annotate the class, method, or field with +`@SuppressKafkaInternalApiUsage` and include a one-line reason: + +```java +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; + +public class MyConnector implements SinkConnector { + + @SuppressKafkaInternalApiUsage("KIP-XYZ: replace with public API once finalised") + private final InternalKafkaHelper helper = new InternalKafkaHelper(); +} +``` + +Suppressed references move from the violations section of the report into a dedicated +**Suppressions** section, together with the reason supplied to the annotation, so +reviewers can audit every escape hatch on every build. + +The annotation lives in `kafka-clients`: + +```xml + + org.apache.kafka + kafka-clients + {{< param fullDotVersion >}} + +``` + +## Kafka version requirement + +The checker reads `@InterfaceAudience.Public` annotations off the **Kafka libraries your +project depends on at compile time**, not off the version of Kafka the checker plugin +itself was published from. If your project still depends on a Kafka release that pre-dates +KIP-1265 — i.e., one that doesn't yet carry the audience annotations on any class — the +checker will see zero public APIs and report every `org.apache.kafka.*` reference in your +bytecode as a violation, including references to genuinely-public types like +`KafkaProducer` or `Topology`. + +Make sure each `org.apache.kafka:*` dependency on your compile classpath +(`kafka-clients`, `kafka-streams`, `connect-api`, `kafka-tools-api`, …) is at least +`{{< param fullDotVersion >}}` before turning `failOnViolation = true`. For older +dependencies, either upgrade them, or temporarily set `failOnViolation = false` so the +checker only generates reports while you migrate. + +## What counts as "internal" + +A Kafka class is considered public when: + +1. It carries `@InterfaceAudience.Public` directly, **or** +2. It is a nested class whose nearest annotated enclosing class is `@InterfaceAudience.Public` + (Hadoop-style audience inheritance — see the KIP for details). + +Classes outside `org.apache.kafka.*` are out of scope; classes carrying `@Deprecated` are +treated as out of scope on both sides of the check so deprecated public APIs you still +reference don't appear as violations. + +## Known limitations + +The bytecode scanner walks every callable instruction, field type, declared exception, and +generic signature in your compiled classes, but a few reference kinds are intentionally not +followed. In practice these don't show up in plugin/connector code, but a "0 violations" +report does not strictly exclude them: + +- **Parameter annotations.** A `@InternalAnno`-typed parameter annotation isn't walked + (the method header itself still is, so the parameter's type and the method's return / + exception types are all caught). +- **Type-use annotations.** JSR 308 type-use annotations attached to type positions like + `List<@InternalAnno String>` aren't walked — these are typically used only by + static-analysis tooling, and the underlying type is still recorded. +- **Class literals exclusively inside annotation element values.** A class literal that + *only* appears in an annotation value (e.g. `@SomeAnnotation(impl = InternalClass.class)`) + won't be flagged. The same `InternalClass.class` loaded into any local variable or method + return *is* caught via `LDC` instructions. +- **Inlined compile-time constants.** Java inlines `public static final` primitive and + `String` constants at the use site, so referencing + `InternalKafkaClass.SOME_CONSTANT_STRING` leaves no class reference in your bytecode and + cannot be detected. This is documented in the KIP. diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/ConsumerGroupPartitionAssignor.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/ConsumerGroupPartitionAssignor.java index b0febdfcff3c7..26b667c0d491f 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/ConsumerGroupPartitionAssignor.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/ConsumerGroupPartitionAssignor.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.coordinator.group.api.assignor; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Server-side partition assignor for consumer groups used by the GroupCoordinator. */ +@InterfaceAudience.Public public interface ConsumerGroupPartitionAssignor extends PartitionAssignor { } diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/GroupAssignment.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/GroupAssignment.java index 4464ddded42e4..12a2d988554c7 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/GroupAssignment.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/GroupAssignment.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.coordinator.group.api.assignor; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Map; import java.util.Objects; /** * The partition assignment for a consumer group. */ +@InterfaceAudience.Public public class GroupAssignment { /** * The member assignments keyed by member id. diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/GroupSpec.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/GroupSpec.java index 3f2d2ca257101..8ec599232c687 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/GroupSpec.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/GroupSpec.java @@ -14,15 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.coordinator.group.api.assignor; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collection; /** * The group metadata specifications required to compute the target assignment. */ +@InterfaceAudience.Public public interface GroupSpec { /** * @return All the member Ids of the consumer group. diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/MemberAssignment.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/MemberAssignment.java index 07f48649d72be..5f6bba567b63c 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/MemberAssignment.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/MemberAssignment.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.coordinator.group.api.assignor; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; import java.util.Set; @@ -24,6 +26,7 @@ /** * The partition assignment for a consumer group member. */ +@InterfaceAudience.Public public interface MemberAssignment { /** * @return The assigned partitions keyed by topic Ids. diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/MemberSubscription.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/MemberSubscription.java index 9de2b14cfead4..269a8b6562b02 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/MemberSubscription.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/MemberSubscription.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.coordinator.group.api.assignor; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Optional; import java.util.Set; @@ -24,6 +26,7 @@ /** * Interface representing the subscription metadata for a group member. */ +@InterfaceAudience.Public public interface MemberSubscription { /** * Gets the rack Id if present. diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/PartitionAssignor.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/PartitionAssignor.java index 10e7ecdd6cf8e..b05437a4f6a6f 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/PartitionAssignor.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/PartitionAssignor.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.coordinator.group.api.assignor; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Server-side partition assignor used by the GroupCoordinator. */ +@InterfaceAudience.Public public interface PartitionAssignor { /** * Unique name for this assignor. diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/PartitionAssignorException.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/PartitionAssignorException.java index deb2e09b402d0..90707c0d69c94 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/PartitionAssignorException.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/PartitionAssignorException.java @@ -16,12 +16,14 @@ */ package org.apache.kafka.coordinator.group.api.assignor; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.ApiException; /** * Exception thrown by {@link PartitionAssignor#assign(GroupSpec, SubscribedTopicDescriber)}}. The exception * is only used internally. */ +@InterfaceAudience.Public public class PartitionAssignorException extends ApiException { public PartitionAssignorException(String message) { diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/ShareGroupPartitionAssignor.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/ShareGroupPartitionAssignor.java index b285c76a43276..e5f3fe3a91bec 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/ShareGroupPartitionAssignor.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/ShareGroupPartitionAssignor.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.coordinator.group.api.assignor; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Server-side partition assignor for share groups used by the GroupCoordinator. */ +@InterfaceAudience.Public public interface ShareGroupPartitionAssignor extends PartitionAssignor { } diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/SubscribedTopicDescriber.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/SubscribedTopicDescriber.java index 2373162c2c9b9..a3e217ea83cec 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/SubscribedTopicDescriber.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/SubscribedTopicDescriber.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.coordinator.group.api.assignor; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Set; @@ -24,6 +26,7 @@ * The subscribed topic describer is used by the {@link PartitionAssignor} * to obtain topic and partition metadata of the subscribed topics. */ +@InterfaceAudience.Public public interface SubscribedTopicDescriber { /** * The number of partitions for the given topic Id. diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/SubscriptionType.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/SubscriptionType.java index bd429eb9d150b..6a49ccb24e9dc 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/SubscriptionType.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/assignor/SubscriptionType.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.coordinator.group.api.assignor; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The subscription type followed by a consumer group. */ +@InterfaceAudience.Public public enum SubscriptionType { /** * A homogeneous subscription type means that all the members diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsGroupTopologyDescription.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsGroupTopologyDescription.java index a5f242ed5a56e..825e9ffa669d0 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsGroupTopologyDescription.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsGroupTopologyDescription.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.coordinator.group.api.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.Collection; @@ -36,6 +37,7 @@ * relation; plugins that need both directions reconstruct predecessors in a single * pass over the nodes. */ +@InterfaceAudience.Public @InterfaceStability.Evolving public record StreamsGroupTopologyDescription( Collection subtopologies, diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsGroupTopologyDescriptionPlugin.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsGroupTopologyDescriptionPlugin.java index 4bb6d13cf8d5b..5f6409a40ac89 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsGroupTopologyDescriptionPlugin.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsGroupTopologyDescriptionPlugin.java @@ -17,6 +17,7 @@ package org.apache.kafka.coordinator.group.api.streams; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import java.util.concurrent.CompletableFuture; @@ -31,6 +32,7 @@ * {@link #deleteTopology} must also be idempotent — it may be called more than once * for the same {@code groupId}, including when nothing is stored. */ +@InterfaceAudience.Public @InterfaceStability.Evolving public interface StreamsGroupTopologyDescriptionPlugin extends Configurable, AutoCloseable { diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsTopologyDescriptionPermanentFailureException.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsTopologyDescriptionPermanentFailureException.java index a11fc9bb0fc06..02c68ab4f7b4f 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsTopologyDescriptionPermanentFailureException.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsTopologyDescriptionPermanentFailureException.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.coordinator.group.api.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import org.apache.kafka.common.errors.ApiException; @@ -23,6 +24,7 @@ * Signals that the topology description for the current epoch will never be accepted * (e.g. too large, semantically rejected). */ +@InterfaceAudience.Public @InterfaceStability.Evolving public class StreamsTopologyDescriptionPermanentFailureException extends ApiException { diff --git a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsTopologyDescriptionTransientFailureException.java b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsTopologyDescriptionTransientFailureException.java index 29faaa111d33c..9d600e6eabfa4 100644 --- a/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsTopologyDescriptionTransientFailureException.java +++ b/group-coordinator/group-coordinator-api/src/main/java/org/apache/kafka/coordinator/group/api/streams/StreamsTopologyDescriptionTransientFailureException.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.coordinator.group.api.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability; import org.apache.kafka.common.errors.ApiException; @@ -23,6 +24,7 @@ * Signals a transient backend failure; the broker re-solicits on a later heartbeat. * Any other exception completed on the future is treated identically. */ +@InterfaceAudience.Public @InterfaceStability.Evolving public class StreamsTopologyDescriptionTransientFailureException extends ApiException { diff --git a/release/release.py b/release/release.py index 11aa9570d1b5c..47f82c9080d29 100644 --- a/release/release.py +++ b/release/release.py @@ -346,6 +346,23 @@ def delete_gitrefs(): confirm_or_fail("Going to build and upload mvn artifacts based on these settings:\n" + textfiles.read(global_gradle_props) + '\nOK?') cmd("Building and uploading archives", "./gradlew publish -PscalaVersion=2.13", cwd=kafka_dir, env=jdk25_env, shell=True) +# Publishes the KIP-1265 plugin artifacts to the same Nexus staging repo. The api-checker +# tree is a separate Gradle build (composite/included) so the root :publish task does not +# descend into it. The five coordinates uploaded here are: +# org.apache.kafka:kafka-api-checker-core (shared scanner/reporter jar) +# org.apache.kafka:kafka-internal-api-checker-gradle-plugin (Gradle plugin impl jar) +# org.apache.kafka.internal-api-checker:org.apache.kafka.internal-api-checker.gradle.plugin +# (Gradle plugin marker) +# org.apache.kafka.public-api-checker:org.apache.kafka.public-api-checker.gradle.plugin +# (Kafka-internal plugin marker) +# org.apache.kafka:kafka-internal-api-checker-maven-plugin (Maven plugin) +# The version is read from the root gradle.properties — release.py has already bumped it +# via `updateVersion` above — and the included build's allprojects block picks it up +# automatically. Publish credentials come from ~/.gradle/gradle.properties (mavenUrl / +# mavenUsername / mavenPassword). +cmd("Building and uploading archives", + "./gradlew :api-checker:core:publish :api-checker:gradle-plugins:publish :api-checker:maven-plugin:publish -PscalaVersion=2.13", + cwd=kafka_dir, env=jdk25_env, shell=True) cmd("Building and uploading archives", "mvn deploy -Pgpg-signing", cwd=os.path.join(kafka_dir, "streams/quickstart"), env=jdk25_env, shell=True) # TODO: Many of these suggested validation steps could be automated diff --git a/server/src/main/java/org/apache/kafka/server/share/fetch/InFlightState.java b/server/src/main/java/org/apache/kafka/server/share/fetch/InFlightState.java index c5e9cb5c1afeb..d061e50c587f6 100644 --- a/server/src/main/java/org/apache/kafka/server/share/fetch/InFlightState.java +++ b/server/src/main/java/org/apache/kafka/server/share/fetch/InFlightState.java @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.server.share.fetch; +package org.apache.kafka.server.share.fetch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/settings.gradle b/settings.gradle index 340cbecd26c35..f051ac2496a85 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +pluginManagement { + // Exposes the api-checker plugins (org.apache.kafka.public-api-checker and + // org.apache.kafka.internal-api-checker) to Kafka's own build by ID. The api-checker + // tree is a separate Gradle build, so its Maven runtime dependencies don't end up on + // every developer's main-build classpath, and each published artifact carries only + // the classes its consumers need. + includeBuild 'api-checker' +} + plugins { id 'com.gradle.develocity' version '3.19' id 'com.gradle.common-custom-user-data-gradle-plugin' version '2.0.2' diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/LogSegmentData.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/LogSegmentData.java index 78ebc657aa931..028218bed0b03 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/LogSegmentData.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/LogSegmentData.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.nio.ByteBuffer; import java.nio.file.Path; import java.util.Objects; @@ -26,6 +29,7 @@ * storage. This is passed with {@link RemoteStorageManager#copyLogSegmentData(RemoteLogSegmentMetadata, LogSegmentData)} * while copying a specific log segment to the remote storage. */ +@InterfaceAudience.Public public class LogSegmentData { private final Path logSegment; diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogMetadata.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogMetadata.java index a5ce5779196f8..b6af987fc946e 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogMetadata.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogMetadata.java @@ -14,14 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; import org.apache.kafka.common.TopicIdPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Base class for remote log metadata objects like {@link RemoteLogSegmentMetadata}, {@link RemoteLogSegmentMetadataUpdate}, * and {@link RemotePartitionDeleteMetadata}. */ +@InterfaceAudience.Public public abstract class RemoteLogMetadata { /** diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogMetadataManager.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogMetadataManager.java index 189e0a1713e31..4e30c59bbc090 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogMetadataManager.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogMetadataManager.java @@ -14,10 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; import org.apache.kafka.common.Configurable; import org.apache.kafka.common.TopicIdPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.io.Closeable; import java.util.Iterator; @@ -52,6 +54,7 @@ * The following tags are automatically added to all metrics registered: config set to * remote.log.metadata.manager.class.name, and class set to the RemoteLogMetadataManager class name. */ +@InterfaceAudience.Public public interface RemoteLogMetadataManager extends Configurable, Closeable { /** diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentId.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentId.java index f1d30a6275347..ceb9455cb1e0e 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentId.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentId.java @@ -14,10 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; import org.apache.kafka.common.TopicIdPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Objects; @@ -26,6 +28,7 @@ * regenerated for every attempt of copying a specific log segment in {@link RemoteStorageManager#copyLogSegmentData(RemoteLogSegmentMetadata, LogSegmentData)}. * Once it is stored in remote storage, it is used to access that segment later from remote log metadata storage. */ +@InterfaceAudience.Public public class RemoteLogSegmentId { private final TopicIdPartition topicIdPartition; diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentMetadata.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentMetadata.java index 7eff2673f6ebd..33dc229f616bd 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentMetadata.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentMetadata.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; import org.apache.kafka.common.TopicIdPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Arrays; import java.util.Collections; @@ -34,6 +36,7 @@ * updated by applying {@link RemoteLogSegmentMetadataUpdate} for the respective {@link RemoteLogSegmentId} of the * {@code RemoteLogSegmentMetadata}. */ +@InterfaceAudience.Public public class RemoteLogSegmentMetadata extends RemoteLogMetadata { /** diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentMetadataUpdate.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentMetadataUpdate.java index aea6bb0cd9195..373b13ebab1b0 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentMetadataUpdate.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentMetadataUpdate.java @@ -17,6 +17,7 @@ package org.apache.kafka.server.log.remote.storage; import org.apache.kafka.common.TopicIdPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.server.log.remote.storage.RemoteLogSegmentMetadata.CustomMetadata; import java.util.Objects; @@ -27,6 +28,7 @@ * state of the remote log segment by using {@link RemoteLogMetadataManager#updateRemoteLogSegmentMetadata(RemoteLogSegmentMetadataUpdate)}. * This also includes the timestamp of this event. */ +@InterfaceAudience.Public public class RemoteLogSegmentMetadataUpdate extends RemoteLogMetadata { /** diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentState.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentState.java index 8418f817deb79..f78cf005ce769 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentState.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteLogSegmentState.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -48,6 +51,7 @@ * +-----------------------+ * */ +@InterfaceAudience.Public public enum RemoteLogSegmentState { /** diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemotePartitionDeleteMetadata.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemotePartitionDeleteMetadata.java index ad187a1240095..cc29dc0c2d439 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemotePartitionDeleteMetadata.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemotePartitionDeleteMetadata.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; import org.apache.kafka.common.TopicIdPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Objects; @@ -24,6 +26,7 @@ * This class represents the metadata about the remote partition. It can be created/updated with {@link RemoteLogMetadataManager#putRemotePartitionDeleteMetadata(RemotePartitionDeleteMetadata)}. * Possible state transitions are mentioned at {@link RemotePartitionDeleteState}. */ +@InterfaceAudience.Public public class RemotePartitionDeleteMetadata extends RemoteLogMetadata { private final TopicIdPartition topicIdPartition; diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemotePartitionDeleteState.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemotePartitionDeleteState.java index 108acf05504cf..e4a7df0c7072f 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemotePartitionDeleteState.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemotePartitionDeleteState.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -46,6 +49,7 @@ * *

    */ +@InterfaceAudience.Public public enum RemotePartitionDeleteState { /** diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteResourceNotFoundException.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteResourceNotFoundException.java index f6ac4ec5ccc19..1b68f91d50935 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteResourceNotFoundException.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteResourceNotFoundException.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Exception thrown when a resource is not found on the remote storage. *

    * A resource can be a log segment, any of the indexes or any which was stored in remote storage for a particular log * segment. */ +@InterfaceAudience.Public public class RemoteResourceNotFoundException extends RemoteStorageException { private static final long serialVersionUID = 1L; diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageException.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageException.java index bd392fc674c90..739561e70d205 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageException.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Exception thrown when there is a remote storage error. This can be used as the base exception by implementors of * {@link RemoteStorageManager} or {@link RemoteLogMetadataManager} to create extended exceptions. */ +@InterfaceAudience.Public public class RemoteStorageException extends Exception { private static final long serialVersionUID = 1L; diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageManager.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageManager.java index e17e3af596d65..91252e0b0219d 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageManager.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageManager.java @@ -17,6 +17,7 @@ package org.apache.kafka.server.log.remote.storage; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.server.log.remote.storage.RemoteLogSegmentMetadata.CustomMetadata; import java.io.Closeable; @@ -49,6 +50,7 @@ * {@link RemoteStorageException} should be thrown. This distinction allows RemoteLogManager to * handle retries gracefully and report metrics accurately. */ +@InterfaceAudience.Public public interface RemoteStorageManager extends Configurable, Closeable { /** diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageMetrics.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageMetrics.java index 05c380c637ce9..fdd8896ab95da 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageMetrics.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageMetrics.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.server.log.remote.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.server.metrics.KafkaYammerMetrics; import com.yammer.metrics.core.MetricName; @@ -27,6 +28,7 @@ * This class contains the metrics related to tiered storage feature, which is to have a centralized * place to store them, so that we can verify all of them easily. */ +@InterfaceAudience.Public public class RemoteStorageMetrics { private static final String REMOTE_LOG_READER_METRICS_NAME_PREFIX = "RemoteLogReader"; private static final String REMOTE_LOG_MANAGER_TASKS_AVG_IDLE_PERCENT = "RemoteLogManagerTasksAvgIdlePercent"; diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageNotReadyException.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageNotReadyException.java index e36fd307a517d..68f94b74c1073 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageNotReadyException.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RemoteStorageNotReadyException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * This exception is thrown when a remote storage operation cannot proceed because the remote storage is not ready. * This may occur in situations where the remote storage (or) metadata layer is initializing, unreachable, @@ -24,6 +27,7 @@ * Instances of this exception indicate that the error is retriable, and the operation might * succeed if attempted again when the remote storage (or) metadata layer becomes operational. */ +@InterfaceAudience.Public public class RemoteStorageNotReadyException extends RetriableRemoteStorageException { public RemoteStorageNotReadyException(String message) { diff --git a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RetriableRemoteStorageException.java b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RetriableRemoteStorageException.java index de180ebbaa867..f867c8b0f8f51 100644 --- a/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RetriableRemoteStorageException.java +++ b/storage/api/src/main/java/org/apache/kafka/server/log/remote/storage/RetriableRemoteStorageException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.server.log.remote.storage; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Represents an exception that indicates a retriable error occurred during remote storage operations. * This exception is thrown when an operation against a remote storage system has failed due to transient * or temporary issues, and the operation has a reasonable chance of succeeding if retried. */ +@InterfaceAudience.Public public class RetriableRemoteStorageException extends RemoteStorageException { private static final long serialVersionUID = 1L; diff --git a/storage/src/testFixtures/java/org/apache/kafka/server/log/remote/storage/LocalTieredStorageListener.java b/storage/src/testFixtures/java/org/apache/kafka/server/log/remote/storage/LocalTieredStorageListener.java index fcc874467d626..a3dfb210a6881 100644 --- a/storage/src/testFixtures/java/org/apache/kafka/server/log/remote/storage/LocalTieredStorageListener.java +++ b/storage/src/testFixtures/java/org/apache/kafka/server/log/remote/storage/LocalTieredStorageListener.java @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.server.log.remote.storage; +package org.apache.kafka.server.log.remote.storage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/streams/src/main/java/org/apache/kafka/streams/AutoOffsetReset.java b/streams/src/main/java/org/apache/kafka/streams/AutoOffsetReset.java index f3f3a941d20f7..889e6ce2590b1 100644 --- a/streams/src/main/java/org/apache/kafka/streams/AutoOffsetReset.java +++ b/streams/src/main/java/org/apache/kafka/streams/AutoOffsetReset.java @@ -17,6 +17,8 @@ package org.apache.kafka.streams; import org.apache.kafka.clients.consumer.internals.AutoOffsetResetStrategy.StrategyType; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.streams.kstream.KStream; import org.apache.kafka.streams.kstream.KTable; @@ -28,7 +30,9 @@ * {@link Topology#addSource(AutoOffsetReset, String, String...) adding a source processor} * or when creating {@link KStream} or {@link KTable} via {@link StreamsBuilder}. */ +@InterfaceAudience.Public public class AutoOffsetReset { + @SuppressKafkaInternalApiUsage("KIP-1265: protected field exposes internal StrategyType for subclass access — pending KIP review to promote the type or refactor") protected final StrategyType offsetResetStrategy; protected final Optional duration; diff --git a/streams/src/main/java/org/apache/kafka/streams/ClientInstanceIds.java b/streams/src/main/java/org/apache/kafka/streams/ClientInstanceIds.java index 48dfcf9f92fa9..3651add7ee7b5 100644 --- a/streams/src/main/java/org/apache/kafka/streams/ClientInstanceIds.java +++ b/streams/src/main/java/org/apache/kafka/streams/ClientInstanceIds.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Map; @@ -24,6 +26,7 @@ * Encapsulates the {@code client instance id} used for metrics collection by * producers, consumers, and the admin client used by Kafka Streams. */ +@InterfaceAudience.Public public interface ClientInstanceIds { /** * Returns the {@code client instance id} of the admin client. diff --git a/streams/src/main/java/org/apache/kafka/streams/CloseOptions.java b/streams/src/main/java/org/apache/kafka/streams/CloseOptions.java index 9e0158be9d2bd..d70ee6c8cfb9b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/CloseOptions.java +++ b/streams/src/main/java/org/apache/kafka/streams/CloseOptions.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.time.Duration; import java.util.Objects; import java.util.Optional; +@InterfaceAudience.Public public class CloseOptions { /** * Enum to specify the group membership operation upon closing the Kafka Streams application. diff --git a/streams/src/main/java/org/apache/kafka/streams/DslStoreFormat.java b/streams/src/main/java/org/apache/kafka/streams/DslStoreFormat.java index 02bfdfad743eb..f6e006a4dfaaf 100644 --- a/streams/src/main/java/org/apache/kafka/streams/DslStoreFormat.java +++ b/streams/src/main/java/org/apache/kafka/streams/DslStoreFormat.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Locale; +@InterfaceAudience.Public public enum DslStoreFormat { /** The non-timestamped state stores */ diff --git a/streams/src/main/java/org/apache/kafka/streams/GroupProtocol.java b/streams/src/main/java/org/apache/kafka/streams/GroupProtocol.java index 146a5e6e9de4a..0cf33adf66650 100644 --- a/streams/src/main/java/org/apache/kafka/streams/GroupProtocol.java +++ b/streams/src/main/java/org/apache/kafka/streams/GroupProtocol.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Locale; +@InterfaceAudience.Public public enum GroupProtocol { /** Classic group protocol. */ CLASSIC("CLASSIC"), diff --git a/streams/src/main/java/org/apache/kafka/streams/KafkaClientSupplier.java b/streams/src/main/java/org/apache/kafka/streams/KafkaClientSupplier.java index fc96ca701c6ac..d136c3071a55d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/KafkaClientSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/KafkaClientSupplier.java @@ -19,6 +19,7 @@ import org.apache.kafka.clients.admin.Admin; import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.producer.Producer; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.kstream.GlobalKTable; import org.apache.kafka.streams.processor.StateStore; @@ -29,6 +30,7 @@ * * @see KafkaStreams#KafkaStreams(Topology, java.util.Properties, KafkaClientSupplier) */ +@InterfaceAudience.Public public interface KafkaClientSupplier { /** * Create an {@link Admin} which is used for internal topic management. diff --git a/streams/src/main/java/org/apache/kafka/streams/KafkaStreams.java b/streams/src/main/java/org/apache/kafka/streams/KafkaStreams.java index 11f4f53a1fa7c..0c2b5582fa6ab 100644 --- a/streams/src/main/java/org/apache/kafka/streams/KafkaStreams.java +++ b/streams/src/main/java/org/apache/kafka/streams/KafkaStreams.java @@ -26,7 +26,9 @@ import org.apache.kafka.common.MetricName; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.Uuid; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.errors.TimeoutException; import org.apache.kafka.common.metrics.KafkaMetricsContext; import org.apache.kafka.common.metrics.MetricConfig; @@ -156,6 +158,7 @@ * @see org.apache.kafka.streams.StreamsBuilder * @see org.apache.kafka.streams.Topology */ +@InterfaceAudience.Public public class KafkaStreams implements AutoCloseable { private static final String JMX_PREFIX = "kafka.streams"; @@ -169,7 +172,9 @@ public class KafkaStreams implements AutoCloseable { protected final String clientId; private final Metrics metrics; protected final StreamsConfig applicationConfigs; + @SuppressKafkaInternalApiUsage("KIP-1265: protected field's generic signature exposes internal StreamThread for subclass access — pending KIP review to promote the type or refactor") protected final List threads; + @SuppressKafkaInternalApiUsage("KIP-1265: protected field exposes internal StreamsMetadataState for subclass access — pending KIP review to promote the type or refactor") protected final StreamsMetadataState streamsMetadataState; private final ScheduledExecutorService stateDirCleaner; private final ScheduledExecutorService rocksDBMetricsRecordingService; @@ -180,12 +185,14 @@ public class KafkaStreams implements AutoCloseable { private final DelegatingStateRestoreListener delegatingStateRestoreListener; private final UUID processId; private final KafkaClientSupplier clientSupplier; + @SuppressKafkaInternalApiUsage("KIP-1265: protected field exposes internal TopologyMetadata for subclass access — pending KIP review to promote the type or refactor") protected final TopologyMetadata topologyMetadata; private final QueryableStoreProvider queryableStoreProvider; private final DelegatingStandbyUpdateListener delegatingStandbyUpdateListener; private final LogContext logContext; GlobalStreamThread globalStreamThread; + @SuppressKafkaInternalApiUsage("KIP-1265: protected field exposes internal StateDirectory for subclass access — pending KIP review to promote the type or refactor") protected StateDirectory stateDirectory = null; private KafkaStreams.StateListener stateListener; private BiConsumer streamsUncaughtExceptionHandler; @@ -848,6 +855,7 @@ public KafkaStreams(final Topology topology, * @param time {@code Time} implementation; cannot be null * @throws StreamsException if any fatal error occurs */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public KafkaStreams(final Topology topology, final Properties props, final Time time) { @@ -867,6 +875,7 @@ public KafkaStreams(final Topology topology, * @param time {@code Time} implementation; cannot be null * @throws StreamsException if any fatal error occurs */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public KafkaStreams(final Topology topology, final Properties props, final KafkaClientSupplier clientSupplier, @@ -918,6 +927,7 @@ public KafkaStreams(final Topology topology, * @param time {@code Time} implementation; cannot be null * @throws StreamsException if any fatal error occurs */ + @SuppressKafkaInternalApiUsage("KIP-1265: ctor leaks internal Time for test injection — pending KIP review to promote Time or refactor") public KafkaStreams(final Topology topology, final StreamsConfig applicationConfigs, final Time time) { @@ -931,6 +941,7 @@ private KafkaStreams(final Topology topology, this(new TopologyMetadata(topology.internalTopologyBuilder, applicationConfigs), applicationConfigs, clientSupplier, time); } + @SuppressKafkaInternalApiUsage("KIP-1265: protected ctor takes internal TopologyMetadata as a subclass extension point — pending KIP review to promote the type or refactor") protected KafkaStreams(final TopologyMetadata topologyMetadata, final StreamsConfig applicationConfigs, final KafkaClientSupplier clientSupplier) throws StreamsException { @@ -1886,6 +1897,7 @@ public void resume() { * threads lock when looping threads. * @param consumer handler */ + @SuppressKafkaInternalApiUsage("KIP-1265: protected method's signature exposes internal StreamThread for subclass access — pending KIP review to promote the type or refactor") protected int processStreamThread(final Consumer consumer) { final List copy = new ArrayList<>(threads); for (final StreamThread thread : copy) consumer.accept(thread); @@ -2058,6 +2070,7 @@ public Map> allLocalStorePartitionLags() { return allLocalStorePartitionLags(allTasks); } + @SuppressKafkaInternalApiUsage("KIP-1265: protected method's signature exposes internal Task for subclass access — pending KIP review to promote the type or refactor") protected Map> allLocalStorePartitionLags(final List tasksToCollectLagFor) { final Map> localStorePartitionLags = new TreeMap<>(); final Collection allPartitions = new LinkedList<>(); diff --git a/streams/src/main/java/org/apache/kafka/streams/KeyQueryMetadata.java b/streams/src/main/java/org/apache/kafka/streams/KeyQueryMetadata.java index a81cfba73817d..a2c40c3fcd8ce 100644 --- a/streams/src/main/java/org/apache/kafka/streams/KeyQueryMetadata.java +++ b/streams/src/main/java/org/apache/kafka/streams/KeyQueryMetadata.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.state.HostInfo; import java.util.Collections; @@ -29,6 +30,7 @@ * e.g: Relating with lags for that store partition. * NOTE: This is a point in time view. It may change as rebalances happen. */ +@InterfaceAudience.Public public class KeyQueryMetadata { /** * Sentinel to indicate that the KeyQueryMetadata is currently unavailable. This can occur during rebalance diff --git a/streams/src/main/java/org/apache/kafka/streams/KeyValue.java b/streams/src/main/java/org/apache/kafka/streams/KeyValue.java index d9d38c39378e3..a8f06810fa4db 100644 --- a/streams/src/main/java/org/apache/kafka/streams/KeyValue.java +++ b/streams/src/main/java/org/apache/kafka/streams/KeyValue.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** @@ -25,6 +28,7 @@ * @param Key type * @param Value type */ +@InterfaceAudience.Public public class KeyValue { /** The key of the key-value pair. */ diff --git a/streams/src/main/java/org/apache/kafka/streams/LagInfo.java b/streams/src/main/java/org/apache/kafka/streams/LagInfo.java index 0121db30239d9..7db81ae632e9a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/LagInfo.java +++ b/streams/src/main/java/org/apache/kafka/streams/LagInfo.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * Encapsulates information about lag, at a store partition replica (active or standby). This information is constantly changing as the * tasks process records and thus, they should be treated as simply instantaneous measure of lag. */ +@InterfaceAudience.Public public class LagInfo { private final long currentOffsetPosition; diff --git a/streams/src/main/java/org/apache/kafka/streams/StoreQueryParameters.java b/streams/src/main/java/org/apache/kafka/streams/StoreQueryParameters.java index b76f310d8d526..ef376acb5466b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/StoreQueryParameters.java +++ b/streams/src/main/java/org/apache/kafka/streams/StoreQueryParameters.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.state.QueryableStoreType; import java.util.Objects; @@ -23,6 +24,7 @@ /** * {@code StoreQueryParameters} allows you to pass a variety of parameters when fetching a store for interactive query. */ +@InterfaceAudience.Public public class StoreQueryParameters { private final Integer partition; diff --git a/streams/src/main/java/org/apache/kafka/streams/StreamsBuilder.java b/streams/src/main/java/org/apache/kafka/streams/StreamsBuilder.java index a7483bc1452d3..6854a30af9215 100644 --- a/streams/src/main/java/org/apache/kafka/streams/StreamsBuilder.java +++ b/streams/src/main/java/org/apache/kafka/streams/StreamsBuilder.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.errors.TopologyException; import org.apache.kafka.streams.kstream.Consumed; @@ -62,14 +64,17 @@ * @see KTable * @see GlobalKTable */ +@InterfaceAudience.Public public class StreamsBuilder { /** The actual topology that is constructed by this StreamsBuilder. */ protected final Topology topology; /** The topology's internal builder. */ + @SuppressKafkaInternalApiUsage("KIP-1265: protected field exposes internal InternalTopologyBuilder for subclass access — pending KIP review to promote the type or refactor") protected final InternalTopologyBuilder internalTopologyBuilder; + @SuppressKafkaInternalApiUsage("KIP-1265: protected field exposes internal InternalStreamsBuilder for subclass access — pending KIP review to promote the type or refactor") protected final InternalStreamsBuilder internalStreamsBuilder; public StreamsBuilder() { diff --git a/streams/src/main/java/org/apache/kafka/streams/StreamsConfig.java b/streams/src/main/java/org/apache/kafka/streams/StreamsConfig.java index 220268c75aceb..bc33f7308690d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/StreamsConfig.java +++ b/streams/src/main/java/org/apache/kafka/streams/StreamsConfig.java @@ -25,6 +25,7 @@ import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.common.IsolationLevel; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.AbstractConfig; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; @@ -159,6 +160,7 @@ * @see ConsumerConfig * @see ProducerConfig */ +@InterfaceAudience.Public public class StreamsConfig extends AbstractConfig { private static final Logger log = LoggerFactory.getLogger(StreamsConfig.class); diff --git a/streams/src/main/java/org/apache/kafka/streams/StreamsMetadata.java b/streams/src/main/java/org/apache/kafka/streams/StreamsMetadata.java index c751325f942af..6b60b15241070 100644 --- a/streams/src/main/java/org/apache/kafka/streams/StreamsMetadata.java +++ b/streams/src/main/java/org/apache/kafka/streams/StreamsMetadata.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.state.HostInfo; import java.util.Set; @@ -24,6 +25,7 @@ /** * Metadata of a Kafka Streams client. */ +@InterfaceAudience.Public public interface StreamsMetadata { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/StreamsMetrics.java b/streams/src/main/java/org/apache/kafka/streams/StreamsMetrics.java index 3f29bf972bcb1..e656222704b3b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/StreamsMetrics.java +++ b/streams/src/main/java/org/apache/kafka/streams/StreamsMetrics.java @@ -18,6 +18,7 @@ import org.apache.kafka.common.Metric; import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.metrics.Sensor; import java.util.Map; @@ -25,6 +26,7 @@ /** * The Kafka Streams metrics interface for adding metric sensors and collecting metric values. */ +@InterfaceAudience.Public public interface StreamsMetrics { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/TaskMetadata.java b/streams/src/main/java/org/apache/kafka/streams/TaskMetadata.java index 0ef742930f94e..702b285e2d56e 100644 --- a/streams/src/main/java/org/apache/kafka/streams/TaskMetadata.java +++ b/streams/src/main/java/org/apache/kafka/streams/TaskMetadata.java @@ -14,19 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TaskId; import java.util.Map; import java.util.Optional; import java.util.Set; - /** * Metadata of a task. */ +@InterfaceAudience.Public public interface TaskMetadata { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/ThreadMetadata.java b/streams/src/main/java/org/apache/kafka/streams/ThreadMetadata.java index f611fe782f0cc..f86dae930a2ae 100644 --- a/streams/src/main/java/org/apache/kafka/streams/ThreadMetadata.java +++ b/streams/src/main/java/org/apache/kafka/streams/ThreadMetadata.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Set; /** * Metadata of a stream thread. */ +@InterfaceAudience.Public public interface ThreadMetadata { diff --git a/streams/src/main/java/org/apache/kafka/streams/Topology.java b/streams/src/main/java/org/apache/kafka/streams/Topology.java index e032abc346fd4..8a705a98c0086 100644 --- a/streams/src/main/java/org/apache/kafka/streams/Topology.java +++ b/streams/src/main/java/org/apache/kafka/streams/Topology.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.serialization.Deserializer; import org.apache.kafka.common.serialization.Serializer; import org.apache.kafka.streams.errors.TopologyException; @@ -57,8 +59,10 @@ * {@link KafkaStreams} instance that will then {@link KafkaStreams#start() begin consuming, processing, and producing * records}. */ +@InterfaceAudience.Public public class Topology { + @SuppressKafkaInternalApiUsage("KIP-1265: protected field exposes internal InternalTopologyBuilder for subclass access — pending KIP review to promote the type or refactor") protected final InternalTopologyBuilder internalTopologyBuilder; public Topology() { @@ -69,6 +73,7 @@ public Topology(final TopologyConfig topologyConfigs) { this(new InternalTopologyBuilder(topologyConfigs)); } + @SuppressKafkaInternalApiUsage("KIP-1265: protected ctor takes internal InternalTopologyBuilder as a subclass extension point — pending KIP review to promote the type or refactor") protected Topology(final InternalTopologyBuilder internalTopologyBuilder) { this.internalTopologyBuilder = internalTopologyBuilder; } diff --git a/streams/src/main/java/org/apache/kafka/streams/TopologyConfig.java b/streams/src/main/java/org/apache/kafka/streams/TopologyConfig.java index 45c0653c84b14..2aa67998c9f74 100644 --- a/streams/src/main/java/org/apache/kafka/streams/TopologyConfig.java +++ b/streams/src/main/java/org/apache/kafka/streams/TopologyConfig.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.AbstractConfig; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; @@ -86,6 +87,7 @@ * to be applied and the config will be ignored. */ @SuppressWarnings("deprecation") +@InterfaceAudience.Public public final class TopologyConfig extends AbstractConfig { public static class InternalConfig { diff --git a/streams/src/main/java/org/apache/kafka/streams/TopologyDescription.java b/streams/src/main/java/org/apache/kafka/streams/TopologyDescription.java index 0ab0e0d92ac2e..286682edf4d6d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/TopologyDescription.java +++ b/streams/src/main/java/org/apache/kafka/streams/TopologyDescription.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TopicNameExtractor; import org.apache.kafka.streams.processor.api.ProcessorContext; import org.apache.kafka.streams.processor.api.ProcessorSupplier; @@ -37,6 +38,7 @@ * When {@link KafkaStreams#start()} is called, different sub-topologies will be constructed and executed as independent * {@link StreamTask tasks}. */ +@InterfaceAudience.Public public interface TopologyDescription { /** * A connected sub-graph of a {@link Topology}. diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/DefaultProductionExceptionHandler.java b/streams/src/main/java/org/apache/kafka/streams/errors/DefaultProductionExceptionHandler.java index 3e9eb2fba86e0..1c69ca5b1d540 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/DefaultProductionExceptionHandler.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/DefaultProductionExceptionHandler.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.errors; import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.errors.RetriableException; import org.apache.kafka.streams.StreamsConfig; @@ -28,6 +29,7 @@ * {@code ProductionExceptionHandler} that always instructs streams to fail when an exception * happens while attempting to produce result records. */ +@InterfaceAudience.Public public class DefaultProductionExceptionHandler implements ProductionExceptionHandler { private String deadLetterQueueTopic = null; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/DeserializationExceptionHandler.java b/streams/src/main/java/org/apache/kafka/streams/errors/DeserializationExceptionHandler.java index 8c3667c20f498..88a9e9e924066 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/DeserializationExceptionHandler.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/DeserializationExceptionHandler.java @@ -19,6 +19,7 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.internals.DefaultErrorHandlerContext; import org.apache.kafka.streams.processor.ProcessorContext; @@ -29,6 +30,7 @@ * Interface that specifies how an exception from source node deserialization * (e.g., reading from Kafka) should be handled. */ +@InterfaceAudience.Public public interface DeserializationExceptionHandler extends Configurable { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/ErrorHandlerContext.java b/streams/src/main/java/org/apache/kafka/streams/errors/ErrorHandlerContext.java index 59ccab6fbf38c..75a17014e110e 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/ErrorHandlerContext.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/ErrorHandlerContext.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.streams.kstream.ValueTransformerWithKeySupplier; import org.apache.kafka.streams.processor.PunctuationType; @@ -32,6 +33,7 @@ *

    {@code ErrorHandlerContext} instances are passed into {@link DeserializationExceptionHandler}, * {@link ProcessingExceptionHandler}, or {@link ProductionExceptionHandler} dependent on what error occurred. */ +@InterfaceAudience.Public public interface ErrorHandlerContext { /** * Return the topic name of the current input record; could be {@code null} if it is not diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/InternalTopicsAlreadySetupException.java b/streams/src/main/java/org/apache/kafka/streams/errors/InternalTopicsAlreadySetupException.java index c5aea1e2fd192..bfaa8fe024265 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/InternalTopicsAlreadySetupException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/InternalTopicsAlreadySetupException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class InternalTopicsAlreadySetupException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/InvalidStateStoreException.java b/streams/src/main/java/org/apache/kafka/streams/errors/InvalidStateStoreException.java index f5fbef7254744..b62fbd8bfd345 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/InvalidStateStoreException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/InvalidStateStoreException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that there was a problem when trying to access a {@link org.apache.kafka.streams.processor.StateStore StateStore}. * {@code InvalidStateStoreException} is not thrown directly but only its following subclasses. */ +@InterfaceAudience.Public public class InvalidStateStoreException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/InvalidStateStorePartitionException.java b/streams/src/main/java/org/apache/kafka/streams/errors/InvalidStateStorePartitionException.java index f27926bfc653b..140165968f449 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/InvalidStateStorePartitionException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/InvalidStateStorePartitionException.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KafkaStreams; /** @@ -24,6 +25,7 @@ * You can use {@link KafkaStreams#metadataForAllStreamsClients()} to discover the correct instance * that hosts the requested partition. */ +@InterfaceAudience.Public public class InvalidStateStorePartitionException extends InvalidStateStoreException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/LockException.java b/streams/src/main/java/org/apache/kafka/streams/errors/LockException.java index a16171f5ee4aa..bf2a6ec16658a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/LockException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/LockException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that the state store directory lock could not be acquired because another thread holds the lock. * * @see org.apache.kafka.streams.processor.StateStore */ +@InterfaceAudience.Public public class LockException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/LogAndContinueExceptionHandler.java b/streams/src/main/java/org/apache/kafka/streams/errors/LogAndContinueExceptionHandler.java index 63972b0840d44..4304ac4e2995a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/LogAndContinueExceptionHandler.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/LogAndContinueExceptionHandler.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.errors; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.StreamsConfig; import org.slf4j.Logger; @@ -30,6 +31,7 @@ * Deserialization handler that logs a deserialization exception and then * signals the processing pipeline to continue processing more records. */ +@InterfaceAudience.Public public class LogAndContinueExceptionHandler implements DeserializationExceptionHandler { private static final Logger log = LoggerFactory.getLogger(LogAndContinueExceptionHandler.class); private String deadLetterQueueTopic = null; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/LogAndContinueProcessingExceptionHandler.java b/streams/src/main/java/org/apache/kafka/streams/errors/LogAndContinueProcessingExceptionHandler.java index 17de09e5f0cd2..7b07e885b7b21 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/LogAndContinueProcessingExceptionHandler.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/LogAndContinueProcessingExceptionHandler.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.StreamsConfig; import org.apache.kafka.streams.processor.api.Record; @@ -30,6 +31,7 @@ * Processing exception handler that logs a processing exception and then * signals the processing pipeline to continue processing more records. */ +@InterfaceAudience.Public public class LogAndContinueProcessingExceptionHandler implements ProcessingExceptionHandler { private static final Logger log = LoggerFactory.getLogger(LogAndContinueProcessingExceptionHandler.class); private String deadLetterQueueTopic = null; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/LogAndFailExceptionHandler.java b/streams/src/main/java/org/apache/kafka/streams/errors/LogAndFailExceptionHandler.java index 6fc129b4d78bf..28036b5cad925 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/LogAndFailExceptionHandler.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/LogAndFailExceptionHandler.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.errors; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.StreamsConfig; import org.slf4j.Logger; @@ -30,6 +31,7 @@ * Deserialization handler that logs a deserialization exception and then * signals the processing pipeline to stop processing more records and fail. */ +@InterfaceAudience.Public public class LogAndFailExceptionHandler implements DeserializationExceptionHandler { private static final Logger log = LoggerFactory.getLogger(LogAndFailExceptionHandler.class); private String deadLetterQueueTopic = null; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/LogAndFailProcessingExceptionHandler.java b/streams/src/main/java/org/apache/kafka/streams/errors/LogAndFailProcessingExceptionHandler.java index 5372d9ad0b679..039af0f355cdb 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/LogAndFailProcessingExceptionHandler.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/LogAndFailProcessingExceptionHandler.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.StreamsConfig; import org.apache.kafka.streams.processor.api.Record; @@ -30,6 +31,7 @@ * Processing exception handler that logs a processing exception and then * signals the processing pipeline to stop processing more records and fail. */ +@InterfaceAudience.Public public class LogAndFailProcessingExceptionHandler implements ProcessingExceptionHandler { private static final Logger log = LoggerFactory.getLogger(LogAndFailProcessingExceptionHandler.class); private String deadLetterQueueTopic = null; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/MisconfiguredInternalTopicException.java b/streams/src/main/java/org/apache/kafka/streams/errors/MisconfiguredInternalTopicException.java index f0b71f8fd118b..053fedaea488e 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/MisconfiguredInternalTopicException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/MisconfiguredInternalTopicException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class MisconfiguredInternalTopicException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/MissingInternalTopicsException.java b/streams/src/main/java/org/apache/kafka/streams/errors/MissingInternalTopicsException.java index 7270468da81dc..b0c72d76a9912 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/MissingInternalTopicsException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/MissingInternalTopicsException.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.List; +@InterfaceAudience.Public public class MissingInternalTopicsException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/MissingSourceTopicException.java b/streams/src/main/java/org/apache/kafka/streams/errors/MissingSourceTopicException.java index a0e5e8cd4ad9f..70ef74b3fc300 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/MissingSourceTopicException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/MissingSourceTopicException.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public class MissingSourceTopicException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/ProcessingExceptionHandler.java b/streams/src/main/java/org/apache/kafka/streams/errors/ProcessingExceptionHandler.java index 07cf0ff6b0e46..6508d5304b940 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/ProcessingExceptionHandler.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/ProcessingExceptionHandler.java @@ -18,6 +18,7 @@ import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.api.Record; import java.util.Collections; @@ -26,6 +27,7 @@ /** * An interface that allows user code to inspect a record that has failed processing */ +@InterfaceAudience.Public public interface ProcessingExceptionHandler extends Configurable { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/ProcessorStateException.java b/streams/src/main/java/org/apache/kafka/streams/errors/ProcessorStateException.java index e09f773584a3a..61af0c456b78b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/ProcessorStateException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/ProcessorStateException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates a processor state operation (e.g. init, put, get) has failed. * * @see org.apache.kafka.streams.processor.StateStore */ +@InterfaceAudience.Public public class ProcessorStateException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/ProductionExceptionHandler.java b/streams/src/main/java/org/apache/kafka/streams/errors/ProductionExceptionHandler.java index 717866a9bed60..ee5e3841c30e5 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/ProductionExceptionHandler.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/ProductionExceptionHandler.java @@ -14,10 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Collections; import java.util.List; @@ -26,6 +28,7 @@ * Interface that specifies how an exception when attempting to produce a result to * Kafka should be handled. */ +@InterfaceAudience.Public public interface ProductionExceptionHandler extends Configurable { /** * Inspect a record that we attempted to produce, and the exception that resulted diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/StateStoreMigratedException.java b/streams/src/main/java/org/apache/kafka/streams/errors/StateStoreMigratedException.java index ed74d972a6d3c..4c6e840a3eeb5 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/StateStoreMigratedException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/StateStoreMigratedException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that the state store being queried is closed although the Kafka Streams state is * {@link org.apache.kafka.streams.KafkaStreams.State#RUNNING RUNNING} or @@ -24,6 +27,7 @@ * rediscovery of the state store is required before retrying. */ @SuppressWarnings("unused") +@InterfaceAudience.Public public class StateStoreMigratedException extends InvalidStateStoreException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/StateStoreNotAvailableException.java b/streams/src/main/java/org/apache/kafka/streams/errors/StateStoreNotAvailableException.java index 26660b2ea7eed..25f3e4ed7e0ef 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/StateStoreNotAvailableException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/StateStoreNotAvailableException.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that the state store being queried is already closed. This could happen when Kafka Streams is in * {@link org.apache.kafka.streams.KafkaStreams.State#PENDING_SHUTDOWN PENDING_SHUTDOWN} or @@ -23,6 +26,7 @@ * {@link org.apache.kafka.streams.KafkaStreams.State#ERROR ERROR} state. */ @SuppressWarnings("unused") +@InterfaceAudience.Public public class StateStoreNotAvailableException extends InvalidStateStoreException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsException.java b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsException.java index 07cdeb4bc3b4a..1f712911b2e4a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsException.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.errors; import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TaskId; import java.util.Optional; @@ -27,6 +28,7 @@ * is guaranteed that any exception thrown up to the {@link StreamsUncaughtExceptionHandler} will be of the type * {@code StreamsException}. For example, any user exceptions will be wrapped as a {@code StreamsException}. */ +@InterfaceAudience.Public public class StreamsException extends KafkaException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsNotStartedException.java b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsNotStartedException.java index 1179c07f422a0..5bcd53b2804fb 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsNotStartedException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsNotStartedException.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.KafkaStreams.State; @@ -24,6 +25,7 @@ * To query state stores, it's required to first start Kafka Streams via {@link KafkaStreams#start()}. * You can retry to query the state after the state transitioned to {@link State RUNNING}. */ +@InterfaceAudience.Public public class StreamsNotStartedException extends InvalidStateStoreException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsRebalancingException.java b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsRebalancingException.java index 7c6c027d2669a..da58431860f33 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsRebalancingException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsRebalancingException.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that Kafka Streams is in state {@link org.apache.kafka.streams.KafkaStreams.State#REBALANCING REBALANCING} and thus * cannot be queried by default. You can retry to query after the rebalance finished. As an alternative, you can also query * (potentially stale) state stores during a rebalance via {@link org.apache.kafka.streams.StoreQueryParameters#enableStaleStores()}. */ @SuppressWarnings("unused") +@InterfaceAudience.Public public class StreamsRebalancingException extends InvalidStateStoreException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsStoppedException.java b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsStoppedException.java index 252edbe31439e..1b1b7c63704b1 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsStoppedException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsStoppedException.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KafkaStreams.State; /** @@ -24,6 +25,7 @@ * State#ERROR}. This Streams instance will need to be discarded and replaced before it can * serve queries. The caller may wish to query a different instance. */ +@InterfaceAudience.Public public class StreamsStoppedException extends InvalidStateStoreException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsUncaughtExceptionHandler.java b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsUncaughtExceptionHandler.java index 2e76d5a0788bc..c5599fd1a9688 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/StreamsUncaughtExceptionHandler.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/StreamsUncaughtExceptionHandler.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public interface StreamsUncaughtExceptionHandler { /** * Inspect the exception received in a stream thread and respond with an action. diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/TaskAssignmentException.java b/streams/src/main/java/org/apache/kafka/streams/errors/TaskAssignmentException.java index 53b40ecae3e52..aa02af21368ed 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/TaskAssignmentException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/TaskAssignmentException.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates a run time error incurred while trying to assign * {@link org.apache.kafka.streams.processor.internals.StreamTask stream tasks} to * {@link org.apache.kafka.streams.processor.internals.StreamThread threads}. */ +@InterfaceAudience.Public public class TaskAssignmentException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/TaskCorruptedException.java b/streams/src/main/java/org/apache/kafka/streams/errors/TaskCorruptedException.java index 09f5f9a4f2bb1..06114ae91e645 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/TaskCorruptedException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/TaskCorruptedException.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.errors; import org.apache.kafka.clients.consumer.InvalidOffsetException; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TaskId; import java.util.Set; @@ -29,6 +30,7 @@ *

  • Out-of-range exception thrown during restoration, meaning that the changelog has been modified and we re-bootstrap the store.
  • * */ +@InterfaceAudience.Public public class TaskCorruptedException extends StreamsException { private final Set corruptedTasks; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/TaskIdFormatException.java b/streams/src/main/java/org/apache/kafka/streams/errors/TaskIdFormatException.java index 04e60ffb6c403..1adcf58e770c1 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/TaskIdFormatException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/TaskIdFormatException.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Indicates a run time error incurred while trying parse the {@link org.apache.kafka.streams.processor.TaskId task id} @@ -23,6 +25,7 @@ * * @see org.apache.kafka.streams.processor.internals.StreamTask */ +@InterfaceAudience.Public public class TaskIdFormatException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/TaskMigratedException.java b/streams/src/main/java/org/apache/kafka/streams/errors/TaskMigratedException.java index 7a2c0600b8189..0eec8e5cfa266 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/TaskMigratedException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/TaskMigratedException.java @@ -14,14 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Indicates that all tasks belongs to the thread have migrated to another thread. This exception can be thrown when * the thread gets fenced (either by the consumer coordinator or by the transaction coordinator), which means it is * no longer part of the group but a "zombie" already */ +@InterfaceAudience.Public public class TaskMigratedException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/TopologyException.java b/streams/src/main/java/org/apache/kafka/streams/errors/TopologyException.java index 30ed93f2aa0aa..83277e9a73474 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/TopologyException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/TopologyException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates a pre run time error occurred while parsing the {@link org.apache.kafka.streams.Topology logical topology} * to construct the {@link org.apache.kafka.streams.processor.internals.ProcessorTopology physical processor topology}. */ +@InterfaceAudience.Public public class TopologyException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/UnknownStateStoreException.java b/streams/src/main/java/org/apache/kafka/streams/errors/UnknownStateStoreException.java index 8fffe89be2e3a..489c7fae54e8d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/UnknownStateStoreException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/UnknownStateStoreException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that the state store being queried is unknown, i.e., the state store does either not exist in your topology * or it is not queryable. */ +@InterfaceAudience.Public public class UnknownStateStoreException extends InvalidStateStoreException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/errors/UnknownTopologyException.java b/streams/src/main/java/org/apache/kafka/streams/errors/UnknownTopologyException.java index accac453a3d2a..4eec2f818639a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/errors/UnknownTopologyException.java +++ b/streams/src/main/java/org/apache/kafka/streams/errors/UnknownTopologyException.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.errors; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Indicates that the {@link org.apache.kafka.streams.processor.internals.namedtopology.NamedTopology} being * looked up does not exist in this application */ +@InterfaceAudience.Public public class UnknownTopologyException extends StreamsException { private static final long serialVersionUID = 1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Aggregator.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Aggregator.java index e35bcaa02fff3..9094a3e632a98 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Aggregator.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Aggregator.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The {@code Aggregator} interface for aggregating values of the given key. @@ -39,6 +41,7 @@ * @see Reducer */ @FunctionalInterface +@InterfaceAudience.Public public interface Aggregator { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Branched.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Branched.java index 2f55f80899a2a..c5095ff43fc7b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Branched.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Branched.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; @@ -27,6 +30,7 @@ * @param type of record key * @param type of record value */ +@InterfaceAudience.Public public class Branched implements NamedOperation> { protected final String name; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/BranchedKStream.java b/streams/src/main/java/org/apache/kafka/streams/kstream/BranchedKStream.java index 5c439d5aa7ce1..c2b242cc4a258 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/BranchedKStream.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/BranchedKStream.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.api.Record; import java.util.Map; @@ -117,6 +118,7 @@ * @param the key type of this stream * @param the value type of this stream */ +@InterfaceAudience.Public public interface BranchedKStream { /** * Define a branch for records that match the predicate. diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/CogroupedKStream.java b/streams/src/main/java/org/apache/kafka/streams/kstream/CogroupedKStream.java index fa6ed8c9a5671..77ab2b9d99d90 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/CogroupedKStream.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/CogroupedKStream.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.StoreQueryParameters; @@ -41,6 +42,7 @@ * @param the key type of this co-grouped stream * @param the result value type of the applied aggregation */ +@InterfaceAudience.Public public interface CogroupedKStream { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Consumed.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Consumed.java index ade104d6118ef..054ebaf1f7839 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Consumed.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Consumed.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.streams.AutoOffsetReset; import org.apache.kafka.streams.StreamsBuilder; @@ -51,6 +52,7 @@ * @param type of record key * @param type of record value */ +@InterfaceAudience.Public public class Consumed implements NamedOperation> { protected Serde keySerde; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/EmitStrategy.java b/streams/src/main/java/org/apache/kafka/streams/kstream/EmitStrategy.java index c415167451fb6..69537c29f9c15 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/EmitStrategy.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/EmitStrategy.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.kstream.internals.UnlimitedWindow; import org.apache.kafka.streams.kstream.internals.emitstrategy.WindowCloseStrategy; import org.apache.kafka.streams.kstream.internals.emitstrategy.WindowUpdateStrategy; @@ -29,6 +30,7 @@ /** * This interface controls the strategy that can be used to control how we emit results in a processor. */ +@InterfaceAudience.Public public interface EmitStrategy { Logger log = LoggerFactory.getLogger(EmitStrategy.class); diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/ForeachAction.java b/streams/src/main/java/org/apache/kafka/streams/kstream/ForeachAction.java index 3ae82e54cb49f..1122a52b8d1cb 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/ForeachAction.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/ForeachAction.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The {@code ForeachAction} interface for performing an action on a {@link org.apache.kafka.streams.KeyValue key-value @@ -31,6 +33,7 @@ * @see KStream#foreach(ForeachAction) */ @FunctionalInterface +@InterfaceAudience.Public public interface ForeachAction { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/GlobalKTable.java b/streams/src/main/java/org/apache/kafka/streams/kstream/GlobalKTable.java index 523e30b522452..fd05ea1ac337b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/GlobalKTable.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/GlobalKTable.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.StoreQueryParameters; import org.apache.kafka.streams.StreamsBuilder; @@ -73,6 +74,7 @@ * * @see StreamsBuilder#addGlobalStore(StoreBuilder, String, Consumed, ProcessorSupplier) */ +@InterfaceAudience.Public public interface GlobalKTable { /** * Get the name of the local state store that can be used to query this {@code GlobalKTable}. diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Grouped.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Grouped.java index 631969734bf20..8a85c2944d3f1 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Grouped.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Grouped.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serde; /** @@ -27,6 +28,7 @@ * @param the key type * @param the value type */ +@InterfaceAudience.Public public class Grouped implements NamedOperation> { protected final Serde keySerde; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Initializer.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Initializer.java index bc6c09ffbad13..ecf26510d4361 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Initializer.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Initializer.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The {@code Initializer} interface for creating an initial value in aggregations. * {@code Initializer} is used in combination with {@link Aggregator}. @@ -31,6 +34,7 @@ * @see SessionWindowedKStream#aggregate(Initializer, Aggregator, Merger, Materialized) */ @FunctionalInterface +@InterfaceAudience.Public public interface Initializer { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/JoinWindows.java b/streams/src/main/java/org/apache/kafka/streams/kstream/JoinWindows.java index 80db8f5624bd3..a8abc6fbef215 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/JoinWindows.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/JoinWindows.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TimestampExtractor; import java.time.Duration; @@ -67,6 +68,7 @@ * @see KStream#outerJoin(KStream, ValueJoiner, JoinWindows, StreamJoined) * @see TimestampExtractor */ +@InterfaceAudience.Public public class JoinWindows extends Windows { /** Maximum time difference for tuples that are before the join tuple. */ diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Joined.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Joined.java index 0ae26ec3ccd1b..bf2565644766f 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Joined.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Joined.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serde; import java.time.Duration; @@ -29,6 +30,7 @@ * @param type of left record value * @param type of right record value */ +@InterfaceAudience.Public public class Joined implements NamedOperation> { protected final Serde keySerde; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/KGroupedStream.java b/streams/src/main/java/org/apache/kafka/streams/kstream/KGroupedStream.java index 9f6d020baf36c..1dab27a48dc46 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/KGroupedStream.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/KGroupedStream.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.KeyValue; @@ -42,6 +43,7 @@ * @param the key type of this grouped stream * @param the value type of this grouped stream */ +@InterfaceAudience.Public public interface KGroupedStream { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/KGroupedTable.java b/streams/src/main/java/org/apache/kafka/streams/kstream/KGroupedTable.java index dee237f7ae6f2..02fae5b9e1d72 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/KGroupedTable.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/KGroupedTable.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.StoreQueryParameters; @@ -35,6 +36,7 @@ * @param the (new) grouping key type of this re-grouped table * @param the (new) value type of this re-grouped table */ +@InterfaceAudience.Public public interface KGroupedTable { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/KStream.java b/streams/src/main/java/org/apache/kafka/streams/kstream/KStream.java index 5ccc84a12750c..900e2eacd9933 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/KStream.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/KStream.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.KeyValue; import org.apache.kafka.streams.StreamsBuilder; @@ -58,6 +59,7 @@ * @param the key type of this stream * @param the value type of this stream */ +@InterfaceAudience.Public public interface KStream { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/KTable.java b/streams/src/main/java/org/apache/kafka/streams/kstream/KTable.java index 2f2aa93c5d60a..f8418df834c77 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/KTable.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/KTable.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.KafkaStreams; @@ -86,6 +87,7 @@ * * @see GlobalKTable */ +@InterfaceAudience.Public public interface KTable { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/KeyValueMapper.java b/streams/src/main/java/org/apache/kafka/streams/kstream/KeyValueMapper.java index d13ed41a97115..b09895ec4d12a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/KeyValueMapper.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/KeyValueMapper.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; /** @@ -45,6 +46,7 @@ * @see KTable#toStream(KeyValueMapper) */ @FunctionalInterface +@InterfaceAudience.Public public interface KeyValueMapper { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Materialized.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Materialized.java index b2075022fd909..862035584d207 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Materialized.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Materialized.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.processor.StateStore; @@ -84,6 +85,7 @@ * * @see org.apache.kafka.streams.state.Stores */ +@InterfaceAudience.Public public class Materialized { protected StoreSupplier storeSupplier; protected String storeName; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Merger.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Merger.java index af2de8da09fa2..9d3bed300cab5 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Merger.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Merger.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The interface for merging aggregate values for {@link SessionWindows} with the given key. @@ -24,6 +26,7 @@ * @param aggregate value type */ @FunctionalInterface +@InterfaceAudience.Public public interface Merger { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Named.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Named.java index ea80003df5e24..d49a83914addc 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Named.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Named.java @@ -16,10 +16,12 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.TopologyException; import java.util.Objects; +@InterfaceAudience.Public public class Named implements NamedOperation { private static final int MAX_NAME_LENGTH = 249; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Predicate.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Predicate.java index 54560df7b875e..3506f96b1c6c5 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Predicate.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Predicate.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; /** @@ -32,6 +33,7 @@ * @see KTable#filterNot(Predicate) */ @FunctionalInterface +@InterfaceAudience.Public public interface Predicate { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Printed.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Printed.java index 6a3d1e53ee05e..e45ef51be7ef1 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Printed.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Printed.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Utils; import org.apache.kafka.streams.errors.TopologyException; @@ -32,6 +33,7 @@ * @param value type * @see KStream#print(Printed) */ +@InterfaceAudience.Public public class Printed implements NamedOperation> { protected final OutputStream outputStream; protected String label; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Produced.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Produced.java index 90fd535fc3bd2..e9640e1f0108a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Produced.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Produced.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.streams.kstream.internals.WindowedSerializer; import org.apache.kafka.streams.kstream.internals.WindowedStreamPartitioner; @@ -31,6 +32,7 @@ * @param key type * @param value type */ +@InterfaceAudience.Public public class Produced implements NamedOperation> { protected Serde keySerde; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Reducer.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Reducer.java index aeb6e9f279f34..c4babcfff8555 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Reducer.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Reducer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; /** @@ -37,6 +38,7 @@ * @see Aggregator */ @FunctionalInterface +@InterfaceAudience.Public public interface Reducer { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Repartitioned.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Repartitioned.java index 390fa2e756bc6..005d5388ecfcf 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Repartitioned.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Repartitioned.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.streams.kstream.internals.WindowedSerializer; import org.apache.kafka.streams.kstream.internals.WindowedStreamPartitioner; @@ -30,6 +31,7 @@ * @see KStream#repartition() * @see KStream#repartition(Repartitioned) */ +@InterfaceAudience.Public public class Repartitioned implements NamedOperation> { protected final String name; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedCogroupedKStream.java b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedCogroupedKStream.java index b273132b11177..a2bab092c6555 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedCogroupedKStream.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedCogroupedKStream.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.StoreQueryParameters; @@ -23,10 +25,10 @@ import org.apache.kafka.streams.Topology; import org.apache.kafka.streams.state.SessionStore; - /** * Same as a {@link SessionWindowedKStream}, however, for multiple co-grouped {@link KStream KStreams}. */ +@InterfaceAudience.Public public interface SessionWindowedCogroupedKStream { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedDeserializer.java b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedDeserializer.java index 8e3dc8663e0a0..da4d623007349 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedDeserializer.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedDeserializer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; @@ -30,6 +31,7 @@ import java.util.Map; +@InterfaceAudience.Public public class SessionWindowedDeserializer implements Deserializer> { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedKStream.java b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedKStream.java index 40e1a6eb72400..c40a984bd334c 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedKStream.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedKStream.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.StoreQueryParameters; @@ -48,6 +49,7 @@ * * @see TimeWindowedKStream */ +@InterfaceAudience.Public public interface SessionWindowedKStream { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedSerializer.java b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedSerializer.java index 9a87752e2888a..dab661b1618c5 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedSerializer.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindowedSerializer.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; @@ -31,6 +33,8 @@ import java.util.Map; +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: implements internal WindowedSerializer — pending KIP review to promote the parent or refactor the Streams windowed-serializer hierarchy") public class SessionWindowedSerializer implements WindowedSerializer { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindows.java b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindows.java index e054446ff27e4..c88a3c63418af 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindows.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/SessionWindows.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TimestampExtractor; import java.time.Duration; @@ -69,6 +70,7 @@ * @see KGroupedStream#windowedBy(SessionWindows) * @see TimestampExtractor */ +@InterfaceAudience.Public public final class SessionWindows { private final long gapMs; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/SlidingWindows.java b/streams/src/main/java/org/apache/kafka/streams/kstream/SlidingWindows.java index 4161dd009e07b..13fa4b03974e9 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/SlidingWindows.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/SlidingWindows.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TimestampExtractor; import java.time.Duration; @@ -71,6 +72,7 @@ * @see TimestampExtractor */ +@InterfaceAudience.Public public final class SlidingWindows { /** The size of the windows in milliseconds, defined by the max time difference between records. */ diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/StreamJoined.java b/streams/src/main/java/org/apache/kafka/streams/kstream/StreamJoined.java index 189979feafb12..490cb0ad57903 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/StreamJoined.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/StreamJoined.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.streams.state.DslStoreSuppliers; import org.apache.kafka.streams.state.WindowBytesStoreSupplier; @@ -31,6 +32,7 @@ * @param this value type * @param other value type */ +@InterfaceAudience.Public public class StreamJoined implements NamedOperation> { protected final Serde keySerde; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Suppressed.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Suppressed.java index 5bda71d487b5c..a76a51dded0fe 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Suppressed.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Suppressed.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.kstream.internals.suppress.EagerBufferConfigImpl; import org.apache.kafka.streams.kstream.internals.suppress.FinalResultsSuppressionBuilder; import org.apache.kafka.streams.kstream.internals.suppress.StrictBufferConfigImpl; @@ -25,6 +26,7 @@ import java.util.Collections; import java.util.Map; +@InterfaceAudience.Public public interface Suppressed extends NamedOperation> { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/TableJoined.java b/streams/src/main/java/org/apache/kafka/streams/kstream/TableJoined.java index 70a3630fd0754..d99bccfd7fafb 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/TableJoined.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/TableJoined.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.StreamPartitioner; import java.util.function.Function; @@ -28,6 +29,7 @@ * @param this key type ; key type for the left (primary) table * @param other key type ; key type for the right (foreign key) table */ +@InterfaceAudience.Public public class TableJoined implements NamedOperation> { protected final StreamPartitioner partitioner; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedCogroupedKStream.java b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedCogroupedKStream.java index 8717b6865370b..f58ac37825ccc 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedCogroupedKStream.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedCogroupedKStream.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.StoreQueryParameters; @@ -25,10 +27,10 @@ import org.apache.kafka.streams.state.TimestampedWindowStore; import org.apache.kafka.streams.state.WindowStore; - /** * Same as a {@link TimeWindowedKStream}, however, for multiple co-grouped {@link KStream KStreams}. */ +@InterfaceAudience.Public public interface TimeWindowedCogroupedKStream { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedDeserializer.java b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedDeserializer.java index 4725974c7da72..f89b9c0e9bd72 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedDeserializer.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedDeserializer.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; @@ -30,6 +31,7 @@ import java.util.Map; +@InterfaceAudience.Public public class TimeWindowedDeserializer implements Deserializer> { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedKStream.java b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedKStream.java index 823cca2dc0045..4d82825fc6f9d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedKStream.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedKStream.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.StoreQueryParameters; @@ -59,6 +60,7 @@ * * @see SessionWindowedKStream */ +@InterfaceAudience.Public public interface TimeWindowedKStream { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedSerializer.java b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedSerializer.java index 5eef64da78000..b1d3c35dbde1e 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedSerializer.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedSerializer.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; @@ -31,6 +33,8 @@ import java.util.Map; +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: implements internal WindowedSerializer — pending KIP review to promote the parent or refactor the Streams windowed-serializer hierarchy") public class TimeWindowedSerializer implements WindowedSerializer { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindows.java b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindows.java index 3653eeea8d852..276445ef7f5fc 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindows.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindows.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.streams.kstream.internals.TimeWindow; import org.apache.kafka.streams.processor.TimestampExtractor; @@ -54,6 +56,8 @@ * @see KGroupedStream#windowedBy(Windows) * @see TimestampExtractor */ +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: class header signature exposes internal TimeWindow (Windows) — pending KIP review to promote the type or refactor") public final class TimeWindows extends Windows { /** The size of the windows in milliseconds. */ @@ -153,6 +157,7 @@ public TimeWindows advanceBy(final Duration advance) { } @Override + @SuppressKafkaInternalApiUsage("KIP-1265: public method's signature exposes internal TimeWindow — pending KIP review to promote the type or refactor the API") public Map windowsFor(final long timestamp) { long windowStart = (Math.max(0, timestamp - sizeMs + advanceMs) / advanceMs) * advanceMs; final Map windows = new LinkedHashMap<>(); diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/UnlimitedWindows.java b/streams/src/main/java/org/apache/kafka/streams/kstream/UnlimitedWindows.java index 7a0573077f780..3419712ffee3a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/UnlimitedWindows.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/UnlimitedWindows.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.streams.internals.ApiUtils; import org.apache.kafka.streams.kstream.internals.UnlimitedWindow; import org.apache.kafka.streams.processor.TimestampExtractor; @@ -42,6 +44,8 @@ * @see KGroupedStream#windowedBy(Windows) * @see TimestampExtractor */ +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: class header signature exposes internal UnlimitedWindow (Windows) — pending KIP review to promote the type or refactor") public final class UnlimitedWindows extends Windows { private static final long DEFAULT_START_TIMESTAMP_MS = 0L; @@ -78,6 +82,7 @@ public UnlimitedWindows startOn(final Instant start) throws IllegalArgumentExcep } @Override + @SuppressKafkaInternalApiUsage("KIP-1265: public method's signature exposes internal UnlimitedWindow — pending KIP review to promote the type or refactor the API") public Map windowsFor(final long timestamp) { // always return the single unlimited window diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueJoiner.java b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueJoiner.java index cac82792355d1..1b91e8fbbabd2 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueJoiner.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueJoiner.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The {@code ValueJoiner} interface for joining two values into a new value of arbitrary type. @@ -41,6 +43,7 @@ * @see KTable#outerJoin(KTable, ValueJoiner) */ @FunctionalInterface +@InterfaceAudience.Public public interface ValueJoiner { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueJoinerWithKey.java b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueJoinerWithKey.java index 84087ff5f63e8..8e2aca44783cb 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueJoinerWithKey.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueJoinerWithKey.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The {@code ValueJoinerWithKey} interface for joining two values into a new value of arbitrary type. @@ -45,6 +47,7 @@ * @see KStream#leftJoin(GlobalKTable, KeyValueMapper, ValueJoinerWithKey, Named) */ @FunctionalInterface +@InterfaceAudience.Public public interface ValueJoinerWithKey { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueMapper.java b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueMapper.java index 9b09db3276fe2..3bcd66022be01 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueMapper.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueMapper.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.api.FixedKeyProcessor; /** @@ -38,6 +39,7 @@ * @see KTable#mapValues(ValueMapperWithKey) */ @FunctionalInterface +@InterfaceAudience.Public public interface ValueMapper { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueMapperWithKey.java b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueMapperWithKey.java index e6b0efd901627..3956773a0516d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueMapperWithKey.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueMapperWithKey.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The {@code ValueMapperWithKey} interface for mapping a value to a new value of arbitrary type. * This is a stateless record-by-record operation, i.e, {@link #apply(Object, Object)} is invoked individually for each @@ -39,6 +42,7 @@ */ @FunctionalInterface +@InterfaceAudience.Public public interface ValueMapperWithKey { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueTransformerWithKey.java b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueTransformerWithKey.java index cc0c38d01ef04..bedc9ab4f6c46 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueTransformerWithKey.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueTransformerWithKey.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; import org.apache.kafka.streams.errors.StreamsException; import org.apache.kafka.streams.processor.ProcessorContext; @@ -51,6 +52,7 @@ * @see Transformer */ +@InterfaceAudience.Public public interface ValueTransformerWithKey { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueTransformerWithKeySupplier.java b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueTransformerWithKeySupplier.java index b59009aab1045..5fbaaa28fa1f8 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/ValueTransformerWithKeySupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/ValueTransformerWithKeySupplier.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.ConnectedStoreProvider; import java.util.function.Supplier; @@ -36,6 +37,7 @@ * @see TransformerSupplier */ @FunctionalInterface +@InterfaceAudience.Public public interface ValueTransformerWithKeySupplier extends ConnectedStoreProvider, Supplier> { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Window.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Window.java index 432bb452ebb2d..2c765f917f7ce 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Window.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Window.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TimestampExtractor; import java.time.Instant; @@ -34,6 +35,7 @@ * @see org.apache.kafka.streams.kstream.internals.UnlimitedWindow * @see TimestampExtractor */ +@InterfaceAudience.Public public abstract class Window { protected final long startMs; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Windowed.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Windowed.java index d830f580835cd..0fcf220c44460 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Windowed.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Windowed.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * The result key type of a windowed stream aggregation. @@ -29,6 +31,7 @@ * @see KGroupedStream#windowedBy(Windows) * @see KGroupedStream#windowedBy(SessionWindows) */ +@InterfaceAudience.Public public class Windowed { private final K key; diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/WindowedSerdes.java b/streams/src/main/java/org/apache/kafka/streams/kstream/WindowedSerdes.java index 2a95469eedc33..2799f740013b0 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/WindowedSerdes.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/WindowedSerdes.java @@ -16,11 +16,13 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Deserializer; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.common.serialization.Serdes; import org.apache.kafka.common.serialization.Serializer; +@InterfaceAudience.Public public class WindowedSerdes { public static class TimeWindowedSerde extends Serdes.WrapperSerde> { diff --git a/streams/src/main/java/org/apache/kafka/streams/kstream/Windows.java b/streams/src/main/java/org/apache/kafka/streams/kstream/Windows.java index cd8a28695e4db..0c311c643859e 100644 --- a/streams/src/main/java/org/apache/kafka/streams/kstream/Windows.java +++ b/streams/src/main/java/org/apache/kafka/streams/kstream/Windows.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.kstream; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TimestampExtractor; import java.util.Map; @@ -36,6 +37,7 @@ * @see SessionWindows * @see TimestampExtractor */ +@InterfaceAudience.Public public abstract class Windows { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/BatchingStateRestoreCallback.java b/streams/src/main/java/org/apache/kafka/streams/processor/BatchingStateRestoreCallback.java index 52ee38848646e..2ba0bf126d9eb 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/BatchingStateRestoreCallback.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/BatchingStateRestoreCallback.java @@ -17,7 +17,7 @@ package org.apache.kafka.streams.processor; - +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; import java.util.Collection; @@ -28,6 +28,7 @@ * It is expected that implementations of this class will not call the {@link StateRestoreCallback#restore(byte[], * byte[])} method. */ +@InterfaceAudience.Public public interface BatchingStateRestoreCallback extends StateRestoreCallback { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/Cancellable.java b/streams/src/main/java/org/apache/kafka/streams/processor/Cancellable.java index fb79926095b80..9408f77083c71 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/Cancellable.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/Cancellable.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.time.Duration; /** @@ -24,6 +27,7 @@ * @see Punctuator */ @FunctionalInterface +@InterfaceAudience.Public public interface Cancellable { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/CommitCallback.java b/streams/src/main/java/org/apache/kafka/streams/processor/CommitCallback.java index 581173d79de97..45569dd19418b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/CommitCallback.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/CommitCallback.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import java.io.IOException; @@ -26,6 +27,7 @@ */ @Evolving @FunctionalInterface +@InterfaceAudience.Public public interface CommitCallback { void onCommit() throws IOException; } diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/ConnectedStoreProvider.java b/streams/src/main/java/org/apache/kafka/streams/processor/ConnectedStoreProvider.java index ad3a834257d1b..8dfebd1ed95e9 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/ConnectedStoreProvider.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/ConnectedStoreProvider.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.Topology; import org.apache.kafka.streams.kstream.KStream; import org.apache.kafka.streams.kstream.Named; @@ -94,6 +95,7 @@ * @see KStream#processValues(FixedKeyProcessorSupplier, String...) * @see KStream#processValues(FixedKeyProcessorSupplier, Named, String...) */ +@InterfaceAudience.Public public interface ConnectedStoreProvider { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/FailOnInvalidTimestamp.java b/streams/src/main/java/org/apache/kafka/streams/processor/FailOnInvalidTimestamp.java index 0d48a2cb9b4f2..2da252ce2b4ae 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/FailOnInvalidTimestamp.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/FailOnInvalidTimestamp.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.processor; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.StreamsException; import org.slf4j.Logger; @@ -45,6 +46,7 @@ * @see UsePartitionTimeOnInvalidTimestamp * @see WallclockTimestampExtractor */ +@InterfaceAudience.Public public class FailOnInvalidTimestamp extends ExtractRecordMetadataTimestamp { private static final Logger log = LoggerFactory.getLogger(FailOnInvalidTimestamp.class); diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/LogAndSkipOnInvalidTimestamp.java b/streams/src/main/java/org/apache/kafka/streams/processor/LogAndSkipOnInvalidTimestamp.java index 09143722ece98..ceb8faa41afd4 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/LogAndSkipOnInvalidTimestamp.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/LogAndSkipOnInvalidTimestamp.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.processor; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,6 +47,7 @@ * @see UsePartitionTimeOnInvalidTimestamp * @see WallclockTimestampExtractor */ +@InterfaceAudience.Public public class LogAndSkipOnInvalidTimestamp extends ExtractRecordMetadataTimestamp { private static final Logger log = LoggerFactory.getLogger(LogAndSkipOnInvalidTimestamp.class); diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/ProcessorContext.java b/streams/src/main/java/org/apache/kafka/streams/processor/ProcessorContext.java index aed4497aa740b..f29857475468b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/ProcessorContext.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/ProcessorContext.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.serialization.Deserializer; import org.apache.kafka.common.serialization.Serde; @@ -47,6 +48,7 @@ * When we deprecate `ProcessorContext` can also deprecate `To` class, * as it is only used in the `ProcessorContext#forward` method. */ +@InterfaceAudience.Public public interface ProcessorContext { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/PunctuationType.java b/streams/src/main/java/org/apache/kafka/streams/processor/PunctuationType.java index 2e50c17053082..7d103f54ef80b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/PunctuationType.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/PunctuationType.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.time.Duration; /** @@ -31,6 +34,7 @@ * by how long an iteration of the processing loop takes to complete * */ +@InterfaceAudience.Public public enum PunctuationType { STREAM_TIME, WALL_CLOCK_TIME, diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/Punctuator.java b/streams/src/main/java/org/apache/kafka/streams/processor/Punctuator.java index ee655d29cf920..4a51975d2db38 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/Punctuator.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/Punctuator.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.api.Record; import java.time.Duration; @@ -27,6 +28,7 @@ * @see Cancellable */ @FunctionalInterface +@InterfaceAudience.Public public interface Punctuator { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/RecordContext.java b/streams/src/main/java/org/apache/kafka/streams/processor/RecordContext.java index f77d4f454ce37..6fdc998a82374 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/RecordContext.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/RecordContext.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.streams.kstream.ValueTransformerWithKeySupplier; @@ -23,6 +24,7 @@ * The context associated with the current record being processed by * a {@link org.apache.kafka.streams.processor.api.Processor} */ +@InterfaceAudience.Public public interface RecordContext { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/StandbyUpdateListener.java b/streams/src/main/java/org/apache/kafka/streams/processor/StandbyUpdateListener.java index 8b9076be55cd0..882747b47dc0d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/StandbyUpdateListener.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/StandbyUpdateListener.java @@ -14,10 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; +@InterfaceAudience.Public public interface StandbyUpdateListener { enum SuspendReason { diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/StateRestoreCallback.java b/streams/src/main/java/org/apache/kafka/streams/processor/StateRestoreCallback.java index 0e43f37ca9580..b6edcdc3f5892 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/StateRestoreCallback.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/StateRestoreCallback.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Restoration logic for log-backed state stores upon restart, * it takes one record at a time from the logs to apply to the restoring state. */ @FunctionalInterface +@InterfaceAudience.Public public interface StateRestoreCallback { void restore(byte[] key, byte[] value); diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/StateRestoreListener.java b/streams/src/main/java/org/apache/kafka/streams/processor/StateRestoreListener.java index 006cc58cd43c8..adc0adc34e461 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/StateRestoreListener.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/StateRestoreListener.java @@ -18,6 +18,7 @@ package org.apache.kafka.streams.processor; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Class for listening to various states of the restoration process of a StateStore. @@ -48,6 +49,7 @@ *

    * Incremental updates are exposed so users can estimate how much progress has been made. */ +@InterfaceAudience.Public public interface StateRestoreListener { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/StateStore.java b/streams/src/main/java/org/apache/kafka/streams/processor/StateStore.java index 19112419ddc00..defc592f6ab8d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/StateStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/StateStore.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.processor; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import org.apache.kafka.streams.errors.StreamsException; import org.apache.kafka.streams.processor.api.ProcessorContext; @@ -48,6 +49,7 @@ * functionality required to reload a storage engine from its changelog as well * as basic lifecycle management. */ +@InterfaceAudience.Public public interface StateStore { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/StateStoreContext.java b/streams/src/main/java/org/apache/kafka/streams/processor/StateStoreContext.java index 35e3e58aadac2..9ff208a68f1d8 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/StateStoreContext.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/StateStoreContext.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.streams.StreamsMetrics; @@ -29,6 +30,7 @@ /** * State store context interface. */ +@InterfaceAudience.Public public interface StateStoreContext { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/StreamPartitioner.java b/streams/src/main/java/org/apache/kafka/streams/processor/StreamPartitioner.java index ced6b81daeb39..20e6cfb5d8108 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/StreamPartitioner.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/StreamPartitioner.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.Topology; import java.util.Optional; @@ -51,6 +52,7 @@ * @see Topology#addSink(String, String, StreamPartitioner, String...) */ @FunctionalInterface +@InterfaceAudience.Public public interface StreamPartitioner { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/TaskId.java b/streams/src/main/java/org/apache/kafka/streams/processor/TaskId.java index 6b909ec72747f..017e879512fe0 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/TaskId.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/TaskId.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.TaskIdFormatException; import org.slf4j.Logger; @@ -26,6 +27,7 @@ /** * The task ID representation composed as subtopology plus the assigned partition ID. */ +@InterfaceAudience.Public public class TaskId implements Comparable { private static final Logger LOG = LoggerFactory.getLogger(TaskId.class); diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/TimestampExtractor.java b/streams/src/main/java/org/apache/kafka/streams/processor/TimestampExtractor.java index aec113458a729..03a069b4911f2 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/TimestampExtractor.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/TimestampExtractor.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.processor; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.kstream.KTable; /** @@ -24,6 +25,7 @@ * The extracted timestamp is defined as milliseconds. */ @FunctionalInterface +@InterfaceAudience.Public public interface TimestampExtractor { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/To.java b/streams/src/main/java/org/apache/kafka/streams/processor/To.java index 69c0c5b4b5f54..8f8d04385b800 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/To.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/To.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; /** * This class is used to provide the optional parameters when sending output records to downstream processor * using {@link ProcessorContext#forward(Object, Object, To)}. */ +@InterfaceAudience.Public public class To { protected String childName; protected long timestamp; diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/TopicNameExtractor.java b/streams/src/main/java/org/apache/kafka/streams/processor/TopicNameExtractor.java index a7fb25df3fb53..1ced2e05c8fb7 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/TopicNameExtractor.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/TopicNameExtractor.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An interface that allows to dynamically determine the name of the Kafka topic to send at the sink node of the topology. */ @FunctionalInterface +@InterfaceAudience.Public public interface TopicNameExtractor { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/UsePartitionTimeOnInvalidTimestamp.java b/streams/src/main/java/org/apache/kafka/streams/processor/UsePartitionTimeOnInvalidTimestamp.java index 92c4022085cc5..ec64f8132be74 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/UsePartitionTimeOnInvalidTimestamp.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/UsePartitionTimeOnInvalidTimestamp.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.processor; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.StreamsException; /** @@ -43,6 +44,7 @@ * @see WallclockTimestampExtractor */ +@InterfaceAudience.Public public class UsePartitionTimeOnInvalidTimestamp extends ExtractRecordMetadataTimestamp { /** * Returns the current stream-time as new timestamp for the record. diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/WallclockTimestampExtractor.java b/streams/src/main/java/org/apache/kafka/streams/processor/WallclockTimestampExtractor.java index 799cdf4d2f49f..8f13d93af269a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/WallclockTimestampExtractor.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/WallclockTimestampExtractor.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Retrieves current wall clock timestamps as {@link System#currentTimeMillis()}. @@ -30,6 +32,7 @@ * @see LogAndSkipOnInvalidTimestamp * @see UsePartitionTimeOnInvalidTimestamp */ +@InterfaceAudience.Public public class WallclockTimestampExtractor implements TimestampExtractor { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/ContextualFixedKeyProcessor.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/ContextualFixedKeyProcessor.java index 7a10675ee59b7..6efc6b7c38b17 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/ContextualFixedKeyProcessor.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/ContextualFixedKeyProcessor.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An abstract implementation of {@link FixedKeyProcessor} that manages the {@link FixedKeyProcessorContext} instance. * @@ -23,6 +26,7 @@ * @param the type of input values * @param the type of output values */ +@InterfaceAudience.Public public abstract class ContextualFixedKeyProcessor implements FixedKeyProcessor { private FixedKeyProcessorContext context; diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/ContextualProcessor.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/ContextualProcessor.java index b3b420fd52f39..8419108d0e78f 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/ContextualProcessor.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/ContextualProcessor.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * An abstract implementation of {@link Processor} that manages the {@link ProcessorContext} instance. * @@ -24,6 +27,7 @@ * @param the type of output keys * @param the type of output values */ +@InterfaceAudience.Public public abstract class ContextualProcessor implements Processor { private ProcessorContext context; diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessor.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessor.java index c8647e2ad0c8c..0ffb544938988 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessor.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessor.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.PunctuationType; import org.apache.kafka.streams.processor.Punctuator; import org.apache.kafka.streams.processor.StateStore; @@ -30,6 +31,7 @@ * @param the type of output values */ @FunctionalInterface +@InterfaceAudience.Public public interface FixedKeyProcessor { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessorContext.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessorContext.java index 1b940c2d17a0b..130d0be7a7aaa 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessorContext.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessorContext.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Processor context interface for {@link FixedKeyRecord}. * * @param a bound on the types of keys that may be forwarded * @param a bound on the types of values that may be forwarded */ +@InterfaceAudience.Public public interface FixedKeyProcessorContext extends ProcessingContext { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessorSupplier.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessorSupplier.java index 06c5699b9d5b4..8552cf1137acd 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessorSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyProcessorSupplier.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.ConnectedStoreProvider; import java.util.function.Supplier; @@ -32,6 +33,7 @@ * @param the type of output values */ @FunctionalInterface +@InterfaceAudience.Public public interface FixedKeyProcessorSupplier extends ConnectedStoreProvider, Supplier> { diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyRecord.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyRecord.java index 1d9490d7750e7..c586624fd075e 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyRecord.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/FixedKeyRecord.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; import org.apache.kafka.streams.errors.StreamsException; @@ -36,6 +37,7 @@ * @param The type of the fixed key * @param The type of the value */ +@InterfaceAudience.Public public final class FixedKeyRecord { private final K key; diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/InternalFixedKeyRecordFactory.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/InternalFixedKeyRecordFactory.java index 2d215a821e581..08a947eacfb4d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/InternalFixedKeyRecordFactory.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/InternalFixedKeyRecordFactory.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public final class InternalFixedKeyRecordFactory { private InternalFixedKeyRecordFactory() { diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessingContext.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessingContext.java index 2030db9ae950b..9bfa5a8b39ae5 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessingContext.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessingContext.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Deserializer; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.streams.StreamsBuilder; @@ -39,6 +40,7 @@ /** * Processor context interface. */ +@InterfaceAudience.Public public interface ProcessingContext { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/Processor.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/Processor.java index 4a4fa67398809..9879d73159bae 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/Processor.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/Processor.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.PunctuationType; import org.apache.kafka.streams.processor.Punctuator; import org.apache.kafka.streams.processor.StateStore; @@ -31,6 +32,7 @@ * @param the type of output values */ @FunctionalInterface +@InterfaceAudience.Public public interface Processor { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorContext.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorContext.java index 4e5e0b1a7560a..1be886845c5f0 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorContext.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorContext.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Processor context interface for {@link Record}. * * @param a bound on the types of keys that may be forwarded * @param a bound on the types of values that may be forwarded */ +@InterfaceAudience.Public public interface ProcessorContext extends ProcessingContext { /** * Forward a record to all child processors. diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorSupplier.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorSupplier.java index 7ee1a5f1df2fd..99a568597c2a8 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorSupplier.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.Topology; import org.apache.kafka.streams.processor.ConnectedStoreProvider; @@ -38,6 +39,7 @@ * @param the type of output values */ @FunctionalInterface +@InterfaceAudience.Public public interface ProcessorSupplier extends ConnectedStoreProvider, Supplier> { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorWrapper.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorWrapper.java index 22b80a35ecb3e..2396be090d4b9 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorWrapper.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/ProcessorWrapper.java @@ -18,6 +18,7 @@ package org.apache.kafka.streams.processor.api; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.StreamsBuilder; import org.apache.kafka.streams.StreamsConfig; import org.apache.kafka.streams.Topology; @@ -42,6 +43,7 @@ * the {@code ProcessorWrapper} is instantiated, and will provide it with the TopologyConfigs that were passed in * to the {@link StreamsBuilder} or {@link Topology} constructor. */ +@InterfaceAudience.Public public interface ProcessorWrapper extends Configurable { @Override diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/Record.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/Record.java index 225b95fa4006d..a2a6df43c6ed8 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/Record.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/Record.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; import org.apache.kafka.streams.errors.StreamsException; @@ -35,6 +36,7 @@ * @param The type of the key * @param The type of the value */ +@InterfaceAudience.Public public class Record { private final K key; private final V value; diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/RecordMetadata.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/RecordMetadata.java index c24b9a7ab168d..46eff7710b725 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/RecordMetadata.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/RecordMetadata.java @@ -16,9 +16,11 @@ */ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.kstream.ValueTransformerWithKeySupplier; import org.apache.kafka.streams.processor.Punctuator; +@InterfaceAudience.Public public interface RecordMetadata { /** * Return the topic name of the current input record; could be {@code null} if it is not diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/WrappedFixedKeyProcessorSupplier.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/WrappedFixedKeyProcessorSupplier.java index 8fb70dbfd54de..8674b4bea7439 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/WrappedFixedKeyProcessorSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/WrappedFixedKeyProcessorSupplier.java @@ -17,6 +17,8 @@ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Marker interface for classes implementing {@link FixedKeyProcessorSupplier} * that have been wrapped via a {@link ProcessorWrapper}. @@ -25,6 +27,7 @@ * use the {@link ProcessorWrapper#asWrappedFixedKey(FixedKeyProcessorSupplier)} method */ @FunctionalInterface +@InterfaceAudience.Public public interface WrappedFixedKeyProcessorSupplier extends FixedKeyProcessorSupplier { } diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/api/WrappedProcessorSupplier.java b/streams/src/main/java/org/apache/kafka/streams/processor/api/WrappedProcessorSupplier.java index 6349b8e52c83a..f6086c5743816 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/api/WrappedProcessorSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/api/WrappedProcessorSupplier.java @@ -17,6 +17,8 @@ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Marker interface for classes implementing {@link ProcessorSupplier} * that have been wrapped via a {@link ProcessorWrapper}. @@ -25,6 +27,7 @@ * use the {@link ProcessorWrapper#asWrapped(ProcessorSupplier)} method */ @FunctionalInterface +@InterfaceAudience.Public public interface WrappedProcessorSupplier extends ProcessorSupplier { } diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/ApplicationState.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/ApplicationState.java index 7a3d687ee3287..d08b972125bd1 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/ApplicationState.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/ApplicationState.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.assignment; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.TaskAssignmentException; import org.apache.kafka.streams.processor.TaskId; @@ -27,6 +28,7 @@ * of each KafkaStreams client with at least one StreamThread participating in this rebalance, the * assignment-related configs, and the tasks to be assigned. */ +@InterfaceAudience.Public public interface ApplicationState { /** * @param computeTaskLags whether to include task lag information in the returned metadata. Note that passing diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/AssignmentConfigs.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/AssignmentConfigs.java index 4b0d4c31f9e8d..b39e012c362cc 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/AssignmentConfigs.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/AssignmentConfigs.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.assignment; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.streams.StreamsConfig; @@ -25,6 +26,7 @@ /** * Assignment related configs for the Kafka Streams {@link TaskAssignor}. */ +@InterfaceAudience.Public public class AssignmentConfigs { private final long acceptableRecoveryLag; private final int maxWarmupReplicas; diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/KafkaStreamsAssignment.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/KafkaStreamsAssignment.java index 080487f250a45..1d2588b140cab 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/KafkaStreamsAssignment.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/KafkaStreamsAssignment.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.assignment; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TaskId; import java.time.Instant; @@ -32,6 +33,7 @@ * A simple container class for the assignor to return the desired placement of active and standby tasks on * KafkaStreams clients. */ +@InterfaceAudience.Public public class KafkaStreamsAssignment { private final ProcessId processId; diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/KafkaStreamsState.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/KafkaStreamsState.java index 3aaddf7d732ef..698881ee014da 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/KafkaStreamsState.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/KafkaStreamsState.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.assignment; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TaskId; import org.apache.kafka.streams.state.HostInfo; @@ -26,6 +27,7 @@ /** * A read-only metadata class representing the current state of each KafkaStreams client with at least one StreamThread participating in this rebalance */ +@InterfaceAudience.Public public interface KafkaStreamsState { /** * @return the processId of the application instance running on this KafkaStreams client diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/ProcessId.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/ProcessId.java index 0a3c2c2bfb4e1..16a278b836f3f 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/ProcessId.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/ProcessId.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor.assignment; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.UUID; /** A simple wrapper around UUID that abstracts a Process ID */ +@InterfaceAudience.Public public class ProcessId implements Comparable { private final UUID id; diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskAssignmentUtils.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskAssignmentUtils.java index 2261e27c367f5..e8452efc37055 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskAssignmentUtils.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskAssignmentUtils.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.processor.assignment; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; import org.apache.kafka.streams.StreamsConfig; import org.apache.kafka.streams.processor.TaskId; @@ -52,6 +53,7 @@ /** * A set of utilities to help implement task assignment via the {@link TaskAssignor} */ +@InterfaceAudience.Public public final class TaskAssignmentUtils { private static final Logger LOG = LoggerFactory.getLogger(TaskAssignmentUtils.class); diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskAssignor.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskAssignor.java index 48e565e28007c..4edb5d6e8d319 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskAssignor.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskAssignor.java @@ -19,6 +19,7 @@ import org.apache.kafka.clients.consumer.ConsumerPartitionAssignor.GroupAssignment; import org.apache.kafka.clients.consumer.ConsumerPartitionAssignor.GroupSubscription; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.StreamsUncaughtExceptionHandler; import org.apache.kafka.streams.errors.TaskAssignmentException; @@ -31,6 +32,7 @@ * The implementation may also override the {@code onAssignmentComputed} callback for insight into * the result of the assignment result. */ +@InterfaceAudience.Public public interface TaskAssignor extends Configurable { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskInfo.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskInfo.java index b1f7df4784bba..624e3bb2b02d0 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskInfo.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskInfo.java @@ -14,9 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.processor.assignment; +package org.apache.kafka.streams.processor.assignment; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TaskId; import java.util.Set; @@ -28,6 +29,7 @@ * for all logged state stores, and the rack ids of all replicas of each topic partition * in the task. */ +@InterfaceAudience.Public public interface TaskInfo { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskTopicPartition.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskTopicPartition.java index cb6dbc376efba..7603cb3ed7079 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskTopicPartition.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/TaskTopicPartition.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor.assignment; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.util.Optional; import java.util.Set; @@ -27,6 +29,7 @@ * looking at, and the rack information of the partition, this container class should have * everything necessary to make informed task assignment decisions. */ +@InterfaceAudience.Public public interface TaskTopicPartition { /** * diff --git a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/assignors/StickyTaskAssignor.java b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/assignors/StickyTaskAssignor.java index 6ad61851ddae3..ec16c0dde3d50 100644 --- a/streams/src/main/java/org/apache/kafka/streams/processor/assignment/assignors/StickyTaskAssignor.java +++ b/streams/src/main/java/org/apache/kafka/streams/processor/assignment/assignors/StickyTaskAssignor.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.processor.assignment.assignors; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.TaskId; import org.apache.kafka.streams.processor.assignment.ApplicationState; import org.apache.kafka.streams.processor.assignment.KafkaStreamsAssignment; @@ -48,7 +50,7 @@ import static java.util.Collections.unmodifiableMap; - +@InterfaceAudience.Public public class StickyTaskAssignor implements TaskAssignor { private static final Logger LOG = LoggerFactory.getLogger(StickyTaskAssignor.class); diff --git a/streams/src/main/java/org/apache/kafka/streams/query/FailureReason.java b/streams/src/main/java/org/apache/kafka/streams/query/FailureReason.java index 4e72edefd4a5e..8a6e892e426c4 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/FailureReason.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/FailureReason.java @@ -14,9 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.query; +package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; /** @@ -27,6 +28,7 @@ * Intended to be used in {@link QueryResult#forFailure(FailureReason, String)}. */ @Evolving +@InterfaceAudience.Public public enum FailureReason { /** * Failure indicating that the store doesn't know how to handle the given query. diff --git a/streams/src/main/java/org/apache/kafka/streams/query/KeyQuery.java b/streams/src/main/java/org/apache/kafka/streams/query/KeyQuery.java index d081d0b44b72d..fc5d4b894935a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/KeyQuery.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/KeyQuery.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import java.util.Objects; @@ -26,6 +27,7 @@ * @param Type of values */ @Evolving +@InterfaceAudience.Public public final class KeyQuery implements Query { private final K key; diff --git a/streams/src/main/java/org/apache/kafka/streams/query/MultiVersionedKeyQuery.java b/streams/src/main/java/org/apache/kafka/streams/query/MultiVersionedKeyQuery.java index 31232a83dd529..f35bec05f7134 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/MultiVersionedKeyQuery.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/MultiVersionedKeyQuery.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import org.apache.kafka.streams.state.VersionedRecordIterator; @@ -31,6 +32,7 @@ * @param The type of the result returned by this query. */ @Evolving +@InterfaceAudience.Public public final class MultiVersionedKeyQuery implements Query> { private final K key; diff --git a/streams/src/main/java/org/apache/kafka/streams/query/Position.java b/streams/src/main/java/org/apache/kafka/streams/query/Position.java index 94acd9d8adff4..20ae1743400cc 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/Position.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/Position.java @@ -14,9 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.query; +package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import java.util.Collections; @@ -41,6 +42,7 @@ * reference. */ @Evolving +@InterfaceAudience.Public public class Position { private final ConcurrentHashMap> position; diff --git a/streams/src/main/java/org/apache/kafka/streams/query/PositionBound.java b/streams/src/main/java/org/apache/kafka/streams/query/PositionBound.java index f5ec3c8c88f4c..8256c5f476475 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/PositionBound.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/PositionBound.java @@ -14,9 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.query; +package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import java.util.Objects; @@ -27,6 +28,7 @@ * specified bound. "Unbounded" places no restrictions on the current location of the partition. */ @Evolving +@InterfaceAudience.Public public class PositionBound { private final Position position; diff --git a/streams/src/main/java/org/apache/kafka/streams/query/Query.java b/streams/src/main/java/org/apache/kafka/streams/query/Query.java index ad77a911751c9..41d07947d4fb9 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/Query.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/Query.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * Marker interface that all interactive queries must implement (see {@link * org.apache.kafka.streams.KafkaStreams#query(StateQueryRequest)}). @@ -30,6 +33,7 @@ * * @param The type of the result returned by this query. */ +@InterfaceAudience.Public public interface Query { } diff --git a/streams/src/main/java/org/apache/kafka/streams/query/QueryConfig.java b/streams/src/main/java/org/apache/kafka/streams/query/QueryConfig.java index 259b67a2e98f3..72397bc5394c7 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/QueryConfig.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/QueryConfig.java @@ -17,12 +17,14 @@ package org.apache.kafka.streams.query; import org.apache.kafka.common.IsolationLevel; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; /** * Runtime configuration parameters */ @Evolving +@InterfaceAudience.Public public class QueryConfig { final boolean collectExecutionInfo; final IsolationLevel isolationLevel; diff --git a/streams/src/main/java/org/apache/kafka/streams/query/QueryResult.java b/streams/src/main/java/org/apache/kafka/streams/query/QueryResult.java index 28871f81e4f52..5d240bd951ac3 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/QueryResult.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/QueryResult.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.StateStore; import org.apache.kafka.streams.query.internals.FailedQueryResult; import org.apache.kafka.streams.query.internals.SucceededQueryResult; @@ -27,6 +28,7 @@ * * @param The result type of the query. */ +@InterfaceAudience.Public public interface QueryResult { /** * Static factory method to create a result object for a successful query. Used by StateStores diff --git a/streams/src/main/java/org/apache/kafka/streams/query/RangeQuery.java b/streams/src/main/java/org/apache/kafka/streams/query/RangeQuery.java index e24862d067b37..6e52893301b2c 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/RangeQuery.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/RangeQuery.java @@ -15,10 +15,9 @@ * limitations under the License. */ - package org.apache.kafka.streams.query; - +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import org.apache.kafka.streams.state.KeyValueIterator; @@ -36,6 +35,7 @@ * @param Type of values */ @Evolving +@InterfaceAudience.Public public final class RangeQuery implements Query> { diff --git a/streams/src/main/java/org/apache/kafka/streams/query/ResultOrder.java b/streams/src/main/java/org/apache/kafka/streams/query/ResultOrder.java index 06665f49c61d1..0ee9f5f71f9b4 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/ResultOrder.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/ResultOrder.java @@ -17,6 +17,9 @@ package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; + +@InterfaceAudience.Public public enum ResultOrder { ANY, ASCENDING, diff --git a/streams/src/main/java/org/apache/kafka/streams/query/StateQueryRequest.java b/streams/src/main/java/org/apache/kafka/streams/query/StateQueryRequest.java index e4574e9120b24..9b1996635b973 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/StateQueryRequest.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/StateQueryRequest.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.query; import org.apache.kafka.common.IsolationLevel; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import java.util.Optional; @@ -30,6 +31,7 @@ * @param The type of the query result. */ @Evolving +@InterfaceAudience.Public public class StateQueryRequest { private final String storeName; diff --git a/streams/src/main/java/org/apache/kafka/streams/query/StateQueryResult.java b/streams/src/main/java/org/apache/kafka/streams/query/StateQueryResult.java index 7ba8ca94af288..fd45c3a9c2d38 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/StateQueryResult.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/StateQueryResult.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import java.util.HashMap; @@ -31,6 +32,7 @@ * @param The type of the query result. */ @Evolving +@InterfaceAudience.Public public class StateQueryResult { private final Map> partitionResults = new HashMap<>(); diff --git a/streams/src/main/java/org/apache/kafka/streams/query/TimestampedKeyQuery.java b/streams/src/main/java/org/apache/kafka/streams/query/TimestampedKeyQuery.java index c2df7b537392a..f0b4c845acc41 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/TimestampedKeyQuery.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/TimestampedKeyQuery.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import org.apache.kafka.streams.state.TimestampedKeyValueStore; import org.apache.kafka.streams.state.ValueAndTimestamp; @@ -28,6 +29,7 @@ * @param Type of values */ @Evolving +@InterfaceAudience.Public public final class TimestampedKeyQuery implements Query> { private final K key; diff --git a/streams/src/main/java/org/apache/kafka/streams/query/TimestampedRangeQuery.java b/streams/src/main/java/org/apache/kafka/streams/query/TimestampedRangeQuery.java index 18acf6a785c8a..07ad4658dbe68 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/TimestampedRangeQuery.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/TimestampedRangeQuery.java @@ -15,10 +15,9 @@ * limitations under the License. */ - package org.apache.kafka.streams.query; - +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import org.apache.kafka.streams.state.KeyValueIterator; import org.apache.kafka.streams.state.TimestampedKeyValueStore; @@ -38,6 +37,7 @@ * @param Type of values */ @Evolving +@InterfaceAudience.Public public final class TimestampedRangeQuery implements Query>> { diff --git a/streams/src/main/java/org/apache/kafka/streams/query/VersionedKeyQuery.java b/streams/src/main/java/org/apache/kafka/streams/query/VersionedKeyQuery.java index 1c5503f560a09..74b74d63ef44b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/VersionedKeyQuery.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/VersionedKeyQuery.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import org.apache.kafka.streams.state.VersionedRecord; @@ -30,6 +31,7 @@ * @param The type of the value. */ @Evolving +@InterfaceAudience.Public public final class VersionedKeyQuery implements Query> { private final K key; diff --git a/streams/src/main/java/org/apache/kafka/streams/query/WindowKeyQuery.java b/streams/src/main/java/org/apache/kafka/streams/query/WindowKeyQuery.java index 79e9dc80120e9..ab14cfc728529 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/WindowKeyQuery.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/WindowKeyQuery.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.annotation.InterfaceStability.Evolving; import org.apache.kafka.streams.state.WindowStoreIterator; @@ -24,6 +25,7 @@ import java.util.Optional; @Evolving +@InterfaceAudience.Public public class WindowKeyQuery implements Query> { private final K key; diff --git a/streams/src/main/java/org/apache/kafka/streams/query/WindowRangeQuery.java b/streams/src/main/java/org/apache/kafka/streams/query/WindowRangeQuery.java index fb658d738efe9..3a457776321eb 100644 --- a/streams/src/main/java/org/apache/kafka/streams/query/WindowRangeQuery.java +++ b/streams/src/main/java/org/apache/kafka/streams/query/WindowRangeQuery.java @@ -17,12 +17,14 @@ package org.apache.kafka.streams.query; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.kstream.Windowed; import org.apache.kafka.streams.state.KeyValueIterator; import java.time.Instant; import java.util.Optional; +@InterfaceAudience.Public public class WindowRangeQuery implements Query, V>> { private final Optional key; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/AggregationWithHeaders.java b/streams/src/main/java/org/apache/kafka/streams/state/AggregationWithHeaders.java index 0e1173c2ed2b5..93228b40a9fc8 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/AggregationWithHeaders.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/AggregationWithHeaders.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import java.util.Objects; @@ -26,6 +27,7 @@ * * @param the aggregation type */ +@InterfaceAudience.Public public final class AggregationWithHeaders { private final AGG aggregation; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/BuiltInDslStoreSuppliers.java b/streams/src/main/java/org/apache/kafka/streams/state/BuiltInDslStoreSuppliers.java index 28e3c65d6781d..29a2404c24230 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/BuiltInDslStoreSuppliers.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/BuiltInDslStoreSuppliers.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.DslStoreFormat; import org.apache.kafka.streams.kstream.EmitStrategy; import org.apache.kafka.streams.state.internals.RocksDbIndexedTimeOrderedWindowBytesStoreSupplier; @@ -27,6 +28,7 @@ * Collection of builtin {@link DslStoreSuppliers} for Kafka Streams. Today we * support RocksDb and InMemory stores out of the box. */ +@InterfaceAudience.Public public class BuiltInDslStoreSuppliers { public static final DslStoreSuppliers ROCKS_DB = new RocksDBDslStoreSuppliers(); diff --git a/streams/src/main/java/org/apache/kafka/streams/state/DslKeyValueParams.java b/streams/src/main/java/org/apache/kafka/streams/state/DslKeyValueParams.java index 3bf696761fb22..a5388a4e711d6 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/DslKeyValueParams.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/DslKeyValueParams.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.DslStoreFormat; import java.util.Objects; @@ -24,6 +25,7 @@ * {@code DslKeyValueParams} is a wrapper class for all parameters that function * as inputs to {@link DslStoreSuppliers#keyValueStore(DslKeyValueParams)}. */ +@InterfaceAudience.Public public class DslKeyValueParams { private final String name; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/DslSessionParams.java b/streams/src/main/java/org/apache/kafka/streams/state/DslSessionParams.java index 16c8c523ec7e7..f5c88f7ef3a94 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/DslSessionParams.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/DslSessionParams.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.DslStoreFormat; import org.apache.kafka.streams.kstream.EmitStrategy; @@ -26,6 +27,7 @@ * {@code DslSessionParams} is a wrapper class for all parameters that function * as inputs to {@link DslStoreSuppliers#sessionStore(DslSessionParams)}. */ +@InterfaceAudience.Public public class DslSessionParams { private final String name; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/DslStoreSuppliers.java b/streams/src/main/java/org/apache/kafka/streams/state/DslStoreSuppliers.java index 1c51a07e674e3..b99b73602ed25 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/DslStoreSuppliers.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/DslStoreSuppliers.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.state; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.TopologyConfig; import java.util.Map; @@ -47,6 +48,7 @@ *

    Kafka Streams is packaged with some pre-existing {@code DslStoreSuppliers} * that exist in {@link BuiltInDslStoreSuppliers} */ +@InterfaceAudience.Public public interface DslStoreSuppliers extends Configurable { @Override diff --git a/streams/src/main/java/org/apache/kafka/streams/state/DslWindowParams.java b/streams/src/main/java/org/apache/kafka/streams/state/DslWindowParams.java index 3d81c2467178e..749a92b3936df 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/DslWindowParams.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/DslWindowParams.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.DslStoreFormat; import org.apache.kafka.streams.kstream.EmitStrategy; @@ -26,6 +27,7 @@ * {@code DslWindowParams} is a wrapper class for all parameters that function * as inputs to {@link DslStoreSuppliers#windowStore(DslWindowParams)}. */ +@InterfaceAudience.Public public class DslWindowParams { private final String name; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/HeadersBytesStore.java b/streams/src/main/java/org/apache/kafka/streams/state/HeadersBytesStore.java index 8d20b1a970500..73ab986ee6dec 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/HeadersBytesStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/HeadersBytesStore.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Marker interface to indicate that a bytes store understands the value-with-headers format @@ -26,6 +28,7 @@ * Per KIP-1271, the value format is: [headersSize(varint)][headersBytes][payloadBytes] * where payloadBytes is the existing serialized value (e.g., [timestamp(8)][value] for timestamped stores). */ +@InterfaceAudience.Public public interface HeadersBytesStore { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/HeadersBytesStoreSupplier.java b/streams/src/main/java/org/apache/kafka/streams/state/HeadersBytesStoreSupplier.java index 411f4bf787d42..1858f93aa5e31 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/HeadersBytesStoreSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/HeadersBytesStoreSupplier.java @@ -14,10 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A store supplier that can be used to create one or more "header" stores, * specifically, {@link HeadersBytesStore} instances. */ +@InterfaceAudience.Public public interface HeadersBytesStoreSupplier { } diff --git a/streams/src/main/java/org/apache/kafka/streams/state/HostInfo.java b/streams/src/main/java/org/apache/kafka/streams/state/HostInfo.java index 1393dc8667e80..3d7e2e188f938 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/HostInfo.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/HostInfo.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.config.ConfigException; import org.apache.kafka.common.utils.Utils; import org.apache.kafka.streams.KafkaStreams; @@ -37,6 +38,7 @@ * If developers wish to expose an endpoint in their KafkaStreams applications they should provide the above * config. */ +@InterfaceAudience.Public public class HostInfo { private final String host; private final int port; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/KeyValueBytesStoreSupplier.java b/streams/src/main/java/org/apache/kafka/streams/state/KeyValueBytesStoreSupplier.java index de37b132acdd6..32fa506b5651b 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/KeyValueBytesStoreSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/KeyValueBytesStoreSupplier.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; /** @@ -28,4 +29,5 @@ *

  • If the key does not exist, get operations should return null value bytes.
  • * */ +@InterfaceAudience.Public public interface KeyValueBytesStoreSupplier extends StoreSupplier> { } \ No newline at end of file diff --git a/streams/src/main/java/org/apache/kafka/streams/state/KeyValueIterator.java b/streams/src/main/java/org/apache/kafka/streams/state/KeyValueIterator.java index b1f5e2c5485db..e6ae921793125 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/KeyValueIterator.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/KeyValueIterator.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; import java.io.Closeable; @@ -31,6 +32,7 @@ * @param Type of keys * @param Type of values */ +@InterfaceAudience.Public public interface KeyValueIterator extends Iterator>, Closeable { @Override diff --git a/streams/src/main/java/org/apache/kafka/streams/state/KeyValueStore.java b/streams/src/main/java/org/apache/kafka/streams/state/KeyValueStore.java index 0d56b947dbbcc..1671f76fe5c10 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/KeyValueStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/KeyValueStore.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; import org.apache.kafka.streams.errors.InvalidStateStoreException; import org.apache.kafka.streams.processor.StateStore; @@ -28,6 +29,7 @@ * @param The key type * @param The value type */ +@InterfaceAudience.Public public interface KeyValueStore extends StateStore, ReadOnlyKeyValueStore { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/QueryableStoreType.java b/streams/src/main/java/org/apache/kafka/streams/state/QueryableStoreType.java index 97715539e1f93..824833e094a7c 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/QueryableStoreType.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/QueryableStoreType.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.processor.StateStore; import org.apache.kafka.streams.state.internals.StateStoreProvider; @@ -26,6 +28,7 @@ * @param The store type * @see QueryableStoreTypes */ +@InterfaceAudience.Public public interface QueryableStoreType { /** @@ -46,6 +49,7 @@ public interface QueryableStoreType { * @return a read-only interface over a {@code StateStore} * (cf. {@link QueryableStoreTypes.KeyValueStoreType}) */ + @SuppressKafkaInternalApiUsage("KIP-1265: method leaks internal StateStoreProvider — pending KIP review to promote or refactor") T create(final StateStoreProvider storeProvider, final String storeName); } \ No newline at end of file diff --git a/streams/src/main/java/org/apache/kafka/streams/state/QueryableStoreTypes.java b/streams/src/main/java/org/apache/kafka/streams/state/QueryableStoreTypes.java index 9f23e5855811b..f547b2c9ab8a8 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/QueryableStoreTypes.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/QueryableStoreTypes.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.StoreQueryParameters; import org.apache.kafka.streams.Topology; @@ -33,6 +35,7 @@ * These can be used with {@link KafkaStreams#store(StoreQueryParameters)}. * To access and query the {@link StateStore}s that are part of a {@link Topology}. */ +@InterfaceAudience.Public public final class QueryableStoreTypes { /** @@ -149,6 +152,7 @@ public static class KeyValueStoreType extends QueryableStoreTypeMatcher create( final StateStoreProvider storeProvider, final String storeName @@ -172,6 +176,7 @@ public boolean accepts(final StateStore stateStore) { } @Override + @SuppressKafkaInternalApiUsage("KIP-1265: override leaks internal StateStoreProvider — pending KIP review") public ReadOnlyKeyValueStore> create( final StateStoreProvider storeProvider, final String storeName @@ -203,6 +208,7 @@ public static class WindowStoreType extends QueryableStoreTypeMatcher create( final StateStoreProvider storeProvider, final String storeName @@ -225,6 +231,7 @@ public boolean accepts(final StateStore stateStore) { } @Override + @SuppressKafkaInternalApiUsage("KIP-1265: override leaks internal StateStoreProvider — pending KIP review") public ReadOnlyWindowStore> create( final StateStoreProvider storeProvider, final String storeName @@ -256,6 +263,7 @@ public static class SessionStoreType extends QueryableStoreTypeMatcher create( final StateStoreProvider storeProvider, final String storeName diff --git a/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlyKeyValueStore.java b/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlyKeyValueStore.java index 832354a2e6222..73c715f8dd0f8 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlyKeyValueStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlyKeyValueStore.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.state; import org.apache.kafka.common.IsolationLevel; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serializer; import org.apache.kafka.streams.errors.InvalidStateStoreException; @@ -33,6 +34,7 @@ * @param the key type * @param the value type */ +@InterfaceAudience.Public public interface ReadOnlyKeyValueStore { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlySessionStore.java b/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlySessionStore.java index 772f8d1b6cbcd..819a885a724aa 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlySessionStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlySessionStore.java @@ -14,10 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.state; +package org.apache.kafka.streams.state; import org.apache.kafka.common.IsolationLevel; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.kstream.Windowed; import java.time.Instant; @@ -29,6 +30,7 @@ * @param the key type * @param the aggregated value type */ +@InterfaceAudience.Public public interface ReadOnlySessionStore { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlyWindowStore.java b/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlyWindowStore.java index f8dff98181496..426e610898bb2 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlyWindowStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/ReadOnlyWindowStore.java @@ -17,6 +17,7 @@ package org.apache.kafka.streams.state; import org.apache.kafka.common.IsolationLevel; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.InvalidStateStoreException; import org.apache.kafka.streams.kstream.Windowed; @@ -34,6 +35,7 @@ * @param Type of keys * @param Type of values */ +@InterfaceAudience.Public public interface ReadOnlyWindowStore { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/RocksDBConfigSetter.java b/streams/src/main/java/org/apache/kafka/streams/state/RocksDBConfigSetter.java index 8f20d0f07a5f6..fd88b3414ecd7 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/RocksDBConfigSetter.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/RocksDBConfigSetter.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; + import org.rocksdb.Options; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,6 +32,7 @@ * the existing one (rather than create a new BlockBasedTableConfig object) so as to not lose the other default settings. * This can be done as {@code BlockBasedTableConfig tableConfig = (BlockBasedTableConfig) options.tableFormatConfig();} */ +@InterfaceAudience.Public public interface RocksDBConfigSetter { Logger LOG = LoggerFactory.getLogger(RocksDBConfigSetter.class); diff --git a/streams/src/main/java/org/apache/kafka/streams/state/SessionBytesStoreSupplier.java b/streams/src/main/java/org/apache/kafka/streams/state/SessionBytesStoreSupplier.java index 5c7bc2532091c..76c67b3d7ec49 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/SessionBytesStoreSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/SessionBytesStoreSupplier.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; /** @@ -28,6 +29,7 @@ *
  • {@code null} value bytes should never be returned in range query results.
  • * */ +@InterfaceAudience.Public public interface SessionBytesStoreSupplier extends StoreSupplier> { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/SessionStore.java b/streams/src/main/java/org/apache/kafka/streams/state/SessionStore.java index 76a43173946e4..5494384e8e086 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/SessionStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/SessionStore.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.internals.ApiUtils; import org.apache.kafka.streams.kstream.Window; import org.apache.kafka.streams.kstream.Windowed; @@ -37,6 +38,7 @@ * @param type of the record keys * @param type of the aggregated values */ +@InterfaceAudience.Public public interface SessionStore extends StateStore, ReadOnlySessionStore { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/SessionStoreWithHeaders.java b/streams/src/main/java/org/apache/kafka/streams/state/SessionStoreWithHeaders.java index 8cae65c809355..3d394bf53ece0 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/SessionStoreWithHeaders.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/SessionStoreWithHeaders.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.kstream.Window; import org.apache.kafka.streams.kstream.Windowed; import org.apache.kafka.streams.processor.StateStore; @@ -32,6 +33,7 @@ * @param type of the record keys * @param type of the aggregated values */ +@InterfaceAudience.Public public interface SessionStoreWithHeaders extends StateStore, SessionStore> { } diff --git a/streams/src/main/java/org/apache/kafka/streams/state/StateSerdes.java b/streams/src/main/java/org/apache/kafka/streams/state/StateSerdes.java index 8632dd37bfe84..3f4b23abfff48 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/StateSerdes.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/StateSerdes.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; import org.apache.kafka.common.serialization.Deserializer; @@ -33,6 +34,7 @@ * @param key type of serde * @param value type of serde */ +@InterfaceAudience.Public public final class StateSerdes { public static final int TIMESTAMP_SIZE = 8; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/StoreBuilder.java b/streams/src/main/java/org/apache/kafka/streams/state/StoreBuilder.java index 430ba27131017..2a9c5b2ac7272 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/StoreBuilder.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/StoreBuilder.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.StateStore; import java.util.Map; @@ -24,6 +25,7 @@ * Build a {@link StateStore} wrapped with optional caching and logging. * @param the type of store to build */ +@InterfaceAudience.Public public interface StoreBuilder { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/StoreSupplier.java b/streams/src/main/java/org/apache/kafka/streams/state/StoreSupplier.java index 10e6f2d5a37a7..22718c27a6fc5 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/StoreSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/StoreSupplier.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.processor.StateStore; /** @@ -23,6 +24,7 @@ * * @param State store type */ +@InterfaceAudience.Public public interface StoreSupplier { /** * Return the name of this state store supplier. diff --git a/streams/src/main/java/org/apache/kafka/streams/state/Stores.java b/streams/src/main/java/org/apache/kafka/streams/state/Stores.java index 675cf06d45c5a..4153f8aabd536 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/Stores.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/Stores.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.common.utils.Bytes; import org.apache.kafka.common.utils.Time; @@ -84,6 +85,7 @@ * topology.addStateStore(storeBuilder, "processorName"); * } */ +@InterfaceAudience.Public public final class Stores { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedBytesStore.java b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedBytesStore.java index e609b70a01ba0..bdf04bc054ca6 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedBytesStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedBytesStore.java @@ -16,10 +16,13 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.nio.ByteBuffer; import static org.apache.kafka.clients.consumer.ConsumerRecord.NO_TIMESTAMP; +@InterfaceAudience.Public public interface TimestampedBytesStore { static byte[] convertToTimestampedFormat(final byte[] plainValue) { if (plainValue == null) { diff --git a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedKeyValueStore.java b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedKeyValueStore.java index ef5ef57443b49..7eb3b9fdb5115 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedKeyValueStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedKeyValueStore.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A key-(value/timestamp) store that supports put/get/delete and range queries. * * @param The key type * @param The value type */ +@InterfaceAudience.Public public interface TimestampedKeyValueStore extends KeyValueStore> { } \ No newline at end of file diff --git a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedKeyValueStoreWithHeaders.java b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedKeyValueStoreWithHeaders.java index d44184cb4ea8f..8022fb334251f 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedKeyValueStoreWithHeaders.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedKeyValueStoreWithHeaders.java @@ -14,14 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A key-(value/timestamp/headers) store that supports put/get/delete. * * @param The key type * @param The value type */ +@InterfaceAudience.Public public interface TimestampedKeyValueStoreWithHeaders extends KeyValueStore> { } \ No newline at end of file diff --git a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedWindowStore.java b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedWindowStore.java index 7d52c12b17ff6..fbb0fb9cc3889 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedWindowStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedWindowStore.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.kstream.Windowed; /** @@ -31,4 +32,5 @@ * @param Type of keys * @param Type of values */ +@InterfaceAudience.Public public interface TimestampedWindowStore extends WindowStore> { } \ No newline at end of file diff --git a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedWindowStoreWithHeaders.java b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedWindowStoreWithHeaders.java index e1793d7734d32..673c7ae90fc5d 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/TimestampedWindowStoreWithHeaders.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/TimestampedWindowStoreWithHeaders.java @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; /** * Interface for storing the aggregated values of fixed-size time windows with headers support. @@ -30,5 +32,6 @@ * @param Type of keys * @param Type of values */ +@InterfaceAudience.Public public interface TimestampedWindowStoreWithHeaders extends WindowStore> { } diff --git a/streams/src/main/java/org/apache/kafka/streams/state/ValueAndTimestamp.java b/streams/src/main/java/org/apache/kafka/streams/state/ValueAndTimestamp.java index 227021d6cf7e3..f639ae91f5d5a 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/ValueAndTimestamp.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/ValueAndTimestamp.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; import java.util.Objects; @@ -25,6 +26,7 @@ * * @param */ +@InterfaceAudience.Public public final class ValueAndTimestamp { private final V value; private final long timestamp; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/ValueTimestampHeaders.java b/streams/src/main/java/org/apache/kafka/streams/state/ValueTimestampHeaders.java index 6a92413486797..0e0bd4b83de59 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/ValueTimestampHeaders.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/ValueTimestampHeaders.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; @@ -26,6 +27,7 @@ * * @param the value type */ +@InterfaceAudience.Public public final class ValueTimestampHeaders { private final V value; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/VersionedBytesStore.java b/streams/src/main/java/org/apache/kafka/streams/state/VersionedBytesStore.java index e840824577e07..0ab6340030f46 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/VersionedBytesStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/VersionedBytesStore.java @@ -16,12 +16,14 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; /** * A representation of a versioned key-value store as a {@link KeyValueStore} of type <Bytes, byte[]>. * See {@link VersionedBytesStoreSupplier} for more. */ +@InterfaceAudience.Public public interface VersionedBytesStore extends KeyValueStore, TimestampedBytesStore { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/VersionedBytesStoreSupplier.java b/streams/src/main/java/org/apache/kafka/streams/state/VersionedBytesStoreSupplier.java index 5ba97335afab6..85f78aaa9ae34 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/VersionedBytesStoreSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/VersionedBytesStoreSupplier.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.StreamsBuilder; import org.apache.kafka.streams.kstream.KTable; import org.apache.kafka.streams.kstream.Materialized; @@ -33,6 +34,7 @@ * is represented as a {@code KeyValueStore KeyValueStore} by interpreting the * value bytes as containing record timestamp information in addition to raw record values. */ +@InterfaceAudience.Public public interface VersionedBytesStoreSupplier extends KeyValueBytesStoreSupplier { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/VersionedKeyValueStore.java b/streams/src/main/java/org/apache/kafka/streams/state/VersionedKeyValueStore.java index 40faaf003d3fe..1c0216baec203 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/VersionedKeyValueStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/VersionedKeyValueStore.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.InvalidStateStoreException; import org.apache.kafka.streams.processor.StateStore; @@ -39,6 +40,7 @@ * @param The key type * @param The value type */ +@InterfaceAudience.Public public interface VersionedKeyValueStore extends StateStore { long PUT_RETURN_CODE_VALID_TO_UNDEFINED = -1L; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/VersionedRecord.java b/streams/src/main/java/org/apache/kafka/streams/state/VersionedRecord.java index 6df07562853a3..27576e9bdca99 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/VersionedRecord.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/VersionedRecord.java @@ -14,8 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.util.Objects; import java.util.Optional; @@ -25,6 +28,7 @@ * * @param The value type */ +@InterfaceAudience.Public public final class VersionedRecord { private final V value; private final long timestamp; diff --git a/streams/src/main/java/org/apache/kafka/streams/state/VersionedRecordIterator.java b/streams/src/main/java/org/apache/kafka/streams/state/VersionedRecordIterator.java index 1dbd7502934cb..66c6dc1995e97 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/VersionedRecordIterator.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/VersionedRecordIterator.java @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.io.Closeable; import java.util.Iterator; - /** * Iterator interface of {@link VersionedRecord VersionedRecord}. *

    @@ -29,6 +31,7 @@ * * @param Type of values */ +@InterfaceAudience.Public public interface VersionedRecordIterator extends Iterator>, Closeable { @Override diff --git a/streams/src/main/java/org/apache/kafka/streams/state/WindowBytesStoreSupplier.java b/streams/src/main/java/org/apache/kafka/streams/state/WindowBytesStoreSupplier.java index 9ced28c180016..a5650d17bdca4 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/WindowBytesStoreSupplier.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/WindowBytesStoreSupplier.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.utils.Bytes; /** @@ -26,6 +27,7 @@ * 1. Null value bytes in put operations should be treated as delete. * 2. Null value bytes should never be returned in range query results. */ +@InterfaceAudience.Public public interface WindowBytesStoreSupplier extends StoreSupplier> { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/WindowStore.java b/streams/src/main/java/org/apache/kafka/streams/state/WindowStore.java index 04cbaf96a0009..febe62ba1c923 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/WindowStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/WindowStore.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.errors.InvalidStateStoreException; import org.apache.kafka.streams.internals.ApiUtils; import org.apache.kafka.streams.kstream.Windowed; @@ -33,6 +34,7 @@ * @param Type of keys * @param Type of values */ +@InterfaceAudience.Public public interface WindowStore extends StateStore, ReadOnlyWindowStore { /** diff --git a/streams/src/main/java/org/apache/kafka/streams/state/WindowStoreIterator.java b/streams/src/main/java/org/apache/kafka/streams/state/WindowStoreIterator.java index 7a318bd10ea78..15578008f60c6 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/WindowStoreIterator.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/WindowStoreIterator.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams.state; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.streams.KeyValue; import java.io.Closeable; @@ -30,6 +31,7 @@ * * @param Type of values */ +@InterfaceAudience.Public public interface WindowStoreIterator extends KeyValueIterator, Closeable { @Override diff --git a/streams/src/main/java/org/apache/kafka/streams/state/internals/InMemoryWindowStore.java b/streams/src/main/java/org/apache/kafka/streams/state/internals/InMemoryWindowStore.java index 6f5b1095f47ca..74c5816a56ab9 100644 --- a/streams/src/main/java/org/apache/kafka/streams/state/internals/InMemoryWindowStore.java +++ b/streams/src/main/java/org/apache/kafka/streams/state/internals/InMemoryWindowStore.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.state.internals; import org.apache.kafka.clients.consumer.ConsumerRecord; @@ -58,7 +59,6 @@ import static org.apache.kafka.streams.state.internals.WindowKeySchema.extractStoreKeyBytes; import static org.apache.kafka.streams.state.internals.WindowKeySchema.extractStoreTimestamp; - public class InMemoryWindowStore implements WindowStore, WithRetentionPeriod { private static final Logger LOG = LoggerFactory.getLogger(InMemoryWindowStore.class); diff --git a/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractColumnFamilyAccessorTest.java b/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractColumnFamilyAccessorTest.java index 848030dc57077..778cf3c9cdf76 100644 --- a/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractColumnFamilyAccessorTest.java +++ b/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractColumnFamilyAccessorTest.java @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.state.internals; +package org.apache.kafka.streams.state.internals; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.serialization.LongSerializer; diff --git a/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractSegmentsTest.java b/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractSegmentsTest.java index 5451ded03bcc9..e4108de78bf29 100644 --- a/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractSegmentsTest.java +++ b/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractSegmentsTest.java @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.state.internals; +package org.apache.kafka.streams.state.internals; import org.apache.kafka.common.metrics.Metrics; import org.apache.kafka.common.serialization.LongSerializer; diff --git a/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractSessionBytesStoreTest.java b/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractSessionBytesStoreTest.java index 39a1970f53312..94bba63099e24 100644 --- a/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractSessionBytesStoreTest.java +++ b/streams/src/test/java/org/apache/kafka/streams/state/internals/AbstractSessionBytesStoreTest.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.streams.state.internals; import org.apache.kafka.clients.producer.ProducerRecord; @@ -75,7 +76,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; - public abstract class AbstractSessionBytesStoreTest { static final long SEGMENT_INTERVAL = 60_000L; diff --git a/streams/src/test/java/org/apache/kafka/streams/state/internals/QueryableStoreProviderTest.java b/streams/src/test/java/org/apache/kafka/streams/state/internals/QueryableStoreProviderTest.java index 4a0d0bb759116..3d1135ac08875 100644 --- a/streams/src/test/java/org/apache/kafka/streams/state/internals/QueryableStoreProviderTest.java +++ b/streams/src/test/java/org/apache/kafka/streams/state/internals/QueryableStoreProviderTest.java @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.state.internals; +package org.apache.kafka.streams.state.internals; import org.apache.kafka.common.IsolationLevel; import org.apache.kafka.streams.StoreQueryParameters; diff --git a/streams/src/test/java/org/apache/kafka/streams/state/internals/ThreadCacheTest.java b/streams/src/test/java/org/apache/kafka/streams/state/internals/ThreadCacheTest.java index d2775c0f3bd06..5d6c1b1633e18 100644 --- a/streams/src/test/java/org/apache/kafka/streams/state/internals/ThreadCacheTest.java +++ b/streams/src/test/java/org/apache/kafka/streams/state/internals/ThreadCacheTest.java @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.state.internals; +package org.apache.kafka.streams.state.internals; import org.apache.kafka.common.header.internals.RecordHeaders; import org.apache.kafka.common.metrics.Metrics; diff --git a/streams/src/test/java/org/apache/kafka/streams/state/internals/WrappingStoreProviderTest.java b/streams/src/test/java/org/apache/kafka/streams/state/internals/WrappingStoreProviderTest.java index a2908a9306e16..368bafe78013b 100644 --- a/streams/src/test/java/org/apache/kafka/streams/state/internals/WrappingStoreProviderTest.java +++ b/streams/src/test/java/org/apache/kafka/streams/state/internals/WrappingStoreProviderTest.java @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.streams.state.internals; +package org.apache.kafka.streams.state.internals; import org.apache.kafka.common.IsolationLevel; import org.apache.kafka.common.serialization.Serdes; diff --git a/streams/test-utils/src/main/java/org/apache/kafka/streams/TestInputTopic.java b/streams/test-utils/src/main/java/org/apache/kafka/streams/TestInputTopic.java index c5966a7e0860f..452ebd36b12bc 100644 --- a/streams/test-utils/src/main/java/org/apache/kafka/streams/TestInputTopic.java +++ b/streams/test-utils/src/main/java/org/apache/kafka/streams/TestInputTopic.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Serializer; import org.apache.kafka.streams.test.TestRecord; @@ -46,6 +47,7 @@ * @see TopologyTestDriver */ +@InterfaceAudience.Public public class TestInputTopic { private final TopologyTestDriver driver; private final String topic; diff --git a/streams/test-utils/src/main/java/org/apache/kafka/streams/TestOutputTopic.java b/streams/test-utils/src/main/java/org/apache/kafka/streams/TestOutputTopic.java index f7ba8709e7833..545f72484f739 100644 --- a/streams/test-utils/src/main/java/org/apache/kafka/streams/TestOutputTopic.java +++ b/streams/test-utils/src/main/java/org/apache/kafka/streams/TestOutputTopic.java @@ -16,6 +16,7 @@ */ package org.apache.kafka.streams; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.serialization.Deserializer; import org.apache.kafka.streams.test.TestRecord; @@ -51,6 +52,7 @@ * @param the type of the record value * @see TopologyTestDriver */ +@InterfaceAudience.Public public class TestOutputTopic { private final TopologyTestDriver driver; private final String topic; diff --git a/streams/test-utils/src/main/java/org/apache/kafka/streams/TopologyTestDriver.java b/streams/test-utils/src/main/java/org/apache/kafka/streams/TopologyTestDriver.java index bad4fd58a7f45..cd9e2af0ce9e7 100644 --- a/streams/test-utils/src/main/java/org/apache/kafka/streams/TopologyTestDriver.java +++ b/streams/test-utils/src/main/java/org/apache/kafka/streams/TopologyTestDriver.java @@ -30,6 +30,7 @@ import org.apache.kafka.common.MetricName; import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; import org.apache.kafka.common.metrics.MetricConfig; @@ -223,6 +224,7 @@ * @see TestInputTopic * @see TestOutputTopic */ +@InterfaceAudience.Public public class TopologyTestDriver implements Closeable { private static final Logger log = LoggerFactory.getLogger(TopologyTestDriver.class); diff --git a/streams/test-utils/src/main/java/org/apache/kafka/streams/processor/api/MockProcessorContext.java b/streams/test-utils/src/main/java/org/apache/kafka/streams/processor/api/MockProcessorContext.java index 6c6a55ca4c45c..f05ed7c45a042 100644 --- a/streams/test-utils/src/main/java/org/apache/kafka/streams/processor/api/MockProcessorContext.java +++ b/streams/test-utils/src/main/java/org/apache/kafka/streams/processor/api/MockProcessorContext.java @@ -16,6 +16,8 @@ */ package org.apache.kafka.streams.processor.api; +import org.apache.kafka.common.annotation.InterfaceAudience; +import org.apache.kafka.common.annotation.SuppressKafkaInternalApiUsage; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.metrics.MetricConfig; import org.apache.kafka.common.metrics.Metrics; @@ -75,6 +77,8 @@ * If you require more automated tests, we recommend wrapping your {@link Processor} in a minimal source-processor-sink * {@link Topology} and using the {@link TopologyTestDriver}. */ +@InterfaceAudience.Public +@SuppressKafkaInternalApiUsage("KIP-1265: implements internal RecordCollector.Supplier for the existing test-utility contract — pending KIP review to promote the type or refactor") public class MockProcessorContext implements ProcessorContext, RecordCollector.Supplier { // Immutable fields ================================================ private final StreamsMetricsImpl metrics; @@ -484,6 +488,7 @@ public void resetCommit() { } @Override + @SuppressKafkaInternalApiUsage("KIP-1265: override leaks internal RecordCollector — pending KIP review to promote or refactor") public RecordCollector recordCollector() { // This interface is assumed by state stores that add change-logging. // Rather than risk a mysterious ClassCastException during unit tests, throw an explanatory exception. diff --git a/streams/test-utils/src/main/java/org/apache/kafka/streams/test/TestRecord.java b/streams/test-utils/src/main/java/org/apache/kafka/streams/test/TestRecord.java index 1a6570a71e0a7..80ba86068dbb4 100644 --- a/streams/test-utils/src/main/java/org/apache/kafka/streams/test/TestRecord.java +++ b/streams/test-utils/src/main/java/org/apache/kafka/streams/test/TestRecord.java @@ -18,6 +18,7 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.annotation.InterfaceAudience; import org.apache.kafka.common.header.Headers; import org.apache.kafka.common.header.internals.RecordHeaders; import org.apache.kafka.streams.TestInputTopic; @@ -32,6 +33,7 @@ * If [a] record does not contain a timestamp, * {@link TestInputTopic} will auto advance it's time when the record is piped. */ +@InterfaceAudience.Public public class TestRecord { private static final int NO_PARTITION = -1; private final Headers headers; diff --git a/tools/src/main/java/org/apache/kafka/tools/ConfigCommand.java b/tools/src/main/java/org/apache/kafka/tools/ConfigCommand.java index 2a93bcdc55789..a9e1dc5e4a0a2 100644 --- a/tools/src/main/java/org/apache/kafka/tools/ConfigCommand.java +++ b/tools/src/main/java/org/apache/kafka/tools/ConfigCommand.java @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.tools; +package org.apache.kafka.tools; import org.apache.kafka.clients.admin.Admin; import org.apache.kafka.clients.admin.AlterClientQuotasOptions; diff --git a/tools/src/test/java/org/apache/kafka/tools/ClientMetricsCommandTest.java b/tools/src/test/java/org/apache/kafka/tools/ClientMetricsCommandTest.java index c9b54d71a1c2d..ec268fade9895 100644 --- a/tools/src/test/java/org/apache/kafka/tools/ClientMetricsCommandTest.java +++ b/tools/src/test/java/org/apache/kafka/tools/ClientMetricsCommandTest.java @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.kafka.tools; +package org.apache.kafka.tools; import org.apache.kafka.clients.admin.Admin; import org.apache.kafka.clients.admin.AdminClientTestUtils; diff --git a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/Decoder.java b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/Decoder.java index f3bb9eb47fb58..8b157a9b3ccb8 100644 --- a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/Decoder.java +++ b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/Decoder.java @@ -14,12 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.tools.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * A decoder is a method of turning byte arrays into objects. */ @FunctionalInterface +@InterfaceAudience.Public public interface Decoder { T fromBytes(byte[] bytes); } diff --git a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/DefaultDecoder.java b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/DefaultDecoder.java index e72aaac2e6c95..6c7373ff88ab6 100644 --- a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/DefaultDecoder.java +++ b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/DefaultDecoder.java @@ -14,11 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.tools.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + /** * The default implementation does nothing, just returns the same byte array it takes in. */ +@InterfaceAudience.Public public class DefaultDecoder implements Decoder { @Override public byte[] fromBytes(byte[] bytes) { diff --git a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/IntegerDecoder.java b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/IntegerDecoder.java index 7e20140927298..d4ad51f784325 100644 --- a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/IntegerDecoder.java +++ b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/IntegerDecoder.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.tools.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.nio.ByteBuffer; /** * The integer decoder translates bytes into integers. */ +@InterfaceAudience.Public public class IntegerDecoder implements Decoder { @Override public Integer fromBytes(byte[] bytes) { diff --git a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/LongDecoder.java b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/LongDecoder.java index 8cdb4bbf6bb36..3a70fa13aa700 100644 --- a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/LongDecoder.java +++ b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/LongDecoder.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.tools.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.nio.ByteBuffer; /** * The long decoder translates bytes into longs. */ +@InterfaceAudience.Public public class LongDecoder implements Decoder { @Override public Long fromBytes(byte[] bytes) { diff --git a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/RecordReader.java b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/RecordReader.java index f8340ddcda1f8..e90a0d695fa52 100644 --- a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/RecordReader.java +++ b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/RecordReader.java @@ -14,10 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.tools.api; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.Configurable; +import org.apache.kafka.common.annotation.InterfaceAudience; import java.io.Closeable; import java.io.InputStream; @@ -30,6 +32,7 @@ * * This is used by the `org.apache.kafka.tools.ConsoleProducer`. */ +@InterfaceAudience.Public public interface RecordReader extends Closeable, Configurable { default void configure(Map configs) {} diff --git a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/StringDecoder.java b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/StringDecoder.java index eb6b8ddff8a63..7064ca44a2d15 100644 --- a/tools/tools-api/src/main/java/org/apache/kafka/tools/api/StringDecoder.java +++ b/tools/tools-api/src/main/java/org/apache/kafka/tools/api/StringDecoder.java @@ -14,13 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.kafka.tools.api; +import org.apache.kafka.common.annotation.InterfaceAudience; + import java.nio.charset.StandardCharsets; /** * The string decoder translates bytes into strings. It uses UTF8 by default. */ +@InterfaceAudience.Public public class StringDecoder implements Decoder { @Override public String fromBytes(byte[] bytes) {