csutherl commented on code in PR #919:
URL: https://github.com/apache/tomcat/pull/919#discussion_r2528070046
##########
java/org/apache/catalina/util/ServerInfo.java:
##########
@@ -129,6 +138,175 @@ public static void main(String[] args) {
System.out.println("Architecture: " + System.getProperty("os.arch"));
System.out.println("JVM Version: " +
System.getProperty("java.runtime.version"));
System.out.println("JVM Vendor: " +
System.getProperty("java.vm.vendor"));
+
+ // Get CATALINA_HOME for library scanning (already displayed in
catalina script output preface)
+ String catalinaHome = System.getProperty("catalina.home");
+
+ // Display APR/Tomcat Native information if available
+ boolean aprLoaded = false;
+ try {
+ // Try to initialize APR by creating an instance and calling
isAprAvailable()
+ // Creating an instance sets the instance flag which allows
initialization
+ Class<?> aprLifecycleListenerClass =
Class.forName("org.apache.catalina.core.AprLifecycleListener");
+ aprLifecycleListenerClass.getConstructor().newInstance();
+ Boolean aprAvailable = (Boolean)
aprLifecycleListenerClass.getMethod("isAprAvailable").invoke(null);
+ if (aprAvailable != null && aprAvailable.booleanValue()) {
+ // APR is available, get version information using public
methods
+ String tcnVersion = (String)
aprLifecycleListenerClass.getMethod("getInstalledTcnVersion").invoke(null);
+ String aprVersion = (String)
aprLifecycleListenerClass.getMethod("getInstalledAprVersion").invoke(null);
+
+ System.out.println("APR loaded: true");
+ System.out.println("APR Version: " + aprVersion);
+ System.out.println("Tomcat Native: " + tcnVersion);
+ aprLoaded = true;
+
+ // Check if installed version is older than recommended
+ try {
+ String warning = (String)
aprLifecycleListenerClass.getMethod("getTcnVersionWarning").invoke(null);
+
+ if (warning != null) {
+ System.out.println(" " + warning);
+ }
+ } catch (Exception e) {
+ // Failed to check version - ignore
+ }
+
+ // Display OpenSSL version if available
+ try {
+ String openSSLVersion = (String)
aprLifecycleListenerClass.getMethod("getInstalledOpenSslVersion").invoke(null);
+
+ if (openSSLVersion != null && !openSSLVersion.isEmpty()) {
+ System.out.println("OpenSSL (APR): " +
openSSLVersion);
+ }
+ } catch (Exception e) {
+ // SSL not initialized or not available
+ }
+ }
+ } catch (ClassNotFoundException | NoClassDefFoundError e) {
+ // APR/Tomcat Native classes not available on classpath
+ } catch (Exception e) {
+ // Error checking APR status
+ }
+
+ if (!aprLoaded) {
+ System.out.println("APR loaded: false");
+ }
+
+ // Display FFM OpenSSL information if available
+ try {
+ // Try to initialize FFM OpenSSL by creating an instance and
calling isAvailable()
+ // Creating an instance sets the instance flag which allows
initialization
+ Class<?> openSSLLifecycleListenerClass =
Class.forName("org.apache.catalina.core.OpenSSLLifecycleListener");
+ openSSLLifecycleListenerClass.getConstructor().newInstance();
+ Boolean ffmAvailable = (Boolean)
openSSLLifecycleListenerClass.getMethod("isAvailable").invoke(null);
+
+ if (ffmAvailable != null && ffmAvailable.booleanValue()) {
+ // FFM OpenSSL is available, get version information using
public method
+ String versionString = (String)
openSSLLifecycleListenerClass.getMethod("getInstalledOpenSslVersion").invoke(null);
+
+ if (versionString != null && !versionString.isEmpty()) {
+ System.out.println("OpenSSL (FFM): " + versionString);
+ }
+ }
+ } catch (ClassNotFoundException | NoClassDefFoundError e) {
+ // FFM OpenSSL classes not available on classpath
+ } catch (Exception e) {
+ // Error checking FFM OpenSSL status
+ }
+
+ // Display third-party libraries in CATALINA_HOME/lib
+ if (catalinaHome != null) {
+ File libDir = new File(catalinaHome, "lib");
+ if (libDir.exists() && libDir.isDirectory()) {
+ File[] allJars = libDir.listFiles((dir, name) ->
name.endsWith(".jar"));
+
+ if (allJars != null && allJars.length > 0) {
+ // First pass: collect third-party JARs and find longest
name
+ List<File> thirdPartyJars = new ArrayList<>();
+ int maxNameLength = 0;
+ for (File jar : allJars) {
+ if (!isTomcatCoreJar(jar)) {
+ thirdPartyJars.add(jar);
+ maxNameLength = Math.max(maxNameLength,
jar.getName().length());
+ }
+ }
+
+ // Second pass: print with aligned formatting
+ if (!thirdPartyJars.isEmpty()) {
+ System.out.println();
+ System.out.println("Third-party libraries:");
+ for (File jar : thirdPartyJars) {
+ String version = getJarVersion(jar);
+ String jarName = jar.getName();
+ // Colon right after name, then pad to align
version numbers
+ String nameWithColon = jarName + ":";
+ String paddedName = String.format("%-" +
(maxNameLength + 1) + "s", nameWithColon);
+ if (version != null) {
+ System.out.println(" " + paddedName + " " +
version);
+ } else {
+ System.out.println(" " + paddedName + "
(unknown)");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean isTomcatCoreJar(File jarFile) {
+ try (JarFile jar = new JarFile(jarFile)) {
+ Manifest manifest = jar.getManifest();
+
+ if (manifest != null) {
+ // Check Bundle-SymbolicName to identify Tomcat core JARs
+ String bundleName =
manifest.getMainAttributes().getValue("Bundle-SymbolicName");
+ if (bundleName != null) {
+ // Tomcat core JARs have Bundle-SymbolicName starting with
org.apache.tomcat,
+ // org.apache.catalina, or jakarta.
+ if (bundleName.startsWith("org.apache.tomcat") ||
+ bundleName.startsWith("org.apache.catalina") ||
+ bundleName.startsWith("jakarta.")) {
+ return true;
+ }
+ }
+
+ // Fallback: Check Implementation-Vendor and
Implementation-Title
+ String implVendor =
manifest.getMainAttributes().getValue("Implementation-Vendor");
+ String implTitle =
manifest.getMainAttributes().getValue("Implementation-Title");
+
+ if ("Apache Software Foundation".equals(implVendor) && "Apache
Tomcat".equals(implTitle)) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ // Ignore errors reading JAR manifest
+ }
+
+ return false;
+ }
+
+ private static String getJarVersion(File jarFile) {
Review Comment:
That's better.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]