/* * RHQ Management Platform * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package org.rhq.enterprise.server.core; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Date; import java.util.HashMap; import java.util.Properties; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.ejb.ConcurrencyManagement; import javax.ejb.ConcurrencyManagementType; import javax.ejb.LocalBean; import javax.ejb.Singleton; import javax.ejb.Startup; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.management.ObjectName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.as.controller.client.ModelControllerClient; import org.rhq.common.jbossas.client.controller.DeploymentJBossASClient; import org.rhq.common.jbossas.client.controller.MCCHelper; import org.rhq.core.domain.common.ProductInfo; import org.rhq.core.util.ObjectNameFactory; import org.rhq.enterprise.server.RHQConstants; import org.rhq.enterprise.server.core.service.ManagementService; import org.rhq.enterprise.server.util.JMXUtil; /** * Get information about RHQ's underlying AS Server. */ @Singleton @Startup @LocalBean @ConcurrencyManagement(ConcurrencyManagementType.BEAN) @TransactionAttribute(TransactionAttributeType.SUPPORTS) public class CoreServer implements CoreServerMBean { private static final String PRODUCT_INFO_PROPERTIES_RESOURCE_PATH = "org/rhq/enterprise/server/core/ProductInfo.properties"; private static final Log LOG = LogFactory.getLog(CoreServer.class); /** * The name of the version file as found in this class's classloader */ private static final String VERSION_FILE = "rhq-server-version.properties"; /** * Version property whose value is the product version. */ private static final String PROP_PRODUCT_VERSION = "Product-Version"; /** * Version property whose value is the source code revision number used to make the build. */ private static final String PROP_BUILD_NUMBER = "Build-Number"; /** * Version property whose value is the date when this version of the product was built. */ private static final String PROP_BUILD_DATE = "Build-Date"; private static class SecurityActions { private SecurityActions() { } private static ModelControllerClient createModelControllerClient() { if (System.getSecurityManager() == null) { return ManagementService.createClient(); } else { return AccessController.doPrivileged(new PrivilegedAction<ModelControllerClient>() { @Override public ModelControllerClient run() { return ManagementService.createClient(); } }); } } } private Properties buildProps; private Date bootTime; @PostConstruct private void init() { JMXUtil.registerMBean(this, OBJECT_NAME); this.buildProps = loadBuildProperties(); this.bootTime = new Date(); // make sure our log file has an indication of the version of this server String version = getVersion(); String buildNumber = getBuildNumber(); String buildDate = this.buildProps.getProperty(PROP_BUILD_DATE, "?"); LOG.info("Version=[" + version + "], Build Number=[" + buildNumber + "], Build Date=[" + buildDate + "]"); } @PreDestroy private void destroy() { JMXUtil.unregisterMBeanQuietly(OBJECT_NAME); } public String getName() { return "RHQ Server"; } @Override public String getVersion() { return this.buildProps.getProperty(PROP_PRODUCT_VERSION, "?"); } @Override public String getBuildNumber() { return this.buildProps.getProperty(PROP_BUILD_NUMBER, "?"); } @Override public Date getBootTime() { return bootTime; } @Override public File getInstallDir() { String rhqHome = System.getProperty("rhq.server.home"); if (rhqHome != null) { return new File(rhqHome); } // I think that sysprop should always be set, but just in case, fallback on using // logDir explicitly - log dir is always under our own installation directory File homeDir = new File(getServerEnvironmentAttribute("logDir")); return homeDir.getParentFile(); // logDir is "rhq-install-dir/logs", so the install dir is .. from there } @Override public File getJBossServerHomeDir() { File baseDir = new File(getServerEnvironmentAttribute("baseDir")); return baseDir; } @Override public File getJBossServerDataDir() { File dataDir = new File(getServerEnvironmentAttribute("dataDir")); return dataDir; } @Override public File getJBossServerTempDir() { File tempDir = new File(getServerEnvironmentAttribute("tempDir")); return tempDir; } @Override public File getEarDeploymentDir() { //Getting model controller client requires privs our callers might not have, but we want to provide this //function even to them. ModelControllerClient mcc = SecurityActions.createModelControllerClient(); try { DeploymentJBossASClient client = new DeploymentJBossASClient(mcc); String earPath = client.getDeploymentPath(RHQConstants.EAR_FILE_NAME); return new File(earPath); } catch (Exception e) { throw new RuntimeException(e); } finally { MCCHelper.safeClose(mcc); } } @Override public ProductInfo getProductInfo() { ClassLoader classLoader = this.getClass().getClassLoader(); InputStream inputStream = classLoader.getResourceAsStream(PRODUCT_INFO_PROPERTIES_RESOURCE_PATH); if (inputStream != null) { Properties props = new Properties(); try { try { props.load(inputStream); } finally { inputStream.close(); } } catch (IOException e) { throw new IllegalStateException("Failed to load product info properties from class loader resource [" + PRODUCT_INFO_PROPERTIES_RESOURCE_PATH + "]."); } ProductInfo productInfo = new ProductInfo(); productInfo.setBuildNumber(props.getProperty("buildNumber")); productInfo.setFullName(props.getProperty("fullName")); productInfo.setHelpDocRoot(props.getProperty("helpDocRoot")); productInfo.setName(props.getProperty("name")); productInfo.setSalesEmail(props.getProperty("salesEmail")); productInfo.setShortName(props.getProperty("shortName")); productInfo.setSupportEmail(props.getProperty("supportEmail")); productInfo.setUrlDomain(props.getProperty("urlDomain")); productInfo.setUrl(props.getProperty("url")); productInfo.setVersion(props.getProperty("version")); productInfo.setSupportedAgentBuilds(props.getProperty("supportedAgentBuilds")); productInfo.setVersionUpdate(""); HashMap<String, String> helpViewContent = new HashMap<String, String>(); for (String propertyName : props.stringPropertyNames()) { if (propertyName.startsWith("view_help_section")) { helpViewContent.put(propertyName, props.getProperty(propertyName)); } } productInfo.setHelpViewContent(helpViewContent); return productInfo; } else { throw new IllegalStateException("Failed to find class loader resource [" + PRODUCT_INFO_PROPERTIES_RESOURCE_PATH + "]."); } } private String getServerEnvironmentAttribute(String attributeName) { try { ObjectName name = ObjectNameFactory.create("jboss.as:core-service=server-environment"); Object value = JMXUtil.getPlatformMBeanServer().getAttribute(name, attributeName); return (value != null) ? value.toString() : null; } catch (Exception e) { throw new RuntimeException(e); } } private Properties loadBuildProperties() { Properties buildProps = new Properties(); ClassLoader classLoader = this.getClass().getClassLoader(); try { InputStream stream = classLoader.getResourceAsStream(VERSION_FILE); try { buildProps.load(stream); } finally { stream.close(); } } catch (Exception e) { LOG.fatal("Failed to load [" + VERSION_FILE + "] via class loader [" + classLoader + "]"); } return buildProps; } }