package com.atlassian.confluence.admin.actions; import com.atlassian.config.db.HibernateConfig; import com.atlassian.confluence.cluster.NodeStatus; import com.atlassian.confluence.core.Administrative; import com.atlassian.confluence.core.ConfluenceActionSupport; import com.atlassian.confluence.setup.BootstrapManager; import com.atlassian.confluence.setup.BootstrapUtils; import com.atlassian.confluence.util.GeneralUtil; import com.atlassian.core.util.DateUtils; import com.atlassian.plugin.PluginManager; import com.atlassian.spring.container.ComponentNotFoundException; import com.atlassian.spring.container.ContainerManager; import com.opensymphony.module.sitemesh.util.Container; import com.opensymphony.webwork.ServletActionContext; import org.apache.commons.collections.SequencedHashMap; import javax.servlet.ServletContext; import java.sql.Driver; import java.sql.DriverManager; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; public class ViewSystemInfoAction extends ConfluenceActionSupport implements Administrative, NodeStatus { Properties sysProps = System.getProperties(); Runtime rt = Runtime.getRuntime(); Map props = new SequencedHashMap(); DateFormat dateFormatter = new SimpleDateFormat("EEEEE, dd MMM yyyy"); DateFormat timeFormatter = new SimpleDateFormat("HH:mm:ss"); static final long MEGABYTE = 1048576; private ServletContext servletContext; private HibernateConfig hibernateConfig; private Map buildstats; private boolean gc = false; /** * Keep the blank constructor so WebWork can construct the action */ public ViewSystemInfoAction() { } public String execute() throws Exception { if (gc) { System.gc(); Thread.sleep(500); } return super.execute(); } public void setHibernateConfig(HibernateConfig hibernateConfig) { this.hibernateConfig = hibernateConfig; } /** * This constructor is used by the error page (500page.jsp) to create a new action after the ActionContext has been reset. */ public ViewSystemInfoAction(ServletContext servletContext) { this.servletContext = servletContext; } public ServletContext getServletContext() { if (servletContext != null) return servletContext; else return ServletActionContext.getServletContext(); } public Map getProps() { props.put("system.date", dateFormatter.format(new Date())); props.put("system.time", timeFormatter.format(new Date())); props.put("system.favourite.colour", "Claret"); props.put("java.version", sysProps.getProperty("java.version")); props.put("java.vendor", sysProps.getProperty("java.vendor")); props.put("jvm.version", sysProps.getProperty("java.vm.specification.version")); props.put("jvm.vendor", sysProps.getProperty("java.vm.specification.vendor")); props.put("jvm.implementation.version", sysProps.getProperty("java.vm.version")); props.put("java.runtime", sysProps.getProperty("java.runtime.name")); props.put("java.vm", sysProps.getProperty("java.vm.name")); props.put("CSP-7323", "proxy parameters follow"); props.put("http.proxyHost", sysProps.getProperty("http.proxyHost")); props.put("http.proxyPort", sysProps.getProperty("http.proxyPort")); props.put("user.name.word", sysProps.getProperty("user.name")); props.put("user.timezone", sysProps.getProperty("user.timezone")); props.put("operating.system", sysProps.getProperty("os.name") + " " + sysProps.getProperty("os.version")); props.put("os.architecture", sysProps.getProperty("os.arch")); props.put("fs.encoding", sysProps.getProperty("file.encoding")); return props; } public Map getJVMstats() { Map jvmstats = new SequencedHashMap(); jvmstats.put("total.memory", "" + getTotalMemory()); jvmstats.put("free.memory", "" + getFreeMemory()); jvmstats.put("used.memory", "" + getUsedMemory()); return jvmstats; } public Map getBuildStats() { if (buildstats == null) { buildstats = new SequencedHashMap(); BootstrapManager setup = BootstrapUtils.getBootstrapManager(); if (setup != null) buildstats.put("confluence.home", setup.getConfluenceHome()); else buildstats.put("confluence.home", "Unknown?"); buildstats.put("system.uptime", getUptime()); buildstats.put("system.version", GeneralUtil.getVersionNumber()); buildstats.put("build.number", GeneralUtil.getBuildNumber()); if (isDevMode()) buildstats.put("developer.mode", "Enabled"); } return buildstats; } // CONF-5212 public String getDatabaseURL() { BootstrapManager setup = BootstrapUtils.getBootstrapManager(); if (setup == null || (hibernateConfig != null && !hibernateConfig.isHibernateSetup())) return "Could not retrieve JDBC connection URL or datasource"; String databaseUrl; // First try the normal connection URL databaseUrl = setup.getString("hibernate.connection.url"); // Try a datasource if there's no connection URL if (databaseUrl == null) databaseUrl = setup.getString("hibernate.connection.datasource"); // If we can't find either, show a message if (databaseUrl == null) databaseUrl = "Could not retrieve JDBC connection URL or datasource"; return databaseUrl; } public String getDatabaseDialect() { BootstrapManager setup = BootstrapUtils.getBootstrapManager(); if (setup == null || (hibernateConfig != null && !hibernateConfig.isHibernateSetup())) { return "N/A"; } else { return setup.getString("hibernate.dialect"); } } /** * Retrieves the class name of the database driver * * @return Returns the class name as a String, or "N/A" if it was unable to be retrieved */ public String getDatabaseDriverName() { BootstrapManager setup = BootstrapUtils.getBootstrapManager(); if (setup == null || (hibernateConfig != null && !hibernateConfig.isHibernateSetup())) { return "N/A"; } else { String driverClass = setup.getString("hibernate.connection.driver_class"); if (driverClass == null) { return "N/A"; } else { return driverClass; } } } /** * Retrieves the version of the database driver, in the form "MAJOR.MINOR" * * @return Returns the version as a String, or "N/A" if it was unable to be retrieved */ public String getDatabaseDriverVersion() { BootstrapManager setup = BootstrapUtils.getBootstrapManager(); if (setup == null || (hibernateConfig != null && !hibernateConfig.isHibernateSetup())) return "Not available"; // Get the connection URL String connectionUrl = setup.getString("hibernate.connection.url"); // If the connectionUrl is null (e.g. if it's a datasource), return "N/A" (CONF-5192, CONF-5211) if (connectionUrl == null) return "N/A"; try { Driver driver = DriverManager.getDriver(connectionUrl); return driver.getMajorVersion() + "." + driver.getMinorVersion(); } catch (Throwable t) { log.error("Error trying to retrieve the Driver for url '" + connectionUrl + "' " + t.getMessage(), t); return "N/A"; } } /** * Retrieves the list of enabled plugins. * Returns null when there was a problem retrieving the pluginManager * * @return List containing the enabled plugins */ public List getEnabledPlugins() { PluginManager pluginManager; // This is unlikely to happen, but if it does, handle it gracefully try { pluginManager = (PluginManager) ContainerManager.getInstance().getContainerContext().getComponent("pluginManager"); } catch (ComponentNotFoundException e) { log.error("Error trying to retrieve the plugin manager when printing out the enabled plugins: ", e); return null; } // Being (ultra) defensive. The last thing we want is the error page to fail. if (pluginManager == null) { log.error("Error trying to retrieve the plugin manager when printing out the enabled plugins."); return null; } return new ArrayList(pluginManager.getEnabledPlugins()); } private String getUptime() { Long startupTime = GeneralUtil.getSystemStartupTime(); if (startupTime == null) return "N/A"; long currentTime = System.currentTimeMillis(); return DateUtils.dateDifference(startupTime.longValue(), currentTime, 4, getI18n().getResourceBundle()); } public String getAppServer() { switch (Container.get()) { case Container.TOMCAT: return "Apache Tomcat"; case Container.ORION: return "Orion"; case Container.WEBLOGIC: return "IBM WebLogic"; case Container.JRUN: return "JRUN"; case Container.RESIN: return "RESIN" + Container.get(); case Container.HPAS: return "HPAS"; case Container.UNKNOWN: return "Unknown"; } return "Unknown"; } public long getTotalMemory() { return rt.totalMemory() / MEGABYTE; } public long getFreeMemory() { return rt.freeMemory() / MEGABYTE; } public long getUsedMemory() { return getTotalMemory() - getFreeMemory(); } public void setGc(boolean gc) { this.gc = gc; } }