(chores): fix SonarCloud S2975 clone without super.clone - #24487
Conversation
Fix 3 clone() methods that don't call super.clone(), addressing SonarCloud rule java:S2975. - MiloClientConfiguration: use super.clone() with deep copy of mutable allowedSecurityPolicies set - ThreadPoolProfile: use super.clone() (all fields are immutable primitives/wrappers/enums/String) - DefaultLineBuilderStrategy.LineBuilder: rename clone() to copy() since the private inner class doesn't implement Cloneable Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
|
🧪 CI tested the following changed modules:
🔬 Scalpel shadow comparison — Scalpel: 552 tested, 29 compile-only — current: 552 all testedMaveniverse Scalpel detected 581 affected modules (current approach: 552).
|
There was a problem hiding this comment.
Pull request overview
This PR addresses SonarCloud rule java:S2975 findings by fixing/adjusting clone() implementations so they either delegate to super.clone() (preserving the Cloneable contract) or avoid overriding Object.clone() when cloning isn’t needed.
Changes:
- Updated
ThreadPoolProfile.clone()to usesuper.clone()withCloneNotSupportedExceptionhandling. - Updated
MiloClientConfiguration.clone()to usesuper.clone()and deep-copyallowedSecurityPolicies. - Renamed an internal
LineBuilder.clone()method tocopy()to avoid overridingObject.clone().
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| core/camel-api/src/main/java/org/apache/camel/spi/ThreadPoolProfile.java | Switches clone() to super.clone() to preserve correct cloning semantics for subclasses. |
| components/camel-pdf/src/main/java/org/apache/camel/component/pdf/text/DefaultLineBuilderStrategy.java | Replaces a private inner clone() with copy() to avoid overriding Object.clone(). |
| components/camel-milo/src/main/java/org/apache/camel/component/milo/client/MiloClientConfiguration.java | Uses super.clone() and deep-copies allowedSecurityPolicies to avoid shared mutable state. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address Copilot review: allowedSecurityPolicies can be null (set via setAllowedSecurityPolicies(String) with null arg), so guard the deep copy to avoid NPE during clone(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Fix 3
clone()methods that don't callsuper.clone(), addressing SonarCloud rule java:S2975.Why SonarCloud flags these
SonarCloud rule S2975 ("clone should not be overridden") fires on any override of
clone(). The rationale (from Joshua Bloch's Effective Java) is thatObject.clone()has a fundamentally broken contract:super.clone()only creates a shallow copy — mutable fields are shared between original and clone, so mutating one silently corrupts the other.Object.clone()creates objects without calling any constructor, violating the invariant that all objects should be built through constructors.newinstead ofsuper.clone(), subclass clones get the wrong runtime type.The 3 files fixed here had the most concrete violation — they didn't call
super.clone()at all, usingnewinstead.Changes
MiloClientConfigurationclone()usednew MiloClientConfiguration(this)— breaks subclass cloning and theCloneablecontractsuper.clone()+ deep-copy of mutableallowedSecurityPoliciesHashSetThreadPoolProfileclone()usednew ThreadPoolProfile()+ manual field-by-field copy — same subclass problem, plus was already missing thesessionTimeoutfieldsuper.clone()(all fields are immutable primitives/wrappers/enums/String)DefaultLineBuilderStrategy.LineBuilderclone()usednew LineBuilder(...)— overridesObject.clone()without implementingCloneableclone()tocopy()since this private inner class doesn't needCloneableNote on the remaining 7 SonarCloud S2975 issues
The remaining 7 flagged files (
Transcribe2Configuration, 5× Infinispan configs,ComponentModel.ApiOptionModel) already callsuper.clone()correctly. SonarCloud still flags them because S2975 fires on anyclone()override — its position is thatclone()shouldn't be used at all. However, these areCloneableconfiguration classes used throughout Camel's component framework for endpoint creation. Removingclone()would be a breaking API change with no functional benefit, since they already follow thesuper.clone()contract correctly.Test plan
mvn testpasses incore/camel-apimvn testpasses incomponents/camel-milo(43 tests, 0 failures)mvn testpasses incomponents/camel-pdf(10 tests, 0 failures)mvn formatter:format impsort:sortapplied on all 3 modulescamel-vertx-websocket(flaky test), not in any changed moduleClaude Code on behalf of gnodet
🤖 Generated with Claude Code