From a179b762e73fafcabfef57f5ab2b187636cc276f Mon Sep 17 00:00:00 2001 From: Onkar Date: Tue, 26 May 2026 10:13:03 +0530 Subject: [PATCH 1/2] Add summary data model classes Introduces JwsInstallation as the root model for a discovered Tomcat installation, along with supporting value objects: JvmInfo, OsInfo, ContainerInfo (with ContainerType enum), and NativeInfo. All models are immutable (builder pattern), null-safe, and annotated for Jackson JSON serialization. Path fields use ToStringSerializer so they render as plain strings in JSON output. --- .../jws/diag/summary/model/ContainerInfo.java | 57 ++++++ .../jws/diag/summary/model/ContainerType.java | 25 +++ .../jboss/jws/diag/summary/model/JvmInfo.java | 89 ++++++++++ .../diag/summary/model/JwsInstallation.java | 165 ++++++++++++++++++ .../jws/diag/summary/model/NativeInfo.java | 71 ++++++++ .../jboss/jws/diag/summary/model/OsInfo.java | 70 ++++++++ 6 files changed, 477 insertions(+) create mode 100644 src/main/java/org/jboss/jws/diag/summary/model/ContainerInfo.java create mode 100644 src/main/java/org/jboss/jws/diag/summary/model/ContainerType.java create mode 100644 src/main/java/org/jboss/jws/diag/summary/model/JvmInfo.java create mode 100644 src/main/java/org/jboss/jws/diag/summary/model/JwsInstallation.java create mode 100644 src/main/java/org/jboss/jws/diag/summary/model/NativeInfo.java create mode 100644 src/main/java/org/jboss/jws/diag/summary/model/OsInfo.java diff --git a/src/main/java/org/jboss/jws/diag/summary/model/ContainerInfo.java b/src/main/java/org/jboss/jws/diag/summary/model/ContainerInfo.java new file mode 100644 index 0000000..189b83b --- /dev/null +++ b/src/main/java/org/jboss/jws/diag/summary/model/ContainerInfo.java @@ -0,0 +1,57 @@ +package org.jboss.jws.diag.summary.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Container runtime detected for the running Tomcat process. + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public final class ContainerInfo { + + private final ContainerType type; + private final String detectionMethod; + + private ContainerInfo(Builder builder) { + this.type = builder.type; + this.detectionMethod = builder.detectionMethod; + } + + @JsonProperty("type") + public ContainerType getType() { + return type; + } + + @JsonProperty("detectionMethod") + public String getDetectionMethod() { + return detectionMethod; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private ContainerType type; + private String detectionMethod; + + public Builder type(ContainerType type) { + this.type = type; + return this; + } + + public Builder detectionMethod(String detectionMethod) { + this.detectionMethod = detectionMethod; + return this; + } + + public ContainerInfo build() { + return new ContainerInfo(this); + } + } + + @Override + public String toString() { + return "ContainerInfo{type=" + type + ", detectionMethod='" + detectionMethod + "'}"; + } +} diff --git a/src/main/java/org/jboss/jws/diag/summary/model/ContainerType.java b/src/main/java/org/jboss/jws/diag/summary/model/ContainerType.java new file mode 100644 index 0000000..6574e45 --- /dev/null +++ b/src/main/java/org/jboss/jws/diag/summary/model/ContainerType.java @@ -0,0 +1,25 @@ +package org.jboss.jws.diag.summary.model; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Container runtime in which the Tomcat process is running. + */ +public enum ContainerType { + + DOCKER("docker"), + PODMAN("podman"), + KUBERNETES("kubernetes"), + BARE_METAL("bare_metal"); + + private final String value; + + ContainerType(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/org/jboss/jws/diag/summary/model/JvmInfo.java b/src/main/java/org/jboss/jws/diag/summary/model/JvmInfo.java new file mode 100644 index 0000000..1aae634 --- /dev/null +++ b/src/main/java/org/jboss/jws/diag/summary/model/JvmInfo.java @@ -0,0 +1,89 @@ +package org.jboss.jws.diag.summary.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Collections; +import java.util.List; + +/** + * JVM information collected from system properties and the running process. + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public final class JvmInfo { + + private final String version; + private final String vendor; + private final String javaHome; + private final List jvmArgs; + + private JvmInfo(Builder builder) { + this.version = builder.version; + this.vendor = builder.vendor; + this.javaHome = builder.javaHome; + this.jvmArgs = builder.jvmArgs != null + ? Collections.unmodifiableList(builder.jvmArgs) + : null; + } + + @JsonProperty("version") + public String getVersion() { + return version; + } + + @JsonProperty("vendor") + public String getVendor() { + return vendor; + } + + @JsonProperty("javaHome") + public String getJavaHome() { + return javaHome; + } + + @JsonProperty("jvmArgs") + public List getJvmArgs() { + return jvmArgs; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private String version; + private String vendor; + private String javaHome; + private List jvmArgs; + + public Builder version(String version) { + this.version = version; + return this; + } + + public Builder vendor(String vendor) { + this.vendor = vendor; + return this; + } + + public Builder javaHome(String javaHome) { + this.javaHome = javaHome; + return this; + } + + public Builder jvmArgs(List jvmArgs) { + this.jvmArgs = jvmArgs; + return this; + } + + public JvmInfo build() { + return new JvmInfo(this); + } + } + + @Override + public String toString() { + return "JvmInfo{version='" + version + "', vendor='" + vendor + + "', javaHome='" + javaHome + "', jvmArgs=" + jvmArgs + '}'; + } +} diff --git a/src/main/java/org/jboss/jws/diag/summary/model/JwsInstallation.java b/src/main/java/org/jboss/jws/diag/summary/model/JwsInstallation.java new file mode 100644 index 0000000..681ad3b --- /dev/null +++ b/src/main/java/org/jboss/jws/diag/summary/model/JwsInstallation.java @@ -0,0 +1,165 @@ +package org.jboss.jws.diag.summary.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.nio.file.Path; + +/** + * Root model representing a discovered JBoss Web Server / Apache Tomcat installation. + * All fields are optional; discovery may populate a subset depending on what is detectable. + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public final class JwsInstallation { + + private final Path catalinaHome; + private final Path catalinaBase; + private final String tomcatVersion; + private final String jwsVersion; + private final JvmInfo jvmInfo; + private final OsInfo osInfo; + private final ContainerInfo containerInfo; + private final NativeInfo nativeInfo; + private final Integer pid; + + private JwsInstallation(Builder builder) { + this.catalinaHome = builder.catalinaHome; + this.catalinaBase = builder.catalinaBase; + this.tomcatVersion = builder.tomcatVersion; + this.jwsVersion = builder.jwsVersion; + this.jvmInfo = builder.jvmInfo; + this.osInfo = builder.osInfo; + this.containerInfo = builder.containerInfo; + this.nativeInfo = builder.nativeInfo; + this.pid = builder.pid; + } + + @JsonSerialize(using = ToStringSerializer.class) + @JsonProperty("catalinaHome") + public Path getCatalinaHome() { + return catalinaHome; + } + + @JsonSerialize(using = ToStringSerializer.class) + @JsonProperty("catalinaBase") + public Path getCatalinaBase() { + return catalinaBase; + } + + @JsonProperty("tomcatVersion") + public String getTomcatVersion() { + return tomcatVersion; + } + + @JsonProperty("jwsVersion") + public String getJwsVersion() { + return jwsVersion; + } + + @JsonProperty("jvmInfo") + public JvmInfo getJvmInfo() { + return jvmInfo; + } + + @JsonProperty("osInfo") + public OsInfo getOsInfo() { + return osInfo; + } + + @JsonProperty("containerInfo") + public ContainerInfo getContainerInfo() { + return containerInfo; + } + + @JsonProperty("nativeInfo") + public NativeInfo getNativeInfo() { + return nativeInfo; + } + + @JsonProperty("pid") + public Integer getPid() { + return pid; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private Path catalinaHome; + private Path catalinaBase; + private String tomcatVersion; + private String jwsVersion; + private JvmInfo jvmInfo; + private OsInfo osInfo; + private ContainerInfo containerInfo; + private NativeInfo nativeInfo; + private Integer pid; + + public Builder catalinaHome(Path catalinaHome) { + this.catalinaHome = catalinaHome; + return this; + } + + public Builder catalinaBase(Path catalinaBase) { + this.catalinaBase = catalinaBase; + return this; + } + + public Builder tomcatVersion(String tomcatVersion) { + this.tomcatVersion = tomcatVersion; + return this; + } + + public Builder jwsVersion(String jwsVersion) { + this.jwsVersion = jwsVersion; + return this; + } + + public Builder jvmInfo(JvmInfo jvmInfo) { + this.jvmInfo = jvmInfo; + return this; + } + + public Builder osInfo(OsInfo osInfo) { + this.osInfo = osInfo; + return this; + } + + public Builder containerInfo(ContainerInfo containerInfo) { + this.containerInfo = containerInfo; + return this; + } + + public Builder nativeInfo(NativeInfo nativeInfo) { + this.nativeInfo = nativeInfo; + return this; + } + + public Builder pid(Integer pid) { + this.pid = pid; + return this; + } + + public JwsInstallation build() { + return new JwsInstallation(this); + } + } + + @Override + public String toString() { + return "JwsInstallation{" + + "catalinaHome=" + catalinaHome + + ", catalinaBase=" + catalinaBase + + ", tomcatVersion='" + tomcatVersion + '\'' + + ", jwsVersion='" + jwsVersion + '\'' + + ", pid=" + pid + + ", jvmInfo=" + jvmInfo + + ", osInfo=" + osInfo + + ", containerInfo=" + containerInfo + + ", nativeInfo=" + nativeInfo + + '}'; + } +} diff --git a/src/main/java/org/jboss/jws/diag/summary/model/NativeInfo.java b/src/main/java/org/jboss/jws/diag/summary/model/NativeInfo.java new file mode 100644 index 0000000..8777d91 --- /dev/null +++ b/src/main/java/org/jboss/jws/diag/summary/model/NativeInfo.java @@ -0,0 +1,71 @@ +package org.jboss.jws.diag.summary.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Information about native libraries (APR, OpenSSL) loaded by Tomcat. + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public final class NativeInfo { + + private final String aprVersion; + private final String opensslVersion; + private final boolean loaded; + + private NativeInfo(Builder builder) { + this.aprVersion = builder.aprVersion; + this.opensslVersion = builder.opensslVersion; + this.loaded = builder.loaded; + } + + @JsonProperty("aprVersion") + public String getAprVersion() { + return aprVersion; + } + + @JsonProperty("opensslVersion") + public String getOpensslVersion() { + return opensslVersion; + } + + @JsonProperty("loaded") + public boolean isLoaded() { + return loaded; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private String aprVersion; + private String opensslVersion; + private boolean loaded; + + public Builder aprVersion(String aprVersion) { + this.aprVersion = aprVersion; + return this; + } + + public Builder opensslVersion(String opensslVersion) { + this.opensslVersion = opensslVersion; + return this; + } + + public Builder loaded(boolean loaded) { + this.loaded = loaded; + return this; + } + + public NativeInfo build() { + return new NativeInfo(this); + } + } + + @Override + public String toString() { + return "NativeInfo{aprVersion='" + aprVersion + "', opensslVersion='" + opensslVersion + + "', loaded=" + loaded + '}'; + } +} diff --git a/src/main/java/org/jboss/jws/diag/summary/model/OsInfo.java b/src/main/java/org/jboss/jws/diag/summary/model/OsInfo.java new file mode 100644 index 0000000..c9b82bb --- /dev/null +++ b/src/main/java/org/jboss/jws/diag/summary/model/OsInfo.java @@ -0,0 +1,70 @@ +package org.jboss.jws.diag.summary.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Operating system information collected from {@code /etc/os-release} or system properties. + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public final class OsInfo { + + private final String name; + private final String version; + private final String arch; + + private OsInfo(Builder builder) { + this.name = builder.name; + this.version = builder.version; + this.arch = builder.arch; + } + + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("version") + public String getVersion() { + return version; + } + + @JsonProperty("arch") + public String getArch() { + return arch; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private String name; + private String version; + private String arch; + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder version(String version) { + this.version = version; + return this; + } + + public Builder arch(String arch) { + this.arch = arch; + return this; + } + + public OsInfo build() { + return new OsInfo(this); + } + } + + @Override + public String toString() { + return "OsInfo{name='" + name + "', version='" + version + "', arch='" + arch + "'}"; + } +} From 74276bc192277c535a3eb11217a5801c76cb4583 Mon Sep 17 00:00:00 2001 From: Onkar Date: Wed, 27 May 2026 00:33:46 +0530 Subject: [PATCH 2/2] Address review feedback on summary data model classes and Added tests. --- .../jws/diag/summary/model/ContainerInfo.java | 3 - .../jboss/jws/diag/summary/model/JvmInfo.java | 24 +-- .../diag/summary/model/JwsInstallation.java | 34 ++-- .../jws/diag/summary/model/NativeInfo.java | 12 +- .../jboss/jws/diag/summary/model/OsInfo.java | 4 - .../model/JwsInstallationModelTest.java | 163 ++++++++++++++++++ 6 files changed, 203 insertions(+), 37 deletions(-) create mode 100644 src/test/java/org/jboss/jws/diag/summary/model/JwsInstallationModelTest.java diff --git a/src/main/java/org/jboss/jws/diag/summary/model/ContainerInfo.java b/src/main/java/org/jboss/jws/diag/summary/model/ContainerInfo.java index 189b83b..e9c15c5 100644 --- a/src/main/java/org/jboss/jws/diag/summary/model/ContainerInfo.java +++ b/src/main/java/org/jboss/jws/diag/summary/model/ContainerInfo.java @@ -1,7 +1,6 @@ package org.jboss.jws.diag.summary.model; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; /** * Container runtime detected for the running Tomcat process. @@ -17,12 +16,10 @@ private ContainerInfo(Builder builder) { this.detectionMethod = builder.detectionMethod; } - @JsonProperty("type") public ContainerType getType() { return type; } - @JsonProperty("detectionMethod") public String getDetectionMethod() { return detectionMethod; } diff --git a/src/main/java/org/jboss/jws/diag/summary/model/JvmInfo.java b/src/main/java/org/jboss/jws/diag/summary/model/JvmInfo.java index 1aae634..7237719 100644 --- a/src/main/java/org/jboss/jws/diag/summary/model/JvmInfo.java +++ b/src/main/java/org/jboss/jws/diag/summary/model/JvmInfo.java @@ -1,8 +1,10 @@ package org.jboss.jws.diag.summary.model; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -14,7 +16,12 @@ public final class JvmInfo { private final String version; private final String vendor; - private final String javaHome; + private final Path javaHome; + /** + * JVM args as seen in {@code /proc//cmdline}. Callers must redact sensitive + * {@code -D} flags (e.g. {@code -Djavax.net.ssl.keyStorePassword}) before passing + * this list to the builder. + */ private final List jvmArgs; private JvmInfo(Builder builder) { @@ -26,22 +33,19 @@ private JvmInfo(Builder builder) { : null; } - @JsonProperty("version") public String getVersion() { return version; } - @JsonProperty("vendor") public String getVendor() { return vendor; } - @JsonProperty("javaHome") - public String getJavaHome() { + @JsonSerialize(using = ToStringSerializer.class) + public Path getJavaHome() { return javaHome; } - @JsonProperty("jvmArgs") public List getJvmArgs() { return jvmArgs; } @@ -53,7 +57,7 @@ public static Builder builder() { public static final class Builder { private String version; private String vendor; - private String javaHome; + private Path javaHome; private List jvmArgs; public Builder version(String version) { @@ -66,7 +70,7 @@ public Builder vendor(String vendor) { return this; } - public Builder javaHome(String javaHome) { + public Builder javaHome(Path javaHome) { this.javaHome = javaHome; return this; } @@ -84,6 +88,6 @@ public JvmInfo build() { @Override public String toString() { return "JvmInfo{version='" + version + "', vendor='" + vendor - + "', javaHome='" + javaHome + "', jvmArgs=" + jvmArgs + '}'; + + "', javaHome=" + javaHome + ", jvmArgs=" + jvmArgs + '}'; } } diff --git a/src/main/java/org/jboss/jws/diag/summary/model/JwsInstallation.java b/src/main/java/org/jboss/jws/diag/summary/model/JwsInstallation.java index 681ad3b..52e78c7 100644 --- a/src/main/java/org/jboss/jws/diag/summary/model/JwsInstallation.java +++ b/src/main/java/org/jboss/jws/diag/summary/model/JwsInstallation.java @@ -1,19 +1,21 @@ package org.jboss.jws.diag.summary.model; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import java.nio.file.Path; /** * Root model representing a discovered JBoss Web Server / Apache Tomcat installation. - * All fields are optional; discovery may populate a subset depending on what is detectable. + * All fields except {@code schemaVersion} are optional; discovery may populate a subset + * depending on what is detectable in the environment. */ @JsonInclude(JsonInclude.Include.NON_NULL) public final class JwsInstallation { + private static final String SCHEMA_VERSION = "1.0"; + private final Path catalinaHome; private final Path catalinaBase; private final String tomcatVersion; @@ -23,6 +25,7 @@ public final class JwsInstallation { private final ContainerInfo containerInfo; private final NativeInfo nativeInfo; private final Integer pid; + private final String uptime; private JwsInstallation(Builder builder) { this.catalinaHome = builder.catalinaHome; @@ -34,55 +37,55 @@ private JwsInstallation(Builder builder) { this.containerInfo = builder.containerInfo; this.nativeInfo = builder.nativeInfo; this.pid = builder.pid; + this.uptime = builder.uptime; + } + + public String getSchemaVersion() { + return SCHEMA_VERSION; } @JsonSerialize(using = ToStringSerializer.class) - @JsonProperty("catalinaHome") public Path getCatalinaHome() { return catalinaHome; } @JsonSerialize(using = ToStringSerializer.class) - @JsonProperty("catalinaBase") public Path getCatalinaBase() { return catalinaBase; } - @JsonProperty("tomcatVersion") public String getTomcatVersion() { return tomcatVersion; } - @JsonProperty("jwsVersion") public String getJwsVersion() { return jwsVersion; } - @JsonProperty("jvmInfo") public JvmInfo getJvmInfo() { return jvmInfo; } - @JsonProperty("osInfo") public OsInfo getOsInfo() { return osInfo; } - @JsonProperty("containerInfo") public ContainerInfo getContainerInfo() { return containerInfo; } - @JsonProperty("nativeInfo") public NativeInfo getNativeInfo() { return nativeInfo; } - @JsonProperty("pid") public Integer getPid() { return pid; } + public String getUptime() { + return uptime; + } + public static Builder builder() { return new Builder(); } @@ -97,6 +100,7 @@ public static final class Builder { private ContainerInfo containerInfo; private NativeInfo nativeInfo; private Integer pid; + private String uptime; public Builder catalinaHome(Path catalinaHome) { this.catalinaHome = catalinaHome; @@ -143,6 +147,11 @@ public Builder pid(Integer pid) { return this; } + public Builder uptime(String uptime) { + this.uptime = uptime; + return this; + } + public JwsInstallation build() { return new JwsInstallation(this); } @@ -156,6 +165,7 @@ public String toString() { + ", tomcatVersion='" + tomcatVersion + '\'' + ", jwsVersion='" + jwsVersion + '\'' + ", pid=" + pid + + ", uptime='" + uptime + '\'' + ", jvmInfo=" + jvmInfo + ", osInfo=" + osInfo + ", containerInfo=" + containerInfo diff --git a/src/main/java/org/jboss/jws/diag/summary/model/NativeInfo.java b/src/main/java/org/jboss/jws/diag/summary/model/NativeInfo.java index 8777d91..0fec2f7 100644 --- a/src/main/java/org/jboss/jws/diag/summary/model/NativeInfo.java +++ b/src/main/java/org/jboss/jws/diag/summary/model/NativeInfo.java @@ -1,7 +1,6 @@ package org.jboss.jws.diag.summary.model; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; /** * Information about native libraries (APR, OpenSSL) loaded by Tomcat. @@ -11,7 +10,7 @@ public final class NativeInfo { private final String aprVersion; private final String opensslVersion; - private final boolean loaded; + private final Boolean loaded; private NativeInfo(Builder builder) { this.aprVersion = builder.aprVersion; @@ -19,18 +18,15 @@ private NativeInfo(Builder builder) { this.loaded = builder.loaded; } - @JsonProperty("aprVersion") public String getAprVersion() { return aprVersion; } - @JsonProperty("opensslVersion") public String getOpensslVersion() { return opensslVersion; } - @JsonProperty("loaded") - public boolean isLoaded() { + public Boolean isLoaded() { return loaded; } @@ -41,7 +37,7 @@ public static Builder builder() { public static final class Builder { private String aprVersion; private String opensslVersion; - private boolean loaded; + private Boolean loaded; public Builder aprVersion(String aprVersion) { this.aprVersion = aprVersion; @@ -53,7 +49,7 @@ public Builder opensslVersion(String opensslVersion) { return this; } - public Builder loaded(boolean loaded) { + public Builder loaded(Boolean loaded) { this.loaded = loaded; return this; } diff --git a/src/main/java/org/jboss/jws/diag/summary/model/OsInfo.java b/src/main/java/org/jboss/jws/diag/summary/model/OsInfo.java index c9b82bb..aa1bc54 100644 --- a/src/main/java/org/jboss/jws/diag/summary/model/OsInfo.java +++ b/src/main/java/org/jboss/jws/diag/summary/model/OsInfo.java @@ -1,7 +1,6 @@ package org.jboss.jws.diag.summary.model; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; /** * Operating system information collected from {@code /etc/os-release} or system properties. @@ -19,17 +18,14 @@ private OsInfo(Builder builder) { this.arch = builder.arch; } - @JsonProperty("name") public String getName() { return name; } - @JsonProperty("version") public String getVersion() { return version; } - @JsonProperty("arch") public String getArch() { return arch; } diff --git a/src/test/java/org/jboss/jws/diag/summary/model/JwsInstallationModelTest.java b/src/test/java/org/jboss/jws/diag/summary/model/JwsInstallationModelTest.java new file mode 100644 index 0000000..a4550c6 --- /dev/null +++ b/src/test/java/org/jboss/jws/diag/summary/model/JwsInstallationModelTest.java @@ -0,0 +1,163 @@ +package org.jboss.jws.diag.summary.model; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class JwsInstallationModelTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + // --- JwsInstallation --- + + @Test + void schemaVersionIsAlways10() throws Exception { + JwsInstallation inst = JwsInstallation.builder().build(); + JsonNode json = mapper.valueToTree(inst); + assertThat(json.get("schemaVersion").asText()).isEqualTo("1.0"); + } + + @Test + void nullFieldsAreExcludedFromJson() throws Exception { + JwsInstallation inst = JwsInstallation.builder() + .tomcatVersion("10.1.49") + .build(); + JsonNode json = mapper.valueToTree(inst); + assertThat(json.has("catalinaHome")).isFalse(); + assertThat(json.has("catalinaBase")).isFalse(); + assertThat(json.has("jwsVersion")).isFalse(); + assertThat(json.has("pid")).isFalse(); + assertThat(json.has("uptime")).isFalse(); + assertThat(json.get("tomcatVersion").asText()).isEqualTo("10.1.49"); + } + + @Test + void pathFieldsSerializeAsPlainStrings() throws Exception { + Path home = Paths.get("/opt/tomcat"); + Path base = Paths.get("/opt/tomcat/conf"); + JwsInstallation inst = JwsInstallation.builder() + .catalinaHome(home) + .catalinaBase(base) + .build(); + JsonNode json = mapper.valueToTree(inst); + assertThat(json.get("catalinaHome").asText()).isEqualTo("/opt/tomcat"); + assertThat(json.get("catalinaBase").asText()).isEqualTo("/opt/tomcat/conf"); + } + + @Test + void builderPopulatesAllFields() { + JvmInfo jvm = JvmInfo.builder().version("17.0.10").build(); + OsInfo os = OsInfo.builder().name("RHEL").version("9.3").arch("x86_64").build(); + ContainerInfo container = ContainerInfo.builder() + .type(ContainerType.PODMAN) + .detectionMethod("/run/.containerenv") + .build(); + NativeInfo native_ = NativeInfo.builder() + .aprVersion("1.7.2") + .opensslVersion("3.0.9") + .loaded(true) + .build(); + + JwsInstallation inst = JwsInstallation.builder() + .catalinaHome(Paths.get("/opt/tomcat")) + .catalinaBase(Paths.get("/etc/tomcat")) + .tomcatVersion("10.1.49") + .jwsVersion("6.1.0") + .jvmInfo(jvm) + .osInfo(os) + .containerInfo(container) + .nativeInfo(native_) + .pid(12345) + .uptime("2d 4h") + .build(); + + assertThat(inst.getTomcatVersion()).isEqualTo("10.1.49"); + assertThat(inst.getJwsVersion()).isEqualTo("6.1.0"); + assertThat(inst.getPid()).isEqualTo(12345); + assertThat(inst.getUptime()).isEqualTo("2d 4h"); + assertThat(inst.getJvmInfo()).isSameAs(jvm); + assertThat(inst.getOsInfo()).isSameAs(os); + assertThat(inst.getContainerInfo()).isSameAs(container); + assertThat(inst.getNativeInfo()).isSameAs(native_); + } + + // --- JvmInfo --- + + @Test + void jvmInfoJavaHomeSerializesAsString() throws Exception { + Path javaHome = Paths.get("/usr/lib/jvm/java-17"); + JvmInfo jvm = JvmInfo.builder() + .version("17.0.10") + .vendor("Red Hat") + .javaHome(javaHome) + .build(); + JsonNode json = mapper.valueToTree(jvm); + assertThat(json.get("javaHome").asText()).isEqualTo("/usr/lib/jvm/java-17"); + } + + @Test + void jvmInfoNullFieldsExcluded() throws Exception { + JvmInfo jvm = JvmInfo.builder().version("17.0.10").build(); + JsonNode json = mapper.valueToTree(jvm); + assertThat(json.has("vendor")).isFalse(); + assertThat(json.has("javaHome")).isFalse(); + assertThat(json.has("jvmArgs")).isFalse(); + } + + @Test + void jvmArgsListIsImmutable() { + List args = Arrays.asList("-Xmx512m", "-Xms256m"); + JvmInfo jvm = JvmInfo.builder().jvmArgs(args).build(); + assertThat(jvm.getJvmArgs()).containsExactly("-Xmx512m", "-Xms256m"); + } + + // --- NativeInfo --- + + @Test + void nativeInfoLoadedNullIsExcludedFromJson() throws Exception { + NativeInfo native_ = NativeInfo.builder() + .aprVersion("1.7.2") + .build(); + assertThat(native_.isLoaded()).isNull(); + JsonNode json = mapper.valueToTree(native_); + assertThat(json.has("loaded")).isFalse(); + } + + @Test + void nativeInfoLoadedFalseIsIncludedInJson() throws Exception { + NativeInfo native_ = NativeInfo.builder().loaded(false).build(); + JsonNode json = mapper.valueToTree(native_); + assertThat(json.get("loaded").asBoolean()).isFalse(); + } + + // --- OsInfo --- + + @Test + void osInfoBuilderAndSerialization() throws Exception { + OsInfo os = OsInfo.builder().name("RHEL").version("9.3").arch("x86_64").build(); + JsonNode json = mapper.valueToTree(os); + assertThat(json.get("name").asText()).isEqualTo("RHEL"); + assertThat(json.get("version").asText()).isEqualTo("9.3"); + assertThat(json.get("arch").asText()).isEqualTo("x86_64"); + } + + // --- ContainerInfo --- + + @Test + void containerInfoEnumSerializesAsLowercaseString() throws Exception { + ContainerInfo info = ContainerInfo.builder() + .type(ContainerType.DOCKER) + .detectionMethod("/.dockerenv") + .build(); + JsonNode json = mapper.valueToTree(info); + assertThat(json.get("type").asText()).isEqualTo("docker"); + assertThat(json.get("detectionMethod").asText()).isEqualTo("/.dockerenv"); + } +}