From c946719dd5bda27ac23c6aa9cccdfcd3060fe7ec Mon Sep 17 00:00:00 2001 From: Anurag Date: Fri, 24 Jul 2026 23:19:59 +0100 Subject: [PATCH] Remove the never-public org.metricshub.winrm.backend property (#121) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The property was a transitional guard around the CXF removal during 2.0.0 development: it defaulted to `light` and rejected `cxf`. No public release ever exposed it, so nobody can have it set and the branches it guards are dead. - WinRMExecutorFactory: drop BACKEND_PROPERTY and the LIGHT/CXF constants, and let createInstance delegate straight to LightWinRMService. - WinRMExecutorFactoryTest: drop the cxf-rejection and unknown-value tests, the @AfterEach that cleared the property, and the setProperty calls. The `light` and default variants of the HTTP/HTTPS tests became identical, so they are merged into one test each; the capability guards (Kerberos over HTTP/HTTPS, closed-executor rejection) are untouched. The issue lists the documentation as already cleaned up, but three references were still there and are removed here too: README.md, CHANGELOG.md, and src/site/markdown/index.md — the last one inside src/, which the acceptance criteria cover. --- CHANGELOG.md | 2 - README.md | 4 +- .../winrm/service/WinRMExecutorFactory.java | 35 ++------ src/site/markdown/index.md | 4 +- .../service/WinRMExecutorFactoryTest.java | 84 ++----------------- 5 files changed, 12 insertions(+), 117 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 165a794..3be755d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,8 +56,6 @@ unaffected. Consequences: (`-Djavax.net.ssl.trustStore=...`); or - disable TLS validation with `-Dorg.metricshub.winrm.tls.insecure=true` (**insecure — for testing only**). -- Setting `-Dorg.metricshub.winrm.backend=cxf` now fails with a clear error instead of selecting - the removed backend: remove the property (or stay on winrm-java 1.x). - The jar shrinks dramatically: the Apache CXF / JAX-WS / JAXB stack is gone, and with the SMB file copy replaced by a WinRM-native transfer (see above), the library has **zero runtime dependencies**. diff --git a/README.md b/README.md index d5bbec0..7336b95 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The Windows Remote Management (WinRM) Java Client is a library that enables to: > ## ⚠️ Upgrading from 1.x > > Version 2.0.0 **removed the legacy Apache CXF backend**: the dependency-free **light** client is -> the only implementation (same public API — calling code is unaffected). Two consequences: +> the only implementation (same public API — calling code is unaffected). One consequence: > > * Unlike the CXF-based client, which silently trusted every TLS certificate, the light client > **validates the server certificate and verifies the hostname by default**. @@ -24,8 +24,6 @@ The Windows Remote Management (WinRM) Java Client is a library that enables to: > will fail** during the TLS handshake unless you install the server certificate (or its issuing > CA) into a Java trust store (e.g. `-Djavax.net.ssl.trustStore=...`) or disable TLS validation > with `-Dorg.metricshub.winrm.tls.insecure=true` (**insecure — for testing only**). -> * Setting `-Dorg.metricshub.winrm.backend=cxf` now fails with a clear error instead of selecting -> the removed backend. Remove the property (or stay on winrm-java 1.x). ## The WinRM client diff --git a/src/main/java/org/metricshub/winrm/service/WinRMExecutorFactory.java b/src/main/java/org/metricshub/winrm/service/WinRMExecutorFactory.java index 3639be6..c89a095 100644 --- a/src/main/java/org/metricshub/winrm/service/WinRMExecutorFactory.java +++ b/src/main/java/org/metricshub/winrm/service/WinRMExecutorFactory.java @@ -22,7 +22,6 @@ import java.nio.file.Path; import java.util.List; -import java.util.Locale; import org.metricshub.winrm.WindowsRemoteExecutor; import org.metricshub.winrm.exceptions.WinRMException; import org.metricshub.winrm.light.LightWinRMService; @@ -30,30 +29,21 @@ /** * Creates the {@link WindowsRemoteExecutor} that fulfils a request. Since 2.0.0 the dependency-free - * {@link LightWinRMService} is the only backend: the legacy CXF-based backend has been removed. - * The {@value #BACKEND_PROPERTY} system property is kept so operators who still set it get a clear - * error ({@code cxf}) or a no-op ({@code light}) instead of a silent behavior change. + * {@link LightWinRMService} is the only implementation: the legacy CXF-based backend has been removed. */ public final class WinRMExecutorFactory { - /** System property selecting the backend; {@code light} is the only supported value. */ - public static final String BACKEND_PROPERTY = "org.metricshub.winrm.backend"; - - private static final String LIGHT = "light"; - private static final String CXF = "cxf"; - private WinRMExecutorFactory() {} /** - * Create a {@link WindowsRemoteExecutor} (light backend). + * Create a {@link WindowsRemoteExecutor}. * * @param winRMEndpoint endpoint with credentials (mandatory) * @param timeout timeout in milliseconds (must be > 0) * @param ticketCache Kerberos ticket cache path (may be {@code null}) * @param authentications requested authentication schemes (may be {@code null}) - * @return a light-backed executor - * @throws WinRMException for any problem creating the executor, or when {@value #BACKEND_PROPERTY} - * requests the removed CXF backend or an unknown value + * @return an executor backed by {@link LightWinRMService} + * @throws WinRMException for any problem creating the executor */ public static WindowsRemoteExecutor createInstance( final WinRMEndpoint winRMEndpoint, @@ -61,21 +51,6 @@ public static WindowsRemoteExecutor createInstance( final Path ticketCache, final List authentications ) throws WinRMException { - final String backend = System.getProperty(BACKEND_PROPERTY, LIGHT).trim().toLowerCase(Locale.ROOT); - if (LIGHT.equals(backend)) { - return LightWinRMService.createInstance(winRMEndpoint, timeout, ticketCache, authentications); - } - if (CXF.equals(backend)) { - // Fail loudly: an operator who explicitly pinned the legacy backend must not be silently - // switched to another implementation. - throw new WinRMException( - "The CXF WinRM backend was removed in winrm-java 2.0.0; remove the " + - BACKEND_PROPERTY + - " system property to use the light backend (or stay on winrm-java 1.x)." - ); - } - throw new WinRMException( - "Unsupported value \"" + backend + "\" for system property " + BACKEND_PROPERTY + "; expected \"" + LIGHT + "\"." - ); + return LightWinRMService.createInstance(winRMEndpoint, timeout, ticketCache, authentications); } } diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index ad29726..1699c1d 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -12,9 +12,7 @@ The Windows Remote Management (WinRM) Java Client is a library that enables to: > **WinRM-over-HTTPS connections to hosts with self-signed or untrusted certificates will fail** > during the TLS handshake. To restore connectivity, either install the certificate into a Java > trust store or set `-Dorg.metricshub.winrm.tls.insecure=true` (insecure — for testing only). -> The client supports NTLM over HTTP/HTTPS and Kerberos (SPNEGO) over HTTPS. Setting -> `-Dorg.metricshub.winrm.backend=cxf` now fails with a clear error; remove the property (or stay -> on winrm-java 1.x). +> The client supports NTLM over HTTP/HTTPS and Kerberos (SPNEGO) over HTTPS. # How to run the WinRM Client inside Java diff --git a/src/test/java/org/metricshub/winrm/service/WinRMExecutorFactoryTest.java b/src/test/java/org/metricshub/winrm/service/WinRMExecutorFactoryTest.java index 29baec9..13083ff 100644 --- a/src/test/java/org/metricshub/winrm/service/WinRMExecutorFactoryTest.java +++ b/src/test/java/org/metricshub/winrm/service/WinRMExecutorFactoryTest.java @@ -3,10 +3,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.metricshub.winrm.WinRMHttpProtocolEnum; import org.metricshub.winrm.WindowsRemoteExecutor; @@ -14,21 +12,15 @@ import org.metricshub.winrm.light.LightWinRMService; import org.metricshub.winrm.service.client.auth.AuthenticationEnum; -/** Verifies backend selection and the light backend's capability guards (no network required). */ +/** Verifies executor creation and the client's capability guards (no network required). */ class WinRMExecutorFactoryTest { private static WinRMEndpoint endpoint(final WinRMHttpProtocolEnum protocol) { return new WinRMEndpoint(protocol, "testhost", null, "user", "pwd".toCharArray(), null); } - @AfterEach - void clearBackend() { - System.clearProperty(WinRMExecutorFactory.BACKEND_PROPERTY); - } - @Test - void lightBackendSelectedForHttpNtlm() throws Exception { - System.setProperty(WinRMExecutorFactory.BACKEND_PROPERTY, "light"); + void createsLightExecutorOverHttp() throws Exception { try ( final WindowsRemoteExecutor executor = WinRMExecutorFactory.createInstance( endpoint(WinRMHttpProtocolEnum.HTTP), @@ -42,55 +34,9 @@ void lightBackendSelectedForHttpNtlm() throws Exception { } @Test - void defaultBackendIsLight() throws Exception { - // No backend property set -> the dependency-free light backend. Building the client does not - // open a connection (that happens on the first operation), so this stays offline. - try ( - final WindowsRemoteExecutor executor = WinRMExecutorFactory.createInstance( - endpoint(WinRMHttpProtocolEnum.HTTP), - 30000L, - null, - List.of(AuthenticationEnum.NTLM) - )) { - assertInstanceOf(LightWinRMService.class, executor); - } - } - - @Test - void cxfBackendRejectedWithRemovalMessage() { - // The CXF backend was removed in 2.0.0. An operator who explicitly pinned it must get a clear - // error, not be silently switched to another implementation. - System.setProperty(WinRMExecutorFactory.BACKEND_PROPERTY, "cxf"); - final WinRMException e = assertThrows( - WinRMException.class, - () -> WinRMExecutorFactory.createInstance( - endpoint(WinRMHttpProtocolEnum.HTTP), - 30000L, - null, - List.of(AuthenticationEnum.NTLM) - ) - ); - assertTrue(e.getMessage().contains("removed in winrm-java 2.0.0"), e.getMessage()); - } - - @Test - void defaultBackendAcceptsHttps() throws Exception { - // Light now supports HTTPS (TLS + plaintext SOAP), so the default backend accepts it. Building - // the client does not open a connection (or a TLS handshake), so this stays offline. - try ( - final WindowsRemoteExecutor executor = WinRMExecutorFactory.createInstance( - endpoint(WinRMHttpProtocolEnum.HTTPS), - 30000L, - null, - List.of(AuthenticationEnum.NTLM) - )) { - assertInstanceOf(LightWinRMService.class, executor); - } - } - - @Test - void lightBackendAcceptsHttps() throws Exception { - System.setProperty(WinRMExecutorFactory.BACKEND_PROPERTY, "light"); + void createsLightExecutorOverHttps() throws Exception { + // The client supports HTTPS (TLS + plaintext SOAP). Building it does not open a connection + // (or a TLS handshake), so this stays offline. try ( final WindowsRemoteExecutor executor = WinRMExecutorFactory.createInstance( endpoint(WinRMHttpProtocolEnum.HTTPS), @@ -106,7 +52,6 @@ void lightBackendAcceptsHttps() throws Exception { void kerberosOnlyOverHttpRejected() { // Kerberos requires HTTPS (no message encryption over plain HTTP, matching CXF) and there is no // other scheme to fall back to, so a Kerberos-only request over HTTP is rejected. - System.setProperty(WinRMExecutorFactory.BACKEND_PROPERTY, "light"); assertThrows( WinRMException.class, () -> WinRMExecutorFactory.createInstance( @@ -122,7 +67,6 @@ void kerberosOnlyOverHttpRejected() { void mixedKerberosNtlmFallsBackToNtlmOverHttp() throws Exception { // Ordered fallback: [KERBEROS, NTLM] over HTTP cannot use Kerberos (HTTPS-only), so it falls back // to NTLM and constructs successfully. Building the client opens no connection, so this is offline. - System.setProperty(WinRMExecutorFactory.BACKEND_PROPERTY, "light"); try ( final WindowsRemoteExecutor executor = WinRMExecutorFactory.createInstance( endpoint(WinRMHttpProtocolEnum.HTTP), @@ -138,7 +82,6 @@ void mixedKerberosNtlmFallsBackToNtlmOverHttp() throws Exception { void kerberosOverHttpsAccepted() throws Exception { // Kerberos is supported over HTTPS; the login/handshake happen on the first operation, so // constructing the executor stays offline. - System.setProperty(WinRMExecutorFactory.BACKEND_PROPERTY, "light"); try ( final WindowsRemoteExecutor executor = WinRMExecutorFactory.createInstance( endpoint(WinRMHttpProtocolEnum.HTTPS), @@ -150,27 +93,10 @@ void kerberosOverHttpsAccepted() throws Exception { } } - @Test - void unsupportedBackendValueRejected() { - // A typo or unknown value must fail loudly instead of silently falling through to a backend the - // operator did not request. - System.setProperty(WinRMExecutorFactory.BACKEND_PROPERTY, "cxff"); - assertThrows( - WinRMException.class, - () -> WinRMExecutorFactory.createInstance( - endpoint(WinRMHttpProtocolEnum.HTTP), - 30000L, - null, - List.of(AuthenticationEnum.NTLM) - ) - ); - } - @Test void closedLightExecutorRejectsOperations() throws Exception { // close() must release the executor for good: a later operation is rejected, not silently served // by a fresh reconnect/handshake. - System.setProperty(WinRMExecutorFactory.BACKEND_PROPERTY, "light"); final WindowsRemoteExecutor executor = WinRMExecutorFactory.createInstance( endpoint(WinRMHttpProtocolEnum.HTTP), 30000L,