This is an automated email from the ASF dual-hosted git repository.
merlimat pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new cf0c24e6723 [improve][build] Fix publishing of public libraries with
correct POM and Gradle module metadata (#26020)
cf0c24e6723 is described below
commit cf0c24e67238700ca9de49d4a765a8b016b87af4
Author: Lari Hotari <[email protected]>
AuthorDate: Sun Jun 14 02:59:57 2026 +0300
[improve][build] Fix publishing of public libraries with correct POM and
Gradle module metadata (#26020)
---
.github/workflows/pulsar-ci.yaml | 3 +
bouncy-castle/bc/LICENSE | 209 --------------------
bouncy-castle/bc/build.gradle.kts | 31 ---
.../apache/pulsar/bcloader/BouncyCastleLoader.java | 46 -----
.../org/apache/pulsar/bcloader/package-info.java | 23 ---
.../resources/META-INF/services/bouncy-castle.yaml | 22 ---
bouncy-castle/bcfips/LICENSE | 210 ---------------------
bouncy-castle/bcfips/build.gradle.kts | 32 ----
.../pulsar/bcloader/BouncyCastleFipsLoader.java | 46 -----
.../org/apache/pulsar/bcloader/package-info.java | 19 --
.../resources/META-INF/services/bouncy-castle.yaml | 22 ---
.../src/main/kotlin/CheckBinaryLicenseTask.kt | 1 -
.../main/kotlin/pulsar.java-conventions.gradle.kts | 91 ++++++---
.../main/kotlin/pulsar.nar-conventions.gradle.kts | 1 -
...lsar.public-java-library-conventions.gradle.kts | 2 +-
.../kotlin/pulsar.publish-conventions.gradle.kts | 94 ++++++---
buildtools/build.gradle.kts | 2 +-
distribution/server/build.gradle.kts | 18 +-
distribution/shell/build.gradle.kts | 21 +--
managed-ledger/build.gradle.kts | 10 +-
microbench/build.gradle.kts | 8 +-
pulsar-bom/build.gradle.kts | 4 -
pulsar-broker-auth-athenz/build.gradle.kts | 2 +-
pulsar-broker-auth-oidc/build.gradle.kts | 4 +-
pulsar-broker-auth-sasl/build.gradle.kts | 4 +-
pulsar-broker-common/build.gradle.kts | 23 ++-
pulsar-broker/build.gradle.kts | 50 ++---
pulsar-cli-utils/build.gradle.kts | 2 +-
pulsar-client-admin-api/build.gradle.kts | 2 +-
pulsar-client-admin-shaded/build.gradle.kts | 15 ++
pulsar-client-admin/build.gradle.kts | 14 +-
pulsar-client-all/build.gradle.kts | 17 +-
pulsar-client-api-v5/build.gradle.kts | 2 +-
pulsar-client-auth-athenz/build.gradle.kts | 2 +-
pulsar-client-messagecrypto-bc/build.gradle.kts | 10 +-
.../pulsar/client/impl/crypto/MessageCryptoBc.java | 80 +++++---
pulsar-client-shaded/build.gradle.kts | 19 +-
pulsar-client-tools/build.gradle.kts | 12 +-
pulsar-client-v5/build.gradle.kts | 4 +-
pulsar-client/build.gradle.kts | 18 +-
pulsar-common/build.gradle.kts | 29 +--
.../org/apache/pulsar/common/util/BCLoader.java | 28 ---
pulsar-docs-tools/build.gradle.kts | 4 +-
pulsar-functions/instance/build.gradle.kts | 22 +--
.../functions/instance/ProducerBuilderFactory.java | 7 -
.../pulsar/functions/source/PulsarSource.java | 7 -
pulsar-functions/localrun/build.gradle.kts | 2 +-
pulsar-functions/runtime/build.gradle.kts | 10 +-
pulsar-functions/secrets/build.gradle.kts | 2 +-
pulsar-functions/utils/build.gradle.kts | 4 +-
pulsar-functions/worker/build.gradle.kts | 14 +-
pulsar-io/batch-data-generator/build.gradle.kts | 4 +-
pulsar-io/data-generator/build.gradle.kts | 4 +-
pulsar-metadata/build.gradle.kts | 4 +-
pulsar-opentelemetry/build.gradle.kts | 2 +-
pulsar-proxy/build.gradle.kts | 24 +--
pulsar-testclient/build.gradle.kts | 18 +-
pulsar-transaction/coordinator/build.gradle.kts | 8 +-
pulsar-websocket/build.gradle.kts | 8 +-
settings.gradle.kts | 9 +-
.../java-test-functions/build.gradle.kts | 4 +-
.../pulsar-client-all-shade-test/build.gradle.kts | 2 +-
.../pulsar-client-test-bcfips}/build.gradle.kts | 12 +-
.../pulsar/client/TlsProducerConsumerBase.java | 0
.../pulsar/client/TlsProducerConsumerTest.java | 0
tiered-storage/file-system/build.gradle.kts | 2 +-
66 files changed, 436 insertions(+), 989 deletions(-)
diff --git a/.github/workflows/pulsar-ci.yaml b/.github/workflows/pulsar-ci.yaml
index 17d88719689..3a7a94f0559 100644
--- a/.github/workflows/pulsar-ci.yaml
+++ b/.github/workflows/pulsar-ci.yaml
@@ -178,6 +178,9 @@ jobs:
- name: Check binary licenses
run: ./gradlew checkBinaryLicense --no-configuration-cache
+ - name: Check that project's public libraries can be published to a
Maven repository
+ run: ./gradlew publishAllPublicationsToLocalDeployRepository
+
- name: Upload Gradle reports
uses: actions/upload-artifact@v4
if: ${{ !success() }}
diff --git a/bouncy-castle/bc/LICENSE b/bouncy-castle/bc/LICENSE
deleted file mode 100644
index 9cbf445cda2..00000000000
--- a/bouncy-castle/bc/LICENSE
+++ /dev/null
@@ -1,209 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed 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.
-
-----------------------------------------------------------------------------------------------------
-
-This projects includes binary packages with the following licenses:
-Bouncy Castle License
- * Bouncy Castle -- licenses/LICENSE-bouncycastle.txt
- - org.bouncycastle-bcpkix-jdk18on-1.81.jar
- - org.bouncycastle-bcprov-jdk18on-1.78.1.jar
diff --git a/bouncy-castle/bc/build.gradle.kts
b/bouncy-castle/bc/build.gradle.kts
deleted file mode 100644
index 9e2527691c2..00000000000
--- a/bouncy-castle/bc/build.gradle.kts
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-plugins {
- id("pulsar.public-java-library-conventions")
-}
-
-dependencies {
- implementation(libs.slog)
- compileOnly(project(":pulsar-common")) {
- exclude(group = "io.prometheus", module = "simpleclient_caffeine")
- }
- implementation(libs.bcpkix.jdk18on)
- implementation(libs.bcprov.jdk18on)
-}
diff --git
a/bouncy-castle/bc/src/main/java/org/apache/pulsar/bcloader/BouncyCastleLoader.java
b/bouncy-castle/bc/src/main/java/org/apache/pulsar/bcloader/BouncyCastleLoader.java
deleted file mode 100644
index f1f452b7d7e..00000000000
---
a/bouncy-castle/bc/src/main/java/org/apache/pulsar/bcloader/BouncyCastleLoader.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.pulsar.bcloader;
-
-import static org.apache.pulsar.common.util.SecurityUtility.BC;
-import java.security.Provider;
-import java.security.Security;
-import lombok.CustomLog;
-import org.apache.pulsar.common.util.BCLoader;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
-/**
- * This is a Bouncy Castle provider Loader.
- */
-@CustomLog
-public class BouncyCastleLoader implements BCLoader {
- public static Provider provider;
- static {
- if (Security.getProvider(BC) == null) {
- Security.addProvider(new BouncyCastleProvider());
- }
- provider = Security.getProvider(BC);
- log.info().attr("provider", provider).log("BouncyCastle Provider BC
loaded");
- }
-
- @Override
- public Provider getProvider() {
- return Security.getProvider(BC);
- }
-}
diff --git
a/bouncy-castle/bc/src/main/java/org/apache/pulsar/bcloader/package-info.java
b/bouncy-castle/bc/src/main/java/org/apache/pulsar/bcloader/package-info.java
deleted file mode 100644
index da465105f14..00000000000
---
a/bouncy-castle/bc/src/main/java/org/apache/pulsar/bcloader/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/**
- * Package for Bouncy Castle provider Loader.
- */
-package org.apache.pulsar.bcloader;
diff --git
a/bouncy-castle/bc/src/main/resources/META-INF/services/bouncy-castle.yaml
b/bouncy-castle/bc/src/main/resources/META-INF/services/bouncy-castle.yaml
deleted file mode 100644
index 5f8217c1ade..00000000000
--- a/bouncy-castle/bc/src/main/resources/META-INF/services/bouncy-castle.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-name: bouncy-castle
-description: loader for Bouncy Castle provider
-bcLoaderClass: org.apache.pulsar.bcloader.BouncyCastleLoader
diff --git a/bouncy-castle/bcfips/LICENSE b/bouncy-castle/bcfips/LICENSE
deleted file mode 100644
index 5eda282e5aa..00000000000
--- a/bouncy-castle/bcfips/LICENSE
+++ /dev/null
@@ -1,210 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed 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.
-
-----------------------------------------------------------------------------------------------------
-
-This projects includes binary packages with the following licenses:
-Bouncy Castle License
- * Bouncy Castle -- licenses/LICENSE-bouncycastle.txt
- - org.bouncycastle-bcpkix-fips-2.0.10.jar
- - org.bouncycastle-bc-fips-2.0.1.jar
- - org.bouncycastle-bctutil-fips-2.0.5.jar
diff --git a/bouncy-castle/bcfips/build.gradle.kts
b/bouncy-castle/bcfips/build.gradle.kts
deleted file mode 100644
index d722c3f4561..00000000000
--- a/bouncy-castle/bcfips/build.gradle.kts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-plugins {
- id("pulsar.public-java-library-conventions")
-}
-
-dependencies {
- implementation(libs.slog)
- compileOnly(project(":pulsar-common")) {
- exclude(group = "io.prometheus", module = "simpleclient_caffeine")
- }
- implementation(libs.bcutil.fips)
- implementation(libs.bc.fips)
- implementation(libs.bcpkix.fips)
-}
diff --git
a/bouncy-castle/bcfips/src/main/java/org/apache/pulsar/bcloader/BouncyCastleFipsLoader.java
b/bouncy-castle/bcfips/src/main/java/org/apache/pulsar/bcloader/BouncyCastleFipsLoader.java
deleted file mode 100644
index 842c9537bd2..00000000000
---
a/bouncy-castle/bcfips/src/main/java/org/apache/pulsar/bcloader/BouncyCastleFipsLoader.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.pulsar.bcloader;
-
-import static org.apache.pulsar.common.util.SecurityUtility.BC_FIPS;
-import java.security.Provider;
-import java.security.Security;
-import lombok.CustomLog;
-import org.apache.pulsar.common.util.BCLoader;
-import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
-
-/**
- * This is a Bouncy Castle provider Loader.
- */
-@CustomLog
-public class BouncyCastleFipsLoader implements BCLoader {
- public static Provider provider;
- static {
- if (Security.getProvider(BC_FIPS) == null) {
- Security.addProvider(new BouncyCastleFipsProvider());
- }
- provider = Security.getProvider(BC_FIPS);
- log.info().attr("provider",
Security.getProvider(BC_FIPS)).log("BouncyCastle Provider BC_FIPS loaded");
- }
-
- @Override
- public Provider getProvider() {
- return Security.getProvider(BC_FIPS);
- }
-}
diff --git
a/bouncy-castle/bcfips/src/main/java/org/apache/pulsar/bcloader/package-info.java
b/bouncy-castle/bcfips/src/main/java/org/apache/pulsar/bcloader/package-info.java
deleted file mode 100644
index d610ff5642d..00000000000
---
a/bouncy-castle/bcfips/src/main/java/org/apache/pulsar/bcloader/package-info.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.pulsar.bcloader;
diff --git
a/bouncy-castle/bcfips/src/main/resources/META-INF/services/bouncy-castle.yaml
b/bouncy-castle/bcfips/src/main/resources/META-INF/services/bouncy-castle.yaml
deleted file mode 100644
index 26ca9cde659..00000000000
---
a/bouncy-castle/bcfips/src/main/resources/META-INF/services/bouncy-castle.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-name: bouncy-castle-fips
-description: loader for Bouncy Castle FIPS provider
-bcLoaderClass: org.apache.pulsar.bcloader.BouncyCastleFipsLoader
diff --git a/build-logic/conventions/src/main/kotlin/CheckBinaryLicenseTask.kt
b/build-logic/conventions/src/main/kotlin/CheckBinaryLicenseTask.kt
index 4be5bd78759..e52ec7bbe65 100644
--- a/build-logic/conventions/src/main/kotlin/CheckBinaryLicenseTask.kt
+++ b/build-logic/conventions/src/main/kotlin/CheckBinaryLicenseTask.kt
@@ -67,7 +67,6 @@ abstract class CheckBinaryLicenseTask : DefaultTask() {
"pulsar-common",
"pulsar-package",
"pulsar-websocket",
- "bouncy-castle-bc",
)
val bundledJars = sortedSetOf<String>()
diff --git
a/build-logic/conventions/src/main/kotlin/pulsar.java-conventions.gradle.kts
b/build-logic/conventions/src/main/kotlin/pulsar.java-conventions.gradle.kts
index a63dbb3ca14..51f1e2a484a 100644
--- a/build-logic/conventions/src/main/kotlin/pulsar.java-conventions.gradle.kts
+++ b/build-logic/conventions/src/main/kotlin/pulsar.java-conventions.gradle.kts
@@ -24,6 +24,45 @@ plugins {
val catalog = the<VersionCatalogsExtension>().named("libs")
+// Versions for dependencies injected by the component-metadata rules below,
captured as plain
+// strings so the rule closures stay configuration-cache compatible (and so
the injected deps carry
+// explicit versions rather than relying on the alignment platform being on
every classpath).
+val jakartaActivationApiVersion =
catalog.findVersion("jakarta-activation").get().requiredVersion
+val angusActivationVersion =
catalog.findVersion("angus-activation").get().requiredVersion
+
+// Internal version-alignment platform bucket.
+// The enforced platform (:pulsar-dependencies) must align the build's OWN
resolution but must NOT
+// leak into the published apiElements/runtimeElements variants: an
enforcedPlatform recorded in
+// published Gradle Module Metadata forces Pulsar's internal versions onto
downstream Gradle
+// consumers and strips their ability to override (Gradle's platforms docs
warn against using
+// enforcedPlatform on a component intended for consumption). Declaring it on
a non-consumable,
+// non-resolvable bucket that only the resolvable build classpaths extend
keeps full build-time
+// alignment (and feeds versionMapping for POM versions) while leaving it out
of publication.
+// Consumers get the separate, non-enforced pulsar-bom for version
recommendations instead.
+val internalPlatform = configurations.create("internalPlatform") {
+ isCanBeConsumed = false
+ isCanBeResolved = false
+ description = "Enforced version-alignment platform for build resolution
only; never published."
+}
+// Wire the alignment platform onto the build's resolvable classpaths by name.
These configurations
+// are created by the Java plugin before this convention's body runs, so the
name match reliably
+// fires for them. (Matching on the mutable isCanBeResolved/isCanBeConsumed
flags is NOT reliable for
+// configurations created later via `configurations.creating {}` — their flags
are set inside the
+// creation block, after a flag-based configureEach predicate has already
evaluated the legacy
+// defaults.) The consumable variants apiElements/runtimeElements are
intentionally not listed, so
+// the enforced platform stays out of published Gradle Module Metadata. Custom
resolvable
+// configurations that collect artifacts and need the same alignment (notably
the distributions'
+// `distLib`, which feeds the binary distribution checked by
checkBinaryLicense) extend
+// `internalPlatform` explicitly where they are declared.
+val platformAlignedClasspaths = setOf(
+ "compileClasspath", "runtimeClasspath",
+ "testCompileClasspath", "testRuntimeClasspath",
+ "annotationProcessor", "testAnnotationProcessor",
+)
+configurations.matching { it.name in platformAlignedClasspaths }.configureEach
{
+ extendsFrom(internalPlatform)
+}
+
tasks.withType<JavaCompile>().configureEach {
options.encoding = "UTF-8"
options.release.set(17)
@@ -31,11 +70,6 @@ tasks.withType<JavaCompile>().configureEach {
}
configurations.all {
- // Exclude the old SLF4J 1.x bridge pulled in by bookkeeper-server.
- // Pulsar uses SLF4J 2.x with log4j-slf4j2-impl; having both causes
- // NoSuchMethodError in Log4jLoggerFactory at test startup.
- exclude(group = "org.apache.logging.log4j", module = "log4j-slf4j-impl")
-
// Force Jackson version to match the version catalog. Transitive
dependencies
// (e.g. from jackson-bom) can pull in newer versions that break API
compatibility
// (EnumResolver.constructUsingToString signature changed in 2.19+).
@@ -50,28 +84,24 @@ configurations.all {
}
}
-// Exclude bc-fips from modules that don't need it. bc-fips's
CryptoServicesRegistrar
-// conflicts with bcprov-jdk18on's version — having both causes
NoSuchMethodError.
-// Only the FIPS-specific modules and modules with explicit FIPS tests should
have it.
-val modulesUsingBcFips = setOf(
- "bcfips", "bcfips-include-test",
- "pulsar-common", "pulsar-broker-common",
-)
-if (project.name !in modulesUsingBcFips) {
- configurations.all {
- exclude(group = "org.bouncycastle", module = "bc-fips")
- }
-}
-
dependencies {
- // Exclude all BouncyCastle from bookkeeper-server (matches Maven parent
POM exclusion).
- // BookKeeper's bc-fips transitive dependency contains a
CryptoServicesRegistrar that
- // conflicts with the non-FIPS version in bcprov-jdk18on. Pulsar manages
its own BC deps.
+ // Strip conflicting transitive dependencies from bookkeeper-server at the
source. Handling them
+ // here (rather than with a build-wide `configurations.all { exclude(...)
}`) keeps them off the
+ // classpath without leaking a per-dependency <exclusion> onto every
dependency in every
+ // published POM.
+ // - All BouncyCastle: BookKeeper's transitive bc-fips bundles a
CryptoServicesRegistrar that
+ // conflicts with the non-FIPS bcprov-jdk18on. Pulsar manages its own
BC deps; the FIPS
+ // modules (bcfips, pulsar-common/pulsar-broker-common tests) declare
bc-fips directly.
+ // - log4j-slf4j-impl: the SLF4J 1.x bridge conflicts with Pulsar's
SLF4J 2.x setup
+ // (log4j-slf4j2-impl), causing NoSuchMethodError in
Log4jLoggerFactory at startup.
components {
withModule("org.apache.bookkeeper:bookkeeper-server") {
allVariants {
withDependencies {
- removeAll { it.group == "org.bouncycastle" }
+ removeAll {
+ it.group == "org.bouncycastle" ||
+ (it.group == "org.apache.logging.log4j" && it.name
== "log4j-slf4j-impl")
+ }
}
}
}
@@ -80,14 +110,15 @@ dependencies {
// jakarta.activation:jakarta.activation-api 2.1.x. Replace it
everywhere with the API artifact
// plus the Eclipse Angus implementation (the EE10 successor).
async-http-client still depends
// on it
(https://github.com/AsyncHttpClient/async-http-client/issues/2190) and this
rule also
- // guards against any future dependency pulling it in. Versions are
pinned by the
- // pulsar-dependencies platform.
+ // guards against any future dependency pulling it in. The
replacements carry explicit catalog
+ // versions so they resolve on any classpath without relying on the
alignment platform being
+ // present (e.g. the protobuf plugin's *ProtoPath configurations do
not extend it).
all {
allVariants {
withDependencies {
if (removeAll { it.group == "com.sun.activation" &&
it.name == "jakarta.activation" }) {
- add("jakarta.activation:jakarta.activation-api")
- add("org.eclipse.angus:angus-activation")
+
add("jakarta.activation:jakarta.activation-api:$jakartaActivationApiVersion")
+
add("org.eclipse.angus:angus-activation:$angusActivationVersion")
}
}
}
@@ -122,9 +153,11 @@ dependencies {
}
}
- // Enforced platform pins all dependency versions from the version catalog.
- // This is the Gradle equivalent of Maven's dependencyManagement section.
- "implementation"(enforcedPlatform(project(":pulsar-dependencies")))
+ // Enforced platform pins all dependency versions from the version catalog
(the Gradle
+ // equivalent of Maven's dependencyManagement). Declared on the internal,
non-published
+ // `internalPlatform` bucket (see above) so it aligns the build's
resolvable classpaths
+ // without leaking the enforced platform into published
apiElements/runtimeElements metadata.
+ "internalPlatform"(enforcedPlatform(project(":pulsar-dependencies")))
// Resolve lz4-java capability conflict: at.yawk.lz4:lz4-java (used by
Pulsar) and
// org.lz4:lz4-java (used by kafka-clients) both provide the
org.lz4:lz4-java capability.
diff --git
a/build-logic/conventions/src/main/kotlin/pulsar.nar-conventions.gradle.kts
b/build-logic/conventions/src/main/kotlin/pulsar.nar-conventions.gradle.kts
index c1014492895..c0c9c1b7eb4 100644
--- a/build-logic/conventions/src/main/kotlin/pulsar.nar-conventions.gradle.kts
+++ b/build-logic/conventions/src/main/kotlin/pulsar.nar-conventions.gradle.kts
@@ -38,7 +38,6 @@ val pulsarPlatformModules = setOf(
"pulsar-client",
"pulsar-common",
"pulsar-config-validation",
- "bouncy-castle-bc",
"pulsar-functions-api",
"pulsar-functions-instance",
"pulsar-functions-proto",
diff --git
a/build-logic/conventions/src/main/kotlin/pulsar.public-java-library-conventions.gradle.kts
b/build-logic/conventions/src/main/kotlin/pulsar.public-java-library-conventions.gradle.kts
index 45010ea6378..3bb57c41f91 100644
---
a/build-logic/conventions/src/main/kotlin/pulsar.public-java-library-conventions.gradle.kts
+++
b/build-logic/conventions/src/main/kotlin/pulsar.public-java-library-conventions.gradle.kts
@@ -31,7 +31,7 @@ plugins {
// Test/compileOnly scoped dependencies are excluded since they don't appear
in the POM.
// NAR modules are not validated here — they bundle all dependencies and have
empty POMs.
run {
- val publishedScopes = listOf("api", "implementation", "runtimeOnly")
+ val publishedScopes = listOf("api", "implementation", "runtimeOnly",
"shadow")
val configsToCheck = publishedScopes.mapNotNull { name ->
configurations.findByName(name)?.let { name to it }
}
diff --git
a/build-logic/conventions/src/main/kotlin/pulsar.publish-conventions.gradle.kts
b/build-logic/conventions/src/main/kotlin/pulsar.publish-conventions.gradle.kts
index 5da26aaac64..67436adb31a 100644
---
a/build-logic/conventions/src/main/kotlin/pulsar.publish-conventions.gradle.kts
+++
b/build-logic/conventions/src/main/kotlin/pulsar.publish-conventions.gradle.kts
@@ -22,6 +22,9 @@
// the ASF Nexus release/snapshot repositories, and a local deploy repository
// for testing.
+import org.gradle.api.services.BuildService
+import org.gradle.api.services.BuildServiceParameters
+
plugins {
`maven-publish`
signing
@@ -49,26 +52,44 @@ pluginManager.withPlugin("java-library") {
from(tasks.named(JavaPlugin.JAVADOC_TASK_NAME))
}
- // Standard java-library modules: publish from components["java"]
- publishing {
- publications {
- create<MavenPublication>("maven") {
- from(components["java"])
- artifact(sourcesJar)
- artifact(javadocJar)
+ // The Maven publication. Its software component is wired in a deferred
block because it depends
+ // on whether this is a shaded module:
+ // - Shaded modules (com.gradleup.shadow applied) publish the shadow
plugin's dependency-reduced
+ // `shadow` component: the artifact is the shadow jar and the
published dependencies are
+ // EXACTLY the `shadow` configuration (the non-bundled runtime deps),
not the bundled
+ // component modules + their unshaded transitive tree. This is the
Gradle equivalent of
+ // Maven's createDependencyReducedPom.
+ // - All other java-library modules publish the standard `java`
component with resolved
+ // version mapping (unchanged behavior).
+ val mavenPublication =
publishing.publications.create<MavenPublication>("maven") {
+ artifact(sourcesJar)
+ artifact(javadocJar)
+ }
- versionMapping {
- usage(Usage.JAVA_RUNTIME) {
- fromResolutionResult()
- }
- usage(Usage.JAVA_API) {
- fromResolutionOf("runtimeClasspath")
- }
+ // Shaded modules: the shadow plugin registers components["shadow"] in its
own afterEvaluate, so
+ // wire it from an afterEvaluate registered AFTER that. Registering inside
withPlugin (which fires
+ // once the shadow plugin is applied, after this convention) guarantees
the ordering.
+ pluginManager.withPlugin("com.gradleup.shadow") {
+ afterEvaluate {
+ mavenPublication.from(components["shadow"])
+ }
+ }
+
+ // Non-shaded modules: standard java component + resolved version mapping.
By afterEvaluate all
+ // plugins are applied, so the shadow-plugin check is reliable.
+ afterEvaluate {
+ if (!pluginManager.hasPlugin("com.gradleup.shadow")) {
+ mavenPublication.from(components["java"])
+ mavenPublication.versionMapping {
+ usage(Usage.JAVA_RUNTIME) {
+ fromResolutionResult()
+ }
+ usage(Usage.JAVA_API) {
+ fromResolutionOf("runtimeClasspath")
}
}
}
}
-
}
// --- java-platform projects (BOM, dependencies): POM-only, no JAR ---
@@ -167,10 +188,11 @@ run {
// Publish with one of:
// ./gradlew publishAllPublicationsToApacheSnapshotsRepository (for
-SNAPSHOT versions)
// ./gradlew publishAllPublicationsToApacheReleasesRepository (for
release versions)
-// Releases must be published with --no-parallel: when uploading to the Apache
staging
-// repository, Nexus creates an implicit staging repository, and concurrent
per-module uploads
-// can end up split across multiple implicitly-created staging repositories
instead of being
-// collected into a single one.
+// Uploads to the Apache staging repository are serialized by the
mavenPublishLock shared build
+// service (defined below) so they all land in a single Nexus staging
repository: Nexus creates an
+// implicit staging repository on first upload, and concurrent per-module
uploads could otherwise be
+// split across multiple implicitly-created staging repositories. Because the
lock handles this,
+// --no-parallel is not required.
// Credentials are resolved by Gradle at execution time from the
apacheReleasesUsername /
// apacheReleasesPassword and apacheSnapshotsUsername /
apacheSnapshotsPassword Gradle properties
// (the credentials(PasswordCredentials::class) form, which keeps the publish
tasks
@@ -180,7 +202,7 @@ run {
// builds; start the command line with a space to keep the password out of
shell history:
// ORG_GRADLE_PROJECT_apacheReleasesUsername=$APACHE_USER \
// ORG_GRADLE_PROJECT_apacheReleasesPassword="<your ASF password>" \
-// ./gradlew publishAllPublicationsToApacheReleasesRepository --no-parallel
...
+// ./gradlew publishAllPublicationsToApacheReleasesRepository ...
// The URLs can be overridden with the apacheReleasesRepoUrl /
apacheSnapshotsRepoUrl Gradle
// properties (e.g. a file:// URL for testing the publication layout).
run {
@@ -244,6 +266,25 @@ run {
}
}
+// --- Serialize uploads to Maven repositories ---
+// Nexus creates an implicit staging repository on the first upload of a
release, and concurrent
+// per-module uploads can end up split across multiple implicitly-created
staging repositories
+// instead of being collected into a single one. A shared build service with
maxParallelUsages = 1
+// ensures at most one PublishToMavenRepository upload runs at a time across
the whole build, so the
+// rest of the build (compilation, jars, signing) can still run in parallel
and --no-parallel is not
+// required.
+abstract class MavenPublishLock : BuildService<BuildServiceParameters.None>
+
+val mavenPublishLock = gradle.sharedServices.registerIfAbsent(
+ "mavenPublishLock", MavenPublishLock::class
+) {
+ maxParallelUsages = 1
+}
+
+tasks.withType<PublishToMavenRepository>().configureEach {
+ usesService(mavenPublishLock)
+}
+
// --- GPG signing ---
signing {
isRequired = !version.toString().endsWith("-SNAPSHOT")
@@ -265,11 +306,10 @@ tasks.withType<Sign>().configureEach {
(providers.gradleProperty("useGpgCmd").orNull?.toBoolean() ?: false)
}
-// Suppress enforced-platform validation: all java-library modules use
-// enforcedPlatform(":pulsar-dependencies") for internal version alignment,
-// but this should not leak to consumers. The dependencyManagement section
-// is stripped from published POMs via withXml above.
-tasks.withType<GenerateModuleMetadata>().configureEach {
- suppressedValidationErrors.add("enforced-platform")
-}
+// NOTE: the enforced-platform validation error is intentionally NOT
suppressed. The internal
+// version-alignment platform (:pulsar-dependencies) is declared on the
non-published
+// `internalPlatform` bucket in pulsar.java-conventions (only the resolvable
build classpaths
+// extend it), so it never reaches the published apiElements/runtimeElements
variants. Letting the
+// validation run unsuppressed guards against the enforced platform regressing
back into published
+// Gradle Module Metadata.
diff --git a/buildtools/build.gradle.kts b/buildtools/build.gradle.kts
index b33adb06d02..8496a0bef97 100644
--- a/buildtools/build.gradle.kts
+++ b/buildtools/build.gradle.kts
@@ -27,7 +27,7 @@ dependencies {
implementation(libs.ant)
implementation(libs.guava)
implementation(libs.guice)
- implementation(libs.testng) {
+ api(libs.testng) {
exclude(group = "org.slf4j")
}
implementation(libs.log4j.api)
diff --git a/distribution/server/build.gradle.kts
b/distribution/server/build.gradle.kts
index ad04b1413b1..7f489628adf 100644
--- a/distribution/server/build.gradle.kts
+++ b/distribution/server/build.gradle.kts
@@ -37,8 +37,11 @@ val distLib by configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
isTransitive = true
- // Inherit version constraints from the root project's version catalog
- extendsFrom(configurations["implementation"])
+ // Inherit the enforced version-alignment platform so bundled dependency
versions match the
+ // version catalog (the platform lives on the non-published
`internalPlatform` bucket from
+ // pulsar.java-conventions; `implementation` no longer carries it). Keeps
the distribution's
+ // resolved versions aligned with what checkBinaryLicense expects.
+ extendsFrom(configurations["implementation"],
configurations["internalPlatform"])
// Global exclusions
exclude(group = "org.projectlombok", module = "lombok")
// Exclude test frameworks that leak through transitive deps
@@ -142,8 +145,9 @@ dependencies {
distLib(libs.vertx.core)
distLib(libs.vertx.web)
- // Bouncy Castle
- distLib(project(":bouncy-castle:bouncy-castle-bc"))
+ // Bouncy Castle (non-FIPS JCA provider for client-side message crypto +
TLS)
+ distLib(libs.bcprov.jdk18on)
+ distLib(libs.bcpkix.jdk18on)
// BookKeeper native JARs (these modules publish .nar artifacts by default;
// we exclude .nar files below and add the .jar variants explicitly)
@@ -263,11 +267,7 @@ val serverDistTar by tasks.registering(Tar::class) {
"${id.group}-${id.module}-${id.version}${classifier}.${ext}"
}
is
org.gradle.api.artifacts.component.ProjectComponentIdentifier -> {
- var mappedName = file.nameWithoutExtension
- // For bouncy-castle-bc, add -pkg classifier
- if (mappedName.startsWith("bouncy-castle-bc-")) {
- mappedName = mappedName + "-pkg"
- }
+ val mappedName = file.nameWithoutExtension
"org.apache.pulsar-${mappedName}.${ext}"
}
else -> file.name
diff --git a/distribution/shell/build.gradle.kts
b/distribution/shell/build.gradle.kts
index 6d21bae8d64..9aa6b3d18e2 100644
--- a/distribution/shell/build.gradle.kts
+++ b/distribution/shell/build.gradle.kts
@@ -31,8 +31,10 @@ val distLib by configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
isTransitive = true
- // Inherit version constraints from the enforced platform (via
implementation)
- extendsFrom(configurations["implementation"])
+ // Inherit the enforced version-alignment platform so bundled dependency
versions match the
+ // version catalog (the platform lives on the non-published
`internalPlatform` bucket from
+ // pulsar.java-conventions; `implementation` no longer carries it).
+ extendsFrom(configurations["implementation"],
configurations["internalPlatform"])
exclude(group = "org.projectlombok", module = "lombok")
// Exclude jars not in the shell distribution
exclude(group = "javax.xml.bind", module = "jaxb-api")
@@ -48,8 +50,9 @@ dependencies {
distLib(libs.log4j.layout.template.json)
distLib(libs.log4j.slf4j2.impl)
distLib(libs.simpleclient.log4j2)
- // Bouncy Castle
- distLib(project(":bouncy-castle:bouncy-castle-bc"))
+ // Bouncy Castle (non-FIPS JCA provider for client-side message crypto +
TLS)
+ distLib(libs.bcprov.jdk18on)
+ distLib(libs.bcpkix.jdk18on)
// conscrypt (in Maven shell dist)
distLib(libs.conscrypt.openjdk.uber)
// swagger-annotations (in Maven shell dist)
@@ -75,10 +78,7 @@ val shellDistTar by tasks.registering(Tar::class) {
val file = result.file
val newName = when (id) {
is
org.gradle.api.artifacts.component.ProjectComponentIdentifier -> {
- var mappedName = file.nameWithoutExtension
- if (mappedName.startsWith("bouncy-castle-bc-")) {
- mappedName = mappedName + "-pkg"
- }
+ val mappedName = file.nameWithoutExtension
"${mappedName}.${file.extension}"
}
else -> file.name
@@ -149,10 +149,7 @@ val shellDistZip by tasks.registering(Zip::class) {
val file = result.file
val newName = when (id) {
is
org.gradle.api.artifacts.component.ProjectComponentIdentifier -> {
- var mappedName = file.nameWithoutExtension
- if (mappedName.startsWith("bouncy-castle-bc-")) {
- mappedName = mappedName + "-pkg"
- }
+ val mappedName = file.nameWithoutExtension
"${mappedName}.${file.extension}"
}
else -> file.name
diff --git a/managed-ledger/build.gradle.kts b/managed-ledger/build.gradle.kts
index 9782a5a86e2..070dca73b3c 100644
--- a/managed-ledger/build.gradle.kts
+++ b/managed-ledger/build.gradle.kts
@@ -26,13 +26,13 @@ dependencies {
api(project(":pulsar-common"))
api(project(":pulsar-metadata"))
implementation(project(":pulsar-opentelemetry"))
- implementation(libs.bookkeeper.server)
- implementation(libs.guava)
+ api(libs.bookkeeper.server)
+ api(libs.guava)
implementation(libs.roaringbitmap)
implementation(libs.jctools.core.jdk11)
- implementation(libs.slog)
- implementation(libs.simpleclient)
- implementation(libs.commons.lang3)
+ api(libs.slog)
+ api(libs.simpleclient)
+ api(libs.commons.lang3)
testImplementation(project(":testmocks"))
testImplementation(libs.dropwizardmetrics.core)
diff --git a/microbench/build.gradle.kts b/microbench/build.gradle.kts
index f9c0a649fd9..9a71b6397b6 100644
--- a/microbench/build.gradle.kts
+++ b/microbench/build.gradle.kts
@@ -23,12 +23,12 @@ plugins {
}
dependencies {
- implementation(project(":managed-ledger"))
+ api(project(":managed-ledger"))
implementation(project(":pulsar-common"))
- implementation(project(":pulsar-broker"))
+ api(project(":pulsar-broker"))
implementation(libs.bookkeeper.server)
- implementation(libs.guava)
- implementation("org.openjdk.jmh:jmh-core:1.37")
+ api(libs.guava)
+ api("org.openjdk.jmh:jmh-core:1.37")
annotationProcessor("org.openjdk.jmh:jmh-generator-annprocess:1.37")
}
diff --git a/pulsar-bom/build.gradle.kts b/pulsar-bom/build.gradle.kts
index 060db049449..841c1c258e7 100644
--- a/pulsar-bom/build.gradle.kts
+++ b/pulsar-bom/build.gradle.kts
@@ -92,10 +92,6 @@ dependencies {
api(project(":pulsar-functions:pulsar-functions-secrets"))
api(project(":pulsar-functions:pulsar-functions-utils"))
- // Bouncy Castle
- api(project(":bouncy-castle:bouncy-castle-bc"))
- api(project(":bouncy-castle:bcfips"))
-
// Athenz auth
api(project(":pulsar-client-auth-athenz"))
api(project(":pulsar-broker-auth-athenz"))
diff --git a/pulsar-broker-auth-athenz/build.gradle.kts
b/pulsar-broker-auth-athenz/build.gradle.kts
index 1d40a2c6e40..e48fdbbf406 100644
--- a/pulsar-broker-auth-athenz/build.gradle.kts
+++ b/pulsar-broker-auth-athenz/build.gradle.kts
@@ -25,7 +25,7 @@ dependencies {
implementation(libs.slog)
compileOnly(project(":pulsar-broker"))
compileOnly(libs.opentelemetry.api)
- implementation(project(":pulsar-broker-common"))
+ api(project(":pulsar-broker-common"))
implementation(project(":pulsar-common"))
implementation(libs.athenz.zts.java.client)
implementation(libs.athenz.zpe.java.client)
diff --git a/pulsar-broker-auth-oidc/build.gradle.kts
b/pulsar-broker-auth-oidc/build.gradle.kts
index a76540c1fb7..8abac178dd2 100644
--- a/pulsar-broker-auth-oidc/build.gradle.kts
+++ b/pulsar-broker-auth-oidc/build.gradle.kts
@@ -24,13 +24,13 @@ plugins {
dependencies {
implementation(libs.slog)
- implementation(project(":pulsar-broker-common"))
+ api(project(":pulsar-broker-common"))
implementation(libs.auth0.java.jwt)
implementation(libs.auth0.jwks.rsa)
implementation(libs.caffeine)
implementation(libs.asynchttpclient)
implementation(libs.jackson.databind)
- implementation(libs.jackson.annotations)
+ api(libs.jackson.annotations)
implementation(libs.kubernetes.client.java) {
exclude(group = "software.amazon.awssdk")
// Swagger 1.x annotations on the generated k8s models are inert
metadata; nothing reads them at runtime
diff --git a/pulsar-broker-auth-sasl/build.gradle.kts
b/pulsar-broker-auth-sasl/build.gradle.kts
index e5477b5a232..8814e9c303a 100644
--- a/pulsar-broker-auth-sasl/build.gradle.kts
+++ b/pulsar-broker-auth-sasl/build.gradle.kts
@@ -31,13 +31,13 @@ tasks.withType<Test> {
dependencies {
implementation(libs.slog)
implementation(project(":pulsar-broker"))
- implementation(project(":pulsar-broker-common"))
+ api(project(":pulsar-broker-common"))
implementation(project(":pulsar-common"))
implementation(libs.guava)
implementation(libs.caffeine)
implementation(libs.commons.lang3)
implementation(libs.commons.codec)
- implementation(libs.jakarta.servlet.api)
+ api(libs.jakarta.servlet.api)
implementation(libs.simpleclient.caffeine)
testImplementation(libs.commons.io)
diff --git a/pulsar-broker-common/build.gradle.kts
b/pulsar-broker-common/build.gradle.kts
index db0ebf68c4c..868150de359 100644
--- a/pulsar-broker-common/build.gradle.kts
+++ b/pulsar-broker-common/build.gradle.kts
@@ -26,22 +26,27 @@ dependencies {
api(project(":pulsar-metadata"))
implementation(libs.slog)
implementation(libs.guava)
- implementation(libs.commons.lang3)
- implementation(libs.netty.common)
- implementation(libs.bookkeeper.server)
- implementation(libs.opentelemetry.api)
- implementation(libs.simpleclient)
+ api(libs.commons.lang3)
+ api(libs.netty.common)
+ api(libs.bookkeeper.server)
+ api(libs.opentelemetry.api)
+ api(libs.simpleclient)
implementation(libs.caffeine)
- implementation(libs.jakarta.servlet.api)
- implementation(libs.jakarta.ws.rs.api)
+ api(libs.jakarta.servlet.api)
+ api(libs.jakarta.ws.rs.api)
implementation(libs.jjwt.impl)
implementation(libs.jjwt.jackson)
- implementation(libs.jetty.server)
+ api(libs.jetty.server)
implementation(libs.jetty.compression.server)
implementation(libs.jetty.compression.gzip)
implementation(libs.jetty.ee10.servlet)
- testImplementation(libs.bc.fips)
+ // Non-FIPS BouncyCastle provider for tests that exercise SecurityUtility
(which loads
+ // org.bouncycastle.jce.provider.BouncyCastleProvider in a static
initializer). This matches
+ // the provider used in production. FIPS is covered separately by the
bcfips-include-test
+ // module; bc-fips must not be on a classpath that also has the non-FIPS
provider because both
+ // jars define org.bouncycastle.* and the JVM rejects the mismatched
signers.
+ testImplementation(libs.bcprov.jdk18on)
testImplementation(libs.awaitility)
testImplementation(libs.restassured)
testImplementation(libs.jersey.server)
diff --git a/pulsar-broker/build.gradle.kts b/pulsar-broker/build.gradle.kts
index aeee78be603..6fd3778c0c3 100644
--- a/pulsar-broker/build.gradle.kts
+++ b/pulsar-broker/build.gradle.kts
@@ -26,28 +26,28 @@ plugins {
}
dependencies {
- implementation(libs.slog)
+ api(libs.slog)
api(project(":managed-ledger"))
api(project(":pulsar-broker-common"))
- implementation(project(":pulsar-client-original"))
+ api(project(":pulsar-client-original"))
implementation(project(":pulsar-client-admin-original"))
- implementation(project(":pulsar-websocket"))
+ api(project(":pulsar-websocket"))
implementation(project(":pulsar-cli-utils"))
implementation(project(":pulsar-transaction:pulsar-transaction-common"))
-
implementation(project(":pulsar-transaction:pulsar-transaction-coordinator"))
- implementation(project(":pulsar-opentelemetry"))
+ api(project(":pulsar-transaction:pulsar-transaction-coordinator"))
+ api(project(":pulsar-opentelemetry"))
implementation(project(":pulsar-client-messagecrypto-bc"))
- implementation(project(":pulsar-functions:pulsar-functions-worker"))
+ api(project(":pulsar-functions:pulsar-functions-worker"))
implementation(project(":pulsar-docs-tools")) {
exclude(group = "io.swagger.core.v3")
}
- implementation(project(":pulsar-package-management:pulsar-package-core"))
+ api(project(":pulsar-package-management:pulsar-package-core"))
implementation(project(":pulsar-package-management:pulsar-package-filesystem-storage"))
implementation(libs.commons.codec)
implementation(libs.commons.collections4)
- implementation(libs.commons.lang3)
- implementation(libs.netty.transport)
+ api(libs.commons.lang3)
+ api(libs.netty.transport)
implementation(libs.protobuf.java)
implementation(libs.curator.recipes)
implementation(libs.bookkeeper.stream.storage.server) {
@@ -60,10 +60,10 @@ dependencies {
implementation(libs.snappy.java)
implementation(libs.jetty.server)
implementation(libs.jetty.alpn.conscrypt.server)
- implementation(libs.jetty.ee10.servlet)
+ api(libs.jetty.ee10.servlet)
implementation(libs.jetty.ee10.servlets)
// ee8 + javax.servlet retained for the legacy AdditionalServlet
javax.servlet path (PIP-472)
- implementation(libs.jetty.ee8.servlet)
+ api(libs.jetty.ee8.servlet)
implementation(libs.javax.servlet.api)
implementation(libs.jersey.server)
implementation(libs.jersey.container.servlet.core)
@@ -74,29 +74,29 @@ dependencies {
implementation(libs.jackson.jakarta.rs.json.provider)
implementation(libs.jackson.module.jsonSchema)
implementation(libs.jcl.over.slf4j)
- implementation(libs.guava)
- implementation(libs.jspecify)
- implementation(libs.picocli)
- implementation(libs.simpleclient)
+ api(libs.guava)
+ api(libs.jspecify)
+ api(libs.picocli)
+ api(libs.simpleclient)
implementation(libs.simpleclient.hotspot)
implementation(libs.simpleclient.caffeine)
implementation(libs.hdrHistogram)
implementation(libs.gson)
- implementation(libs.java.semver)
- implementation(libs.avro)
- implementation(libs.hppc)
- implementation(libs.roaringbitmap)
+ api(libs.java.semver)
+ api(libs.avro)
+ api(libs.hppc)
+ api(libs.roaringbitmap)
implementation(libs.oshi.core)
implementation(libs.jakarta.xml.bind.api)
implementation(libs.angus.activation)
- implementation(libs.bookkeeper.server)
+ api(libs.bookkeeper.server)
implementation(libs.bookkeeper.circe.checksum)
- implementation(libs.caffeine)
+ api(libs.caffeine)
implementation(libs.datasketches.java)
- implementation(libs.netty.codec.haproxy)
- implementation(libs.opentelemetry.sdk.extension.autoconfigure)
- implementation(libs.jetty.ee10.websocket.jetty.server)
- implementation(libs.jersey.media.multipart)
+ api(libs.netty.codec.haproxy)
+ api(libs.opentelemetry.sdk.extension.autoconfigure)
+ api(libs.jetty.ee10.websocket.jetty.server)
+ api(libs.jersey.media.multipart)
implementation(libs.bookkeeper.stream.storage.java.client)
implementation(libs.bookkeeper.stream.storage.service.api)
implementation(libs.bookkeeper.stream.storage.service.impl)
diff --git a/pulsar-cli-utils/build.gradle.kts
b/pulsar-cli-utils/build.gradle.kts
index 5e0b01267ef..a12c15610da 100644
--- a/pulsar-cli-utils/build.gradle.kts
+++ b/pulsar-cli-utils/build.gradle.kts
@@ -22,6 +22,6 @@ plugins {
}
dependencies {
- implementation(libs.picocli)
+ api(libs.picocli)
implementation(libs.commons.lang3)
}
diff --git a/pulsar-client-admin-api/build.gradle.kts
b/pulsar-client-admin-api/build.gradle.kts
index 48f33b2d074..533bef97f31 100644
--- a/pulsar-client-admin-api/build.gradle.kts
+++ b/pulsar-client-admin-api/build.gradle.kts
@@ -24,5 +24,5 @@ plugins {
dependencies {
implementation(libs.slog)
api(project(":pulsar-client-api"))
- implementation(libs.jackson.annotations)
+ api(libs.jackson.annotations)
}
diff --git a/pulsar-client-admin-shaded/build.gradle.kts
b/pulsar-client-admin-shaded/build.gradle.kts
index df1c0d177f1..8fe0120d3a2 100644
--- a/pulsar-client-admin-shaded/build.gradle.kts
+++ b/pulsar-client-admin-shaded/build.gradle.kts
@@ -23,6 +23,21 @@ plugins {
}
dependencies {
+ // Bundled into the shaded jar (kept on the runtime classpath so shadowJar
packs them):
implementation(project(":pulsar-client-admin-original"))
implementation(project(":pulsar-client-messagecrypto-bc"))
+
+ // Non-bundled runtime dependencies for the dependency-reduced published
POM/GMM (the `shadow`
+ // component). Logging is slf4j + slog only — never log4j.
+ "shadow"(project(":pulsar-client-api"))
+ "shadow"(project(":pulsar-client-admin-api"))
+ "shadow"(libs.protobuf.java)
+ "shadow"(libs.jackson.annotations)
+ "shadow"(libs.bcprov.jdk18on)
+ "shadow"(libs.bcpkix.jdk18on)
+ "shadow"(libs.opentelemetry.api)
+ "shadow"(libs.opentelemetry.api.incubator)
+ "shadow"(libs.jspecify)
+ "shadow"(libs.slf4j.api)
+ "shadow"(libs.slog)
}
diff --git a/pulsar-client-admin/build.gradle.kts
b/pulsar-client-admin/build.gradle.kts
index 0d95a6c443f..b82bdf95708 100644
--- a/pulsar-client-admin/build.gradle.kts
+++ b/pulsar-client-admin/build.gradle.kts
@@ -24,22 +24,22 @@ plugins {
dependencies {
implementation(libs.slog)
api(project(":pulsar-client-admin-api"))
- implementation(project(":pulsar-client-original"))
- implementation(project(":pulsar-common"))
+ api(project(":pulsar-client-original"))
+ api(project(":pulsar-common"))
implementation(project(":pulsar-package-management:pulsar-package-core"))
- implementation(libs.jersey.client)
+ api(libs.jersey.client)
implementation(libs.jersey.media.json.jackson)
implementation(libs.jersey.media.multipart)
implementation(libs.jersey.hk2)
implementation(libs.jackson.jakarta.rs.json.provider)
- implementation(libs.jackson.databind)
- implementation(libs.jakarta.ws.rs.api)
+ api(libs.jackson.databind)
+ api(libs.jakarta.ws.rs.api)
implementation(libs.jakarta.xml.bind.api)
implementation(libs.jakarta.activation.api)
runtimeOnly(libs.angus.activation)
implementation(libs.guava)
- implementation(libs.gson)
- implementation(libs.asynchttpclient)
+ api(libs.gson)
+ api(libs.asynchttpclient)
implementation(libs.commons.lang3)
implementation(libs.completable.futures)
diff --git a/pulsar-client-all/build.gradle.kts
b/pulsar-client-all/build.gradle.kts
index f6526e423ed..7c49a7d5465 100644
--- a/pulsar-client-all/build.gradle.kts
+++ b/pulsar-client-all/build.gradle.kts
@@ -23,11 +23,26 @@ plugins {
}
dependencies {
- implementation(project(":pulsar-client-api"))
+ // Bundled into the shaded jar (kept on the runtime classpath so shadowJar
packs them):
implementation(project(":pulsar-client-original"))
implementation(project(":pulsar-client-admin-original"))
implementation(project(":pulsar-client-messagecrypto-bc"))
+ // Non-bundled runtime dependencies for the dependency-reduced published
POM/GMM (the `shadow`
+ // component) — union of the client and admin shaded sets. Logging is
slf4j + slog only — never
+ // log4j (the log4j entries below are test-only and never reach the
publication).
+ "shadow"(project(":pulsar-client-api"))
+ "shadow"(project(":pulsar-client-admin-api"))
+ "shadow"(libs.protobuf.java)
+ "shadow"(libs.jackson.annotations)
+ "shadow"(libs.bcprov.jdk18on)
+ "shadow"(libs.bcpkix.jdk18on)
+ "shadow"(libs.opentelemetry.api)
+ "shadow"(libs.opentelemetry.api.incubator)
+ "shadow"(libs.jspecify)
+ "shadow"(libs.slf4j.api)
+ "shadow"(libs.slog)
+
testImplementation(libs.log4j.api)
testImplementation(libs.log4j.core)
testImplementation(libs.log4j.slf4j2.impl)
diff --git a/pulsar-client-api-v5/build.gradle.kts
b/pulsar-client-api-v5/build.gradle.kts
index fa777518491..6b232316368 100644
--- a/pulsar-client-api-v5/build.gradle.kts
+++ b/pulsar-client-api-v5/build.gradle.kts
@@ -18,7 +18,7 @@
*/
plugins {
- id("pulsar.java-conventions")
+ id("pulsar.public-java-library-conventions")
}
dependencies {
diff --git a/pulsar-client-auth-athenz/build.gradle.kts
b/pulsar-client-auth-athenz/build.gradle.kts
index eea4f829ecf..97830fd4451 100644
--- a/pulsar-client-auth-athenz/build.gradle.kts
+++ b/pulsar-client-auth-athenz/build.gradle.kts
@@ -22,7 +22,7 @@ plugins {
}
dependencies {
- implementation(project(":pulsar-client-api"))
+ api(project(":pulsar-client-api"))
implementation(project(":pulsar-client-original"))
implementation(libs.athenz.zts.java.client)
implementation(libs.athenz.cert.refresher)
diff --git a/pulsar-client-messagecrypto-bc/build.gradle.kts
b/pulsar-client-messagecrypto-bc/build.gradle.kts
index 8befb504e5b..553b714703a 100644
--- a/pulsar-client-messagecrypto-bc/build.gradle.kts
+++ b/pulsar-client-messagecrypto-bc/build.gradle.kts
@@ -23,11 +23,13 @@ plugins {
dependencies {
implementation(libs.slog)
- compileOnly(project(":pulsar-common"))
- implementation(project(":pulsar-client-api"))
- implementation(project(":bouncy-castle:bouncy-castle-bc"))
+ implementation(project(":pulsar-common"))
+ api(project(":pulsar-client-api"))
+ // MessageCryptoBc uses BouncyCastle types directly: bcpkix for PEM
parsing (PEMParser,
+ // JcaPEMKeyConverter) and bcprov for the EC/IES key specs and ASN.1 types
used in key handling.
+ // The JCA provider itself is resolved at runtime via SecurityUtility
(pulsar-common), not here.
implementation(libs.bcpkix.jdk18on)
- implementation(libs.bcprov.jdk18on)
+ api(libs.bcprov.jdk18on)
implementation(libs.guava)
implementation(libs.caffeine)
compileOnly(libs.netty.buffer)
diff --git
a/pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java
b/pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java
index c9e5604a7b7..7b418cd67dc 100644
---
a/pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java
+++
b/pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java
@@ -29,8 +29,8 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
import java.security.PrivateKey;
+import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
@@ -64,6 +64,7 @@ import
org.apache.pulsar.client.api.PulsarClientException.CryptoException;
import org.apache.pulsar.common.api.proto.EncryptionKeys;
import org.apache.pulsar.common.api.proto.KeyValue;
import org.apache.pulsar.common.api.proto.MessageMetadata;
+import org.apache.pulsar.common.util.SecurityUtility;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
@@ -71,7 +72,6 @@ import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.jce.interfaces.ECPublicKey;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
@@ -91,7 +91,22 @@ public class MessageCryptoBc implements
MessageCrypto<MessageMetadata, MessageMe
// from assuming hardcoded value. However, it will increase the size of
the message even further.
public static final String RSA_TRANS =
"RSA/NONE/OAEPWithSHA1AndMGF1Padding";
public static final String AESGCM = "AES/GCM/NoPadding";
- private static final String AESGCM_PROVIDER_NAME;
+
+ // BouncyCastle JCA provider, resolved lazily on first use via the
initialization-on-demand holder
+ // idiom. Resolution is delegated to SecurityUtility.getProvider() — the
same FIPS-agnostic lookup
+ // used elsewhere in Pulsar (e.g. TLS) — so message crypto uses whichever
BouncyCastle provider is
+ // present on the classpath: the non-FIPS "BC"
(org.bouncycastle.jce.provider.BouncyCastleProvider)
+ // or the FIPS "BCFIPS"
(org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider), rather than
+ // hardcoding one. The resolved provider is passed directly to the JCA
getInstance(...) calls.
+ // Deferring the lookup to first use (asymmetric key wrapping with
RSA-OAEP/ECIES, or EC key
+ // loading) keeps any resolution failure out of class loading.
+ private static final class BcProviderHolder {
+ static final Provider PROVIDER = SecurityUtility.getProvider();
+ }
+
+ private static Provider bcProvider() {
+ return BcProviderHolder.PROVIDER;
+ }
private static final int tagLen = 16 * 8;
private final String logCtx;
@@ -117,30 +132,37 @@ public class MessageCryptoBc implements
MessageCrypto<MessageMetadata, MessageMe
// Initial seed
secureRandom.nextBytes(new byte[IV_LEN]);
-
- // Prefer SunJCE provider for AES-GCM for performance reason.
- // For cases where SunJCE is not available (e.g. non-hotspot JVM), use
BouncyCastle as fallback.
- String sunJceProviderName = "SunJCE";
- if (Security.getProvider(sunJceProviderName) != null) {
- AESGCM_PROVIDER_NAME = sunJceProviderName;
- } else {
- AESGCM_PROVIDER_NAME = BouncyCastleProvider.PROVIDER_NAME;
- }
-
- // Add provider only if it's not in the JVM
- if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
- Security.addProvider(new BouncyCastleProvider());
- }
}
// Thread-local instances for non-thread-safe JCA classes
private static final FastThreadLocal<Cipher> THREAD_LOCAL_CIPHER = new
FastThreadLocal<Cipher>() {
@Override
protected Cipher initialValue() throws Exception {
- return Cipher.getInstance(AESGCM, AESGCM_PROVIDER_NAME);
+ return createAesGcmCipher();
}
};
+ /**
+ * Creates an AES-GCM cipher, preferring a JDK-provided implementation for
performance and broad
+ * JVM compatibility. SunJCE is used when present (HotSpot); otherwise the
platform default
+ * provider is used (e.g. IBMJCE on IBM JDKs), and BouncyCastle is the
last resort. The provider
+ * is resolved here — lazily, per thread — rather than during class
initialization, so a missing
+ * or unusual provider surfaces as a normal crypto exception at use time
instead of breaking class
+ * loading.
+ */
+ private static Cipher createAesGcmCipher() throws
NoSuchAlgorithmException, NoSuchPaddingException {
+ Provider sunJce = Security.getProvider("SunJCE");
+ if (sunJce != null) {
+ return Cipher.getInstance(AESGCM, sunJce);
+ }
+ try {
+ // No explicit provider: let the JVM select its default AES-GCM
implementation.
+ return Cipher.getInstance(AESGCM);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ return Cipher.getInstance(AESGCM, bcProvider());
+ }
+ }
+
private static final FastThreadLocal<KeyGenerator>
THREAD_LOCAL_KEY_GENERATOR =
new FastThreadLocal<KeyGenerator>() {
@Override
@@ -215,7 +237,7 @@ public class MessageCryptoBc implements
MessageCrypto<MessageMetadata, MessageMe
PublicKey publicKey;
try (PEMParser pemReader = new PEMParser(keyReader)) {
Object pemObj = pemReader.readObject();
- JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
+ JcaPEMKeyConverter pemConverter = new
JcaPEMKeyConverter().setProvider(bcProvider());
SubjectPublicKeyInfo keyInfo;
X9ECParameters ecParam = null;
@@ -244,11 +266,11 @@ public class MessageCryptoBc implements
MessageCrypto<MessageMetadata, MessageMe
if (ecParam != null && ECDSA.equals(publicKey.getAlgorithm())) {
ECParameterSpec ecSpec = new
ECParameterSpec(ecParam.getCurve(), ecParam.getG(), ecParam.getN(),
ecParam.getH(), ecParam.getSeed());
- KeyFactory keyFactory = KeyFactory.getInstance(ECDSA,
BouncyCastleProvider.PROVIDER_NAME);
+ KeyFactory keyFactory = KeyFactory.getInstance(ECDSA,
bcProvider());
ECPublicKeySpec keySpec = new ECPublicKeySpec(((ECPublicKey)
publicKey).getQ(), ecSpec);
publicKey = keyFactory.generatePublic(keySpec);
}
- } catch (IOException | NoSuchAlgorithmException |
NoSuchProviderException | InvalidKeySpecException e) {
+ } catch (IOException | NoSuchAlgorithmException |
InvalidKeySpecException e) {
throw new Exception(e);
}
return publicKey;
@@ -279,10 +301,10 @@ public class MessageCryptoBc implements
MessageCrypto<MessageMetadata, MessageMe
if (pemObj instanceof PEMKeyPair) {
PrivateKeyInfo pKeyInfo = ((PEMKeyPair)
pemObj).getPrivateKeyInfo();
- JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
+ JcaPEMKeyConverter pemConverter = new
JcaPEMKeyConverter().setProvider(bcProvider());
privateKey = pemConverter.getPrivateKey(pKeyInfo);
} else if (pemObj instanceof PrivateKeyInfo) {
- JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
+ JcaPEMKeyConverter pemConverter = new
JcaPEMKeyConverter().setProvider(bcProvider());
privateKey = pemConverter.getPrivateKey((PrivateKeyInfo)
pemObj);
}
@@ -291,7 +313,7 @@ public class MessageCryptoBc implements
MessageCrypto<MessageMetadata, MessageMe
if (ecParam != null && ECDSA.equals(privateKey.getAlgorithm())) {
ECParameterSpec ecSpec = new
ECParameterSpec(ecParam.getCurve(), ecParam.getG(), ecParam.getN(),
ecParam.getH(), ecParam.getSeed());
- KeyFactory keyFactory = KeyFactory.getInstance(ECDSA,
BouncyCastleProvider.PROVIDER_NAME);
+ KeyFactory keyFactory = KeyFactory.getInstance(ECDSA,
bcProvider());
ECPrivateKeySpec keySpec = new
ECPrivateKeySpec(((ECPrivateKey) privateKey).getS(), ecSpec);
privateKey = keyFactory.generatePrivate(keySpec);
}
@@ -346,9 +368,9 @@ public class MessageCryptoBc implements
MessageCrypto<MessageMetadata, MessageMe
AlgorithmParameterSpec params = null;
// Encrypt data key using public key
if (RSA.equals(pubKey.getAlgorithm())) {
- dataKeyCipher = Cipher.getInstance(RSA_TRANS,
BouncyCastleProvider.PROVIDER_NAME);
+ dataKeyCipher = Cipher.getInstance(RSA_TRANS, bcProvider());
} else if (ECDSA.equals(pubKey.getAlgorithm())) {
- dataKeyCipher = Cipher.getInstance(ECIES,
BouncyCastleProvider.PROVIDER_NAME);
+ dataKeyCipher = Cipher.getInstance(ECIES, bcProvider());
params = createIESParameterSpec();
} else {
String msg = logCtx + "Unsupported key type " +
pubKey.getAlgorithm() + " for key " + keyName;
@@ -361,7 +383,7 @@ public class MessageCryptoBc implements
MessageCrypto<MessageMetadata, MessageMe
dataKeyCipher.init(Cipher.ENCRYPT_MODE, pubKey);
}
encryptedKey = dataKeyCipher.doFinal(encryptionKey.getEncoded());
- } catch (IllegalBlockSizeException | BadPaddingException |
NoSuchAlgorithmException | NoSuchProviderException
+ } catch (IllegalBlockSizeException | BadPaddingException |
NoSuchAlgorithmException
| NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException e) {
log.error().attr("logCtx", logCtx).attr("keyName", keyName)
.exceptionMessage(e).log("Failed to encrypt data key");
@@ -508,9 +530,9 @@ public class MessageCryptoBc implements
MessageCrypto<MessageMetadata, MessageMe
Cipher dataKeyCipher;
// Decrypt data key using private key
if (RSA.equals(privateKey.getAlgorithm())) {
- dataKeyCipher = Cipher.getInstance(RSA_TRANS,
BouncyCastleProvider.PROVIDER_NAME);
+ dataKeyCipher = Cipher.getInstance(RSA_TRANS, bcProvider());
} else if (ECDSA.equals(privateKey.getAlgorithm())) {
- dataKeyCipher = Cipher.getInstance(ECIES,
BouncyCastleProvider.PROVIDER_NAME);
+ dataKeyCipher = Cipher.getInstance(ECIES, bcProvider());
params = createIESParameterSpec();
} else {
log.error().attr("keyType",
privateKey.getAlgorithm()).attr("keyName", keyName)
diff --git a/pulsar-client-shaded/build.gradle.kts
b/pulsar-client-shaded/build.gradle.kts
index 4822c850d10..654e50f7273 100644
--- a/pulsar-client-shaded/build.gradle.kts
+++ b/pulsar-client-shaded/build.gradle.kts
@@ -23,7 +23,24 @@ plugins {
}
dependencies {
- implementation(project(":pulsar-client-api"))
+ // Bundled into the shaded jar (kept on the runtime classpath so shadowJar
packs them):
implementation(project(":pulsar-client-original"))
implementation(project(":pulsar-client-messagecrypto-bc"))
+
+ // Non-bundled runtime dependencies. These are the ONLY entries in the
dependency-reduced
+ // published POM/Gradle Module Metadata (the `shadow` component). The
bundled modules above and
+ // their relocated third-party deps live inside the jar and must NOT
appear as POM dependencies.
+ // pulsar-client-api, protobuf, jackson-annotations, the BouncyCastle jars
(signed, not
+ // relocatable), OpenTelemetry and jspecify are deliberately not bundled.
Logging is slf4j + slog
+ // only — never log4j.
+ "shadow"(project(":pulsar-client-api"))
+ "shadow"(libs.protobuf.java)
+ "shadow"(libs.jackson.annotations)
+ "shadow"(libs.bcprov.jdk18on)
+ "shadow"(libs.bcpkix.jdk18on)
+ "shadow"(libs.opentelemetry.api)
+ "shadow"(libs.opentelemetry.api.incubator)
+ "shadow"(libs.jspecify)
+ "shadow"(libs.slf4j.api)
+ "shadow"(libs.slog)
}
diff --git a/pulsar-client-tools/build.gradle.kts
b/pulsar-client-tools/build.gradle.kts
index 6db5482e942..e97417c862d 100644
--- a/pulsar-client-tools/build.gradle.kts
+++ b/pulsar-client-tools/build.gradle.kts
@@ -24,10 +24,10 @@ plugins {
dependencies {
implementation(libs.slog)
api(project(":pulsar-client-tools-api"))
- implementation(project(":pulsar-client-admin-api"))
+ api(project(":pulsar-client-admin-api"))
implementation(project(":pulsar-client-admin-original"))
implementation(project(":pulsar-client-original"))
- implementation(project(":pulsar-client-api-v5"))
+ api(project(":pulsar-client-api-v5"))
implementation(project(":pulsar-client-v5"))
implementation(project(":pulsar-common"))
implementation(project(":pulsar-client-messagecrypto-bc"))
@@ -35,9 +35,9 @@ dependencies {
implementation(project(":pulsar-websocket")) {
exclude(group = "*", module = "*")
}
- implementation(libs.picocli)
+ api(libs.picocli)
implementation(libs.picocli.shell.jline3)
- implementation(libs.jline)
+ api(libs.jline)
implementation(libs.commons.io)
implementation(libs.commons.lang3)
// guava was previously leaked onto the compile classpath via
compileOnly(swagger-core 1.x)
@@ -45,11 +45,11 @@ dependencies {
implementation(libs.commons.text)
implementation(libs.asynchttpclient)
implementation(libs.netty.reactive.streams)
- implementation(libs.gson)
+ api(libs.gson)
implementation(libs.javassist)
implementation(libs.avro)
implementation(libs.jetty.client)
- implementation(libs.jetty.websocket.jetty.api)
+ api(libs.jetty.websocket.jetty.api)
implementation(libs.jetty.websocket.jetty.client)
runtimeOnly(libs.jna)
diff --git a/pulsar-client-v5/build.gradle.kts
b/pulsar-client-v5/build.gradle.kts
index 0a5ebda446d..8e564ca4593 100644
--- a/pulsar-client-v5/build.gradle.kts
+++ b/pulsar-client-v5/build.gradle.kts
@@ -18,11 +18,11 @@
*/
plugins {
- id("pulsar.java-conventions")
+ id("pulsar.public-java-library-conventions")
}
dependencies {
- implementation(project(":pulsar-client-api-v5"))
+ api(project(":pulsar-client-api-v5"))
implementation(project(":pulsar-client-original"))
implementation(project(":pulsar-common"))
implementation(libs.slf4j.api)
diff --git a/pulsar-client/build.gradle.kts b/pulsar-client/build.gradle.kts
index 43c382b2478..c6c623a9b82 100644
--- a/pulsar-client/build.gradle.kts
+++ b/pulsar-client/build.gradle.kts
@@ -24,13 +24,15 @@ plugins {
dependencies {
api(project(":pulsar-client-api"))
- implementation(project(":pulsar-common")) {
+ api(project(":pulsar-common")) {
exclude(group = "io.prometheus", module = "simpleclient_caffeine")
}
- implementation(project(":bouncy-castle:bouncy-castle-bc"))
+ // Non-FIPS BouncyCastle JCA provider, needed at runtime by
pulsar-client-messagecrypto-bc.
+ implementation(libs.bcprov.jdk18on)
+ implementation(libs.bcpkix.jdk18on)
compileOnly(project(":pulsar-client-messagecrypto-bc"))
- implementation(libs.opentelemetry.api)
+ api(libs.opentelemetry.api)
implementation(libs.opentelemetry.api.incubator)
implementation(libs.netty.codec.http)
implementation(libs.netty.handler.proxy)
@@ -38,18 +40,18 @@ dependencies {
implementation(libs.netty.resolver.dns)
implementation(variantOf(libs.netty.resolver.dns.native.macos) {
classifier("osx-aarch_64") })
implementation(variantOf(libs.netty.resolver.dns.native.macos) {
classifier("osx-x86_64") })
- implementation(libs.guava)
+ api(libs.guava)
implementation(libs.bookkeeper.circe.checksum) {
exclude(group = "io.netty")
}
implementation(libs.commons.lang3)
- implementation(libs.asynchttpclient)
+ api(libs.asynchttpclient)
implementation(libs.netty.reactive.streams)
- implementation(libs.slog)
+ api(libs.slog)
implementation(libs.commons.codec)
implementation(libs.datasketches.java)
implementation(libs.gson)
- implementation(libs.avro) {
+ api(libs.avro) {
exclude(group = "org.slf4j")
}
implementation(libs.avro.protobuf) {
@@ -57,7 +59,7 @@ dependencies {
}
implementation(libs.jackson.module.jsonSchema)
implementation(libs.jsr305)
- implementation(libs.jspecify)
+ api(libs.jspecify)
implementation(libs.roaringbitmap)
compileOnly(libs.swagger.annotations)
diff --git a/pulsar-common/build.gradle.kts b/pulsar-common/build.gradle.kts
index 6e192df5a64..e3b9595ab1f 100644
--- a/pulsar-common/build.gradle.kts
+++ b/pulsar-common/build.gradle.kts
@@ -148,17 +148,17 @@ dependencies {
api(project(":pulsar-client-api"))
api(project(":pulsar-client-admin-api"))
- implementation(libs.jackson.databind)
+ api(libs.jackson.databind)
implementation(libs.jackson.module.parameter.names)
implementation(libs.jackson.datatype.jsr310)
implementation(libs.jackson.datatype.jdk8)
implementation(libs.jackson.dataformat.yaml)
- implementation(libs.guava)
- implementation(libs.simpleclient.caffeine)
- implementation(libs.jspecify)
- implementation(libs.netty.handler)
- implementation(libs.netty.buffer)
- implementation(libs.netty.resolver.dns)
+ api(libs.guava)
+ api(libs.simpleclient.caffeine)
+ api(libs.jspecify)
+ api(libs.netty.handler)
+ api(libs.netty.buffer)
+ api(libs.netty.resolver.dns)
implementation(variantOf(libs.netty.transport.native.epoll) {
classifier("linux-x86_64") })
implementation(variantOf(libs.netty.transport.native.epoll) {
classifier("linux-aarch_64") })
implementation(libs.netty.transport.native.unix.common)
@@ -170,7 +170,7 @@ dependencies {
exclude(group = "commons-configuration", module =
"commons-configuration2")
exclude(group = "commons-beanutils", module = "commons-beanutils")
}
- implementation(libs.aircompressor)
+ api(libs.aircompressor)
implementation(libs.bookkeeper.circe.checksum) {
exclude(group = "io.netty")
exclude(group = "commons-configuration", module =
"commons-configuration2")
@@ -184,18 +184,23 @@ dependencies {
implementation(libs.netty.transport.classes.io.uring)
implementation(variantOf(libs.netty.transport.native.io.uring) {
classifier("linux-x86_64") })
implementation(variantOf(libs.netty.transport.native.io.uring) {
classifier("linux-aarch_64") })
- implementation(libs.netty.codec.haproxy)
+ api(libs.netty.codec.haproxy)
implementation(libs.commons.lang3)
- implementation(libs.jakarta.ws.rs.api)
+ api(libs.jakarta.ws.rs.api)
implementation(libs.commons.io)
implementation(libs.re2j)
implementation(libs.completable.futures)
- implementation(libs.gson)
+ api(libs.gson)
compileOnly(libs.swagger.annotations)
compileOnly(libs.spotbugs.annotations)
- testImplementation(libs.bc.fips)
+ // Non-FIPS BouncyCastle provider for tests that exercise SecurityUtility
(which loads
+ // org.bouncycastle.jce.provider.BouncyCastleProvider in a static
initializer). This matches
+ // the provider used in production. FIPS is covered separately by the
bcfips-include-test
+ // module; bc-fips must not be on a classpath that also has the non-FIPS
provider because both
+ // jars define org.bouncycastle.* and the JVM rejects the mismatched
signers.
+ testImplementation(libs.bcprov.jdk18on)
testImplementation(libs.lz4.java)
testImplementation(libs.zstd.jni)
testImplementation(libs.snappy.java)
diff --git
a/pulsar-common/src/main/java/org/apache/pulsar/common/util/BCLoader.java
b/pulsar-common/src/main/java/org/apache/pulsar/common/util/BCLoader.java
deleted file mode 100644
index 268cd430e68..00000000000
--- a/pulsar-common/src/main/java/org/apache/pulsar/common/util/BCLoader.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.pulsar.common.util;
-
-import java.security.Provider;
-
-/**
- * This interface declares a Bouncy Castle provider Loader.
- */
-public interface BCLoader {
- Provider getProvider();
-}
diff --git a/pulsar-docs-tools/build.gradle.kts
b/pulsar-docs-tools/build.gradle.kts
index 4438ae22edd..a30427b9221 100644
--- a/pulsar-docs-tools/build.gradle.kts
+++ b/pulsar-docs-tools/build.gradle.kts
@@ -22,9 +22,9 @@ plugins {
}
dependencies {
- implementation(libs.commons.lang3)
+ api(libs.commons.lang3)
implementation(libs.guava)
implementation(libs.slog)
implementation(libs.swagger.annotations)
- implementation(libs.picocli)
+ api(libs.picocli)
}
diff --git a/pulsar-functions/instance/build.gradle.kts
b/pulsar-functions/instance/build.gradle.kts
index f9e9494fe52..1482d258321 100644
--- a/pulsar-functions/instance/build.gradle.kts
+++ b/pulsar-functions/instance/build.gradle.kts
@@ -24,30 +24,30 @@ plugins {
dependencies {
implementation(libs.slog)
api(project(":pulsar-functions:pulsar-functions-utils"))
- implementation(project(":pulsar-functions:pulsar-functions-api"))
- implementation(project(":pulsar-functions:pulsar-functions-secrets"))
- implementation(project(":pulsar-functions:pulsar-functions-proto"))
+ api(project(":pulsar-functions:pulsar-functions-api"))
+ api(project(":pulsar-functions:pulsar-functions-secrets"))
+ api(project(":pulsar-functions:pulsar-functions-proto"))
implementation(project(":pulsar-metadata"))
- implementation(project(":pulsar-io:pulsar-io-core"))
- implementation(project(":pulsar-client-original"))
+ api(project(":pulsar-io:pulsar-io-core"))
+ api(project(":pulsar-client-original"))
implementation(project(":pulsar-client-admin-original"))
implementation(project(":pulsar-client-messagecrypto-bc"))
- implementation(libs.guava)
+ api(libs.guava)
implementation(libs.gson)
- implementation(libs.commons.lang3)
+ api(libs.commons.lang3)
implementation(libs.caffeine)
implementation(libs.picocli)
implementation(libs.typetools)
- implementation(libs.simpleclient)
+ api(libs.simpleclient)
implementation(libs.simpleclient.hotspot)
implementation(libs.simpleclient.caffeine)
implementation(libs.simpleclient.httpserver)
implementation(libs.prometheus.jmx.collector)
implementation(libs.datasketches.java)
implementation(libs.jackson.databind)
- implementation(libs.netty.buffer)
+ api(libs.netty.buffer)
implementation(libs.netty.common)
- implementation(libs.bookkeeper.stream.storage.java.client) {
+ api(libs.bookkeeper.stream.storage.java.client) {
exclude(group = "io.grpc")
exclude(group = "com.google.protobuf")
}
@@ -60,7 +60,7 @@ dependencies {
runtimeOnly(libs.perfmark.api)
implementation(libs.log4j.slf4j2.impl)
implementation(libs.log4j.api)
- implementation(libs.log4j.core)
+ api(libs.log4j.core)
implementation(libs.bcpkix.jdk18on)
implementation(libs.bookkeeper.circe.checksum)
// Main code only touches com.google.protobuf reflectively (protobuf
schema detection for user
diff --git
a/pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/instance/ProducerBuilderFactory.java
b/pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/instance/ProducerBuilderFactory.java
index a73c9d6d1a6..1ed3a9962e9 100644
---
a/pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/instance/ProducerBuilderFactory.java
+++
b/pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/instance/ProducerBuilderFactory.java
@@ -20,7 +20,6 @@ package org.apache.pulsar.functions.instance;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import com.google.common.annotations.VisibleForTesting;
-import java.security.Security;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import lombok.Builder;
@@ -38,7 +37,6 @@ import org.apache.pulsar.client.api.Schema;
import org.apache.pulsar.common.functions.CryptoConfig;
import org.apache.pulsar.common.functions.ProducerConfig;
import org.apache.pulsar.functions.utils.CryptoUtils;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* This class is responsible for creating ProducerBuilders with the
appropriate configurations to
@@ -162,11 +160,6 @@ public class ProducerBuilderFactory {
CryptoConfig cryptoConfig = producerConfig.getCryptoConfig();
- // add provider only if it's not in the JVM
- if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
- Security.addProvider(new BouncyCastleProvider());
- }
-
final String[] encryptionKeys = cryptoConfig.getEncryptionKeys();
Crypto.CryptoBuilder bldr = Crypto.builder()
.failureAction(cryptoConfig.getProducerCryptoFailureAction())
diff --git
a/pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/source/PulsarSource.java
b/pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/source/PulsarSource.java
index 835659d4a7d..9cdb3405926 100644
---
a/pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/source/PulsarSource.java
+++
b/pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/source/PulsarSource.java
@@ -18,7 +18,6 @@
*/
package org.apache.pulsar.functions.source;
-import java.security.Security;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -39,7 +38,6 @@ import org.apache.pulsar.functions.api.Record;
import org.apache.pulsar.functions.utils.CryptoUtils;
import org.apache.pulsar.functions.utils.MessagePayloadProcessorUtils;
import org.apache.pulsar.io.core.Source;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
public abstract class PulsarSource<T> implements Source<T> {
protected final PulsarClient pulsarClient;
@@ -185,11 +183,6 @@ public abstract class PulsarSource<T> implements Source<T>
{
consumerConfBuilder.schema(schema);
if (conf.getCryptoConfig() != null) {
- // add provider only if it's not in the JVM
- if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) ==
null) {
- Security.addProvider(new BouncyCastleProvider());
- }
-
consumerConfBuilder.consumerCryptoFailureAction(conf.getCryptoConfig().getConsumerCryptoFailureAction());
consumerConfBuilder.cryptoKeyReader(CryptoUtils.getCryptoKeyReaderInstance(
conf.getCryptoConfig().getCryptoKeyReaderClassName(),
diff --git a/pulsar-functions/localrun/build.gradle.kts
b/pulsar-functions/localrun/build.gradle.kts
index 4ab324064f9..ed7a3285728 100644
--- a/pulsar-functions/localrun/build.gradle.kts
+++ b/pulsar-functions/localrun/build.gradle.kts
@@ -25,7 +25,7 @@ dependencies {
implementation(libs.slog)
api(project(":pulsar-functions:pulsar-functions-instance"))
api(project(":pulsar-functions:pulsar-functions-runtime"))
- implementation(libs.picocli)
+ api(libs.picocli)
implementation(libs.gson)
implementation(libs.commons.lang3)
implementation(libs.simpleclient.httpserver)
diff --git a/pulsar-functions/runtime/build.gradle.kts
b/pulsar-functions/runtime/build.gradle.kts
index 7750e88989e..507c4b54e37 100644
--- a/pulsar-functions/runtime/build.gradle.kts
+++ b/pulsar-functions/runtime/build.gradle.kts
@@ -38,12 +38,12 @@ tasks.named<ProcessResources>("processTestResources") {
dependencies {
implementation(libs.slog)
api(project(":pulsar-functions:pulsar-functions-instance"))
- implementation(project(":pulsar-functions:pulsar-functions-secrets"))
- implementation(project(":pulsar-broker-common"))
- implementation(libs.picocli)
+ api(project(":pulsar-functions:pulsar-functions-secrets"))
+ api(project(":pulsar-broker-common"))
+ api(libs.picocli)
implementation(libs.jackson.dataformat.yaml)
implementation(libs.jackson.databind)
- implementation(libs.jackson.annotations)
+ api(libs.jackson.annotations)
implementation(libs.commons.lang3)
implementation(libs.kubernetes.client.java) {
exclude(group = "org.bouncycastle", module = "bcpkix-jdk18on")
@@ -58,7 +58,7 @@ dependencies {
implementation(libs.prometheus.jmx.collector)
implementation(libs.protobuf.java.util)
implementation(libs.guava)
- implementation(project(":pulsar-functions:pulsar-functions-proto"))
+ api(project(":pulsar-functions:pulsar-functions-proto"))
implementation(project(":pulsar-client-original"))
implementation(libs.grpc.netty.shaded)
implementation(libs.grpc.stub)
diff --git a/pulsar-functions/secrets/build.gradle.kts
b/pulsar-functions/secrets/build.gradle.kts
index 0dd441a0f24..b08de752c37 100644
--- a/pulsar-functions/secrets/build.gradle.kts
+++ b/pulsar-functions/secrets/build.gradle.kts
@@ -22,7 +22,7 @@ plugins {
}
dependencies {
- implementation(project(":pulsar-functions:pulsar-functions-proto"))
+ api(project(":pulsar-functions:pulsar-functions-proto"))
implementation(libs.kubernetes.client.java) {
exclude(group = "software.amazon.awssdk")
// Swagger 1.x annotations on the generated k8s models are inert
metadata; nothing reads them at runtime
diff --git a/pulsar-functions/utils/build.gradle.kts
b/pulsar-functions/utils/build.gradle.kts
index 13a8a910f3e..9e0d4fa1a6a 100644
--- a/pulsar-functions/utils/build.gradle.kts
+++ b/pulsar-functions/utils/build.gradle.kts
@@ -25,7 +25,7 @@ dependencies {
implementation(libs.slog)
api(project(":pulsar-common"))
api(project(":pulsar-functions:pulsar-functions-api"))
- implementation(project(":pulsar-functions:pulsar-functions-proto"))
+ api(project(":pulsar-functions:pulsar-functions-proto"))
implementation(project(":pulsar-io:pulsar-io-core"))
implementation(project(":pulsar-config-validation"))
implementation(libs.commons.lang3)
@@ -34,7 +34,7 @@ dependencies {
implementation(project(":pulsar-client-original"))
implementation(libs.protobuf.java)
implementation(libs.protobuf.java.util)
- implementation(libs.byte.buddy)
+ api(libs.byte.buddy)
implementation(libs.zt.zip)
implementation(libs.guava)
diff --git a/pulsar-functions/worker/build.gradle.kts
b/pulsar-functions/worker/build.gradle.kts
index a4201d6a2ae..5c7890e2194 100644
--- a/pulsar-functions/worker/build.gradle.kts
+++ b/pulsar-functions/worker/build.gradle.kts
@@ -38,11 +38,11 @@ tasks.named<ProcessResources>("processTestResources") {
dependencies {
implementation(libs.slog)
api(project(":pulsar-functions:pulsar-functions-runtime"))
- implementation(project(":pulsar-broker-common"))
+ api(project(":pulsar-broker-common"))
implementation(project(":pulsar-opentelemetry"))
implementation(project(":pulsar-client-original"))
implementation(project(":pulsar-client-admin-original"))
- implementation(project(":pulsar-functions:pulsar-functions-proto"))
+ api(project(":pulsar-functions:pulsar-functions-proto"))
implementation(project(":pulsar-functions:pulsar-functions-secrets"))
implementation(project(":pulsar-docs-tools")) {
exclude(group = "io.swagger.core.v3")
@@ -54,12 +54,12 @@ dependencies {
implementation(libs.guava)
implementation(libs.gson)
implementation(libs.picocli)
- implementation(libs.jackson.core)
- implementation(libs.jackson.databind)
+ api(libs.jackson.core)
+ api(libs.jackson.databind)
implementation(libs.netty.common)
implementation(libs.byte.buddy)
- implementation(libs.distributedlog.core) {
+ api(libs.distributedlog.core) {
exclude(group = "net.jpountz.lz4", module = "lz4")
}
implementation(libs.bookkeeper.server)
@@ -69,7 +69,7 @@ dependencies {
implementation(libs.jersey.container.servlet)
implementation(libs.jersey.container.servlet.core)
implementation(libs.jersey.media.json.jackson)
- implementation(libs.jersey.media.multipart)
+ api(libs.jersey.media.multipart)
implementation(libs.jetty.server)
implementation(libs.jetty.alpn.conscrypt.server)
@@ -77,7 +77,7 @@ dependencies {
implementation(libs.jetty.ee10.servlets)
implementation(libs.jakarta.activation.api)
- implementation(libs.jakarta.ws.rs.api)
+ api(libs.jakarta.ws.rs.api)
implementation(libs.simpleclient)
implementation(libs.simpleclient.hotspot)
diff --git a/pulsar-io/batch-data-generator/build.gradle.kts
b/pulsar-io/batch-data-generator/build.gradle.kts
index c9505b6a090..97dafcf249e 100644
--- a/pulsar-io/batch-data-generator/build.gradle.kts
+++ b/pulsar-io/batch-data-generator/build.gradle.kts
@@ -23,10 +23,10 @@ plugins {
}
dependencies {
implementation(libs.slog)
- implementation(project(":pulsar-io:pulsar-io-core"))
+ api(project(":pulsar-io:pulsar-io-core"))
implementation(project(":pulsar-io:pulsar-io-batch-discovery-triggerers"))
implementation(libs.spring.context)
- implementation(libs.jfairy)
+ api(libs.jfairy)
implementation(libs.avro)
testImplementation(project(":pulsar-functions:pulsar-functions-local-runner-original"))
diff --git a/pulsar-io/data-generator/build.gradle.kts
b/pulsar-io/data-generator/build.gradle.kts
index bbdc495048c..0db651943f4 100644
--- a/pulsar-io/data-generator/build.gradle.kts
+++ b/pulsar-io/data-generator/build.gradle.kts
@@ -23,8 +23,8 @@ plugins {
}
dependencies {
implementation(libs.slog)
- implementation(project(":pulsar-io:pulsar-io-core"))
+ api(project(":pulsar-io:pulsar-io-core"))
implementation(project(":pulsar-config-validation"))
- implementation(libs.jfairy)
+ api(libs.jfairy)
implementation(libs.avro)
}
diff --git a/pulsar-metadata/build.gradle.kts b/pulsar-metadata/build.gradle.kts
index 4a27ab0d9fc..c0469923ac3 100644
--- a/pulsar-metadata/build.gradle.kts
+++ b/pulsar-metadata/build.gradle.kts
@@ -23,13 +23,13 @@ plugins {
dependencies {
api(project(":pulsar-common"))
- implementation(libs.bookkeeper.server)
+ api(libs.bookkeeper.server)
implementation(libs.zookeeper) {
exclude(group = "org.slf4j")
}
implementation(libs.jackson.dataformat.yaml)
implementation(libs.oxia.client)
- implementation(libs.slog)
+ api(libs.slog)
implementation(libs.caffeine)
implementation(libs.simpleclient)
implementation(libs.simpleclient.caffeine)
diff --git a/pulsar-opentelemetry/build.gradle.kts
b/pulsar-opentelemetry/build.gradle.kts
index 333529da4a2..32718c76153 100644
--- a/pulsar-opentelemetry/build.gradle.kts
+++ b/pulsar-opentelemetry/build.gradle.kts
@@ -26,7 +26,7 @@ dependencies {
implementation(libs.opentelemetry.exporter.otlp)
implementation(libs.opentelemetry.exporter.prometheus)
implementation(libs.opentelemetry.sdk)
- implementation(libs.opentelemetry.sdk.extension.autoconfigure)
+ api(libs.opentelemetry.sdk.extension.autoconfigure)
implementation(libs.opentelemetry.instrumentation.resources)
implementation(libs.opentelemetry.semconv)
implementation(libs.opentelemetry.instrumentation.runtime.telemetry)
diff --git a/pulsar-proxy/build.gradle.kts b/pulsar-proxy/build.gradle.kts
index 12724d2ae79..d57bd0a885f 100644
--- a/pulsar-proxy/build.gradle.kts
+++ b/pulsar-proxy/build.gradle.kts
@@ -25,21 +25,21 @@ plugins {
dependencies {
implementation(libs.slog)
api(project(":pulsar-broker-common"))
- implementation(project(":pulsar-client-original"))
- implementation(project(":pulsar-common"))
+ api(project(":pulsar-client-original"))
+ api(project(":pulsar-common"))
implementation(project(":pulsar-opentelemetry"))
- implementation(project(":pulsar-docs-tools"))
- implementation(project(":pulsar-websocket"))
+ api(project(":pulsar-docs-tools"))
+ api(project(":pulsar-websocket"))
implementation(libs.commons.lang3)
implementation(libs.jetty.server)
implementation(libs.jetty.alpn.conscrypt.server)
implementation(libs.jetty.client)
- implementation(libs.jetty.ee10.servlet)
+ api(libs.jetty.ee10.servlet)
implementation(libs.jetty.ee10.servlets)
implementation(libs.jetty.ee10.proxy)
implementation(libs.jetty.ee10.websocket.jetty.server)
// ee8 + javax.servlet retained for the legacy AdditionalServlet
javax.servlet path (PIP-472)
- implementation(libs.jetty.ee8.servlet)
+ api(libs.jetty.ee8.servlet)
implementation(libs.javax.servlet.api)
implementation(libs.jersey.server)
implementation(libs.jersey.container.servlet.core)
@@ -51,20 +51,20 @@ dependencies {
implementation(libs.simpleclient.hotspot)
implementation(libs.simpleclient.servlet)
implementation(libs.jackson.jakarta.rs.json.provider)
- implementation(libs.picocli)
+ api(libs.picocli)
implementation(libs.log4j.core)
implementation(libs.log4j.api)
implementation(libs.ipaddress)
implementation(libs.netty.handler)
- implementation(libs.netty.transport)
- implementation(libs.netty.buffer)
+ api(libs.netty.transport)
+ api(libs.netty.buffer)
implementation(libs.netty.common)
- implementation(libs.netty.codec.haproxy)
+ api(libs.netty.codec.haproxy)
implementation(libs.netty.codec.http)
- implementation(libs.netty.resolver.dns)
+ api(libs.netty.resolver.dns)
implementation(libs.netty.transport.native.epoll)
implementation(libs.netty.handler.proxy)
- implementation(libs.bookkeeper.common)
+ api(libs.bookkeeper.common)
compileOnly(libs.swagger.annotations)
diff --git a/pulsar-testclient/build.gradle.kts
b/pulsar-testclient/build.gradle.kts
index 54637f9c0e7..9fd025af6f1 100644
--- a/pulsar-testclient/build.gradle.kts
+++ b/pulsar-testclient/build.gradle.kts
@@ -23,20 +23,20 @@ plugins {
}
dependencies {
- implementation(libs.slog)
+ api(libs.slog)
implementation(project(":pulsar-client-original"))
implementation(project(":pulsar-client-admin-original"))
- implementation(project(":pulsar-client-api-v5"))
+ api(project(":pulsar-client-api-v5"))
implementation(project(":pulsar-client-v5"))
implementation(project(":pulsar-client-messagecrypto-bc"))
implementation(project(":pulsar-broker"))
- implementation(project(":pulsar-cli-utils"))
+ api(project(":pulsar-cli-utils"))
implementation(project(":pulsar-common"))
implementation(project(":managed-ledger"))
- implementation(libs.picocli)
- implementation(libs.hdrHistogram)
+ api(libs.picocli)
+ api(libs.hdrHistogram)
implementation(libs.jackson.databind)
- implementation(libs.guava)
+ api(libs.guava)
implementation(libs.commons.lang3)
implementation(libs.commons.codec)
implementation(libs.slf4j.api)
@@ -45,11 +45,11 @@ dependencies {
implementation(libs.zookeeper) {
exclude(group = "org.slf4j")
}
- implementation(libs.bookkeeper.server)
+ api(libs.bookkeeper.server)
implementation(libs.re2j)
- implementation(libs.gson)
+ api(libs.gson)
implementation(libs.jetty.client)
- implementation(libs.jetty.websocket.jetty.api)
+ api(libs.jetty.websocket.jetty.api)
implementation(libs.jetty.websocket.jetty.client)
implementation(libs.jetty.util)
implementation(libs.opentelemetry.sdk.extension.autoconfigure)
diff --git a/pulsar-transaction/coordinator/build.gradle.kts
b/pulsar-transaction/coordinator/build.gradle.kts
index 9223abfc712..a8af0c1b02a 100644
--- a/pulsar-transaction/coordinator/build.gradle.kts
+++ b/pulsar-transaction/coordinator/build.gradle.kts
@@ -26,13 +26,13 @@ dependencies {
implementation(libs.slog)
api(project(":pulsar-common"))
implementation(project(":pulsar-opentelemetry"))
- implementation(project(":managed-ledger"))
+ api(project(":managed-ledger"))
implementation(libs.commons.lang3)
implementation(libs.commons.collections4)
- implementation(libs.netty.buffer)
- implementation(libs.netty.common)
+ api(libs.netty.buffer)
+ api(libs.netty.common)
implementation(libs.jctools.core.jdk11)
- implementation(libs.simpleclient)
+ api(libs.simpleclient)
implementation(libs.guava)
implementation(libs.bookkeeper.server)
diff --git a/pulsar-websocket/build.gradle.kts
b/pulsar-websocket/build.gradle.kts
index aae83d0db43..ee2b5d7e6e5 100644
--- a/pulsar-websocket/build.gradle.kts
+++ b/pulsar-websocket/build.gradle.kts
@@ -24,7 +24,7 @@ plugins {
dependencies {
implementation(libs.slog)
api(project(":pulsar-broker-common"))
- implementation(project(":pulsar-common"))
+ api(project(":pulsar-common"))
implementation(project(":pulsar-client-original"))
implementation(project(":pulsar-docs-tools"))
implementation(libs.commons.lang3)
@@ -39,10 +39,10 @@ dependencies {
// ee10 + jakarta.servlet for the REST/admin tier (Jersey 3) and the
WebSocket endpoint layer
implementation(libs.jetty.ee10.servlet)
implementation(libs.jetty.ee10.servlets)
- implementation(libs.jakarta.servlet.api)
+ api(libs.jakarta.servlet.api)
// Modern Jetty 12 WebSocket API on the ee10 stack (PIP-472)
- implementation(libs.jetty.ee10.websocket.jetty.server)
- implementation(libs.jetty.websocket.jetty.api)
+ api(libs.jetty.ee10.websocket.jetty.server)
+ api(libs.jetty.websocket.jetty.api)
implementation(libs.jetty.websocket.jetty.client)
implementation(libs.hdrHistogram)
implementation(libs.picocli)
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 7c5eba5a6b4..c847d5be210 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -68,10 +68,6 @@ include("pulsar-bom")
// Tier 0 — no internal dependencies
include("buildtools")
-// Maven artifactId is "bouncy-castle-bc" (directory is "bouncy-castle/bc")
-include("bouncy-castle:bouncy-castle-bc")
-project(":bouncy-castle:bouncy-castle-bc").projectDir =
file("bouncy-castle/bc")
-include("bouncy-castle:bcfips")
include("pulsar-config-validation")
include("pulsar-client-api")
include("pulsar-client-api-v5")
@@ -180,8 +176,9 @@
project(":jetty-upgrade:pulsar-zookeeper-prometheus-metrics").projectDir = file(
include("jetty-upgrade:zookeeper-with-patched-admin")
project(":jetty-upgrade:zookeeper-with-patched-admin").projectDir =
file("jetty-upgrade/zookeeper-with-patched-admin")
-// Tier 6.5 — bouncy castle test
-include("bouncy-castle:bcfips-include-test")
+// Tier 6.5 — FIPS BouncyCastle TLS integration test
+include("tests:pulsar-client-test-bcfips")
+project(":tests:pulsar-client-test-bcfips").projectDir =
file("tests/pulsar-client-test-bcfips")
// Tier 7
include("pulsar-proxy")
diff --git a/tests/docker-images/java-test-functions/build.gradle.kts
b/tests/docker-images/java-test-functions/build.gradle.kts
index c94069cf976..c0df4956809 100644
--- a/tests/docker-images/java-test-functions/build.gradle.kts
+++ b/tests/docker-images/java-test-functions/build.gradle.kts
@@ -24,8 +24,8 @@ plugins {
dependencies {
implementation(libs.slog)
- implementation(project(":pulsar-io:pulsar-io-core"))
- implementation(project(":pulsar-functions:pulsar-functions-api"))
+ api(project(":pulsar-io:pulsar-io-core"))
+ api(project(":pulsar-functions:pulsar-functions-api"))
compileOnly(libs.avro)
compileOnly(libs.jackson.databind)
compileOnly(libs.protobuf.java)
diff --git a/tests/pulsar-client-all-shade-test/build.gradle.kts
b/tests/pulsar-client-all-shade-test/build.gradle.kts
index 48c7260d96b..bd3f111ea17 100644
--- a/tests/pulsar-client-all-shade-test/build.gradle.kts
+++ b/tests/pulsar-client-all-shade-test/build.gradle.kts
@@ -30,9 +30,9 @@ dependencies {
testImplementation(project(":pulsar-client-api"))
testImplementation(project(":pulsar-client-admin-api"))
testImplementation(project(":pulsar-client-messagecrypto-bc"))
- testImplementation(project(":bouncy-castle:bouncy-castle-bc"))
testImplementation(project(":buildtools"))
testImplementation(libs.bcprov.jdk18on)
+ testImplementation(libs.bcpkix.jdk18on)
testImplementation(libs.testcontainers)
// Runtime deps needed by the client that are not bundled in the shaded
JARs
testRuntimeOnly(libs.opentelemetry.api)
diff --git a/bouncy-castle/bcfips-include-test/build.gradle.kts
b/tests/pulsar-client-test-bcfips/build.gradle.kts
similarity index 75%
rename from bouncy-castle/bcfips-include-test/build.gradle.kts
rename to tests/pulsar-client-test-bcfips/build.gradle.kts
index d52407e2d4b..836e1382b99 100644
--- a/bouncy-castle/bcfips-include-test/build.gradle.kts
+++ b/tests/pulsar-client-test-bcfips/build.gradle.kts
@@ -22,11 +22,11 @@ plugins {
id("pulsar.test-certs-conventions")
}
-
-// Exclude the non-FIPS BouncyCastle module — this module tests with FIPS
provider only.
-// Having both bc (bcprov) and bcfips (bc-fips) causes CryptoServicesRegistrar
conflicts.
+// FIPS is selected by EXCLUDING the non-FIPS BouncyCastle libraries
(bcprov/bcpkix/bcutil) that the
+// broker and client pull in transitively, leaving only the FIPS provider
(bc-fips) on the classpath.
+// The non-FIPS and FIPS jars both define org.bouncycastle.* classes with
different signers, so having
+// both on one classpath triggers CryptoServicesRegistrar signer conflicts.
configurations.all {
- exclude(group = "org.apache.pulsar", module = "bc")
exclude(group = "org.bouncycastle", module = "bcprov-jdk18on")
exclude(group = "org.bouncycastle", module = "bcprov-ext-jdk18on")
exclude(group = "org.bouncycastle", module = "bcpkix-jdk18on")
@@ -35,7 +35,9 @@ configurations.all {
dependencies {
implementation(libs.slog)
- testImplementation(project(":bouncy-castle:bcfips"))
+ testImplementation(libs.bc.fips)
+ testImplementation(libs.bcpkix.fips)
+ testImplementation(libs.bcutil.fips)
testImplementation(project(":pulsar-common"))
testImplementation(project(":pulsar-broker"))
testImplementation(project(path = ":pulsar-broker", configuration =
"testJar"))
diff --git
a/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java
b/tests/pulsar-client-test-bcfips/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java
similarity index 100%
rename from
bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java
rename to
tests/pulsar-client-test-bcfips/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java
diff --git
a/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java
b/tests/pulsar-client-test-bcfips/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java
similarity index 100%
rename from
bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java
rename to
tests/pulsar-client-test-bcfips/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java
diff --git a/tiered-storage/file-system/build.gradle.kts
b/tiered-storage/file-system/build.gradle.kts
index 57982d45222..93d2d8c1c80 100644
--- a/tiered-storage/file-system/build.gradle.kts
+++ b/tiered-storage/file-system/build.gradle.kts
@@ -60,7 +60,7 @@ dependencies {
compileOnly(project(":managed-ledger"))
compileOnly(libs.bookkeeper.server)
compileOnly(libs.netty.buffer)
- implementation(libs.hadoop.common) {
+ api(libs.hadoop.common) {
exclude(group = "log4j", module = "log4j")
exclude(group = "org.slf4j")
exclude(group = "dnsjava", module = "dnsjava")