/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.hq.plugin.weblogic.jmx; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Comparator; import java.util.Hashtable; import java.util.List; import java.util.Properties; import java.util.StringTokenizer; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.MalformedObjectNameException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hq.plugin.weblogic.WeblogicDetector; import org.hyperic.hq.product.TypeBuilder; import org.hyperic.hq.plugin.weblogic.WeblogicLogFileTrackPlugin; import org.hyperic.hq.plugin.weblogic.WeblogicMetric; import org.hyperic.hq.plugin.weblogic.WeblogicProductPlugin; public class ServerQuery extends BaseServerQuery implements Comparator { private static final Log log = LogFactory.getLog(ServerQuery.class); private WeblogicDiscover discover; private String url; private boolean isAdmin = false; private boolean isRunning = true; //innocent until proven guilty private String jvmType = "JVMRuntime"; private File cwd; private String wlsVersion; public static final String MBEAN_TYPE = "Server"; public static final String PROTOCOL_T3 = "t3"; public static final String PROTOCOL_T3S = "t3s"; public static final String ATTR_ADMIN_PORT = "AdministrationPort"; public static final String ATTR_ADMIN_OVERRIDE_PORT = "AdministrationPortAfterOverride"; public static final String ATTR_ADMIN_PORT_ENABLED = "AdministrationPortEnabled"; public static final String ATTR_JVM_RUNTIME = "JVMRuntime"; //seems MBeanServer.getAttributes stops getting attributes //without throwing an exception when it hits an attribute //that does not exist. so the order is important here //to support 6.1 private static final String[] SERVER_ATTRS = { //6.1+ ATTR_LISTEN_ADDR, ATTR_LISTEN_PORT, "DefaultProtocol", ATTR_NOTES, //7.1+ "ServerVersion", ATTR_ADMIN_PORT, ATTR_ADMIN_PORT_ENABLED, //ATTR_ADMIN_OVERRIDE_PORT, XXX gone in 9.1 }; private static final String[] CPROP_ATTRS = { "ServerVersion", "JavaVersion", "JavaVendor" }; private static final String[] JVM_RUNTIME_ATTRS = { "JavaVersion", "JavaVendor" }; //ListenAddress here is more reliable //in the standalone server it is null in the ServerMBean (above) private static final String[] SERVER_RUNTIME_ATTRS = { //6.1+ "WeblogicVersion", ATTR_LISTEN_ADDR, "CurrentDirectory", ATTR_JVM_RUNTIME, //7.1+ ATTR_SSL_LISTEN_PORT, "AdminServer" }; private static final String[] LOG_ATTRS = { "FileName" }; public WeblogicDiscover getDiscover() { return this.discover; } public void setDiscover(WeblogicDiscover discover) { this.discover = discover; } public WeblogicQuery cloneInstance() { ServerQuery query = (ServerQuery)super.cloneInstance(); query.discover = this.discover; return query; } private boolean isAdminPortEnabled() { return "true".equals(getAttribute(ATTR_ADMIN_PORT_ENABLED)); } public String getListenPort() { if (isAdminPortEnabled()) { String oPort = getAttribute(ATTR_ADMIN_OVERRIDE_PORT); if ("0".equals(oPort) || (oPort == null)) { //no override port configured. return getAttribute(ATTR_ADMIN_PORT); } return oPort; } if (isAdminSSL()) { return getSSLListenPort(); } return super.getListenPort(); } public String getProtocol() { return isAdminSSL() ? PROTOCOL_T3S : getAttribute("DefaultProtocol"); } public boolean isAdminSSL() { return this.discover.isAdminSSL(); } private void configureUrl() { String address = getListenAddress(); int idx = address.indexOf("/"); if (idx != -1) { address = address.substring(idx+1); this.attrs.put(ATTR_LISTEN_ADDR, address); } this.url = getProtocol() + "://" + address + ":" + getListenPort(); } public String getUrl() { return this.url; } public boolean isValidVersion(String version) { if (version == null) { return false; } //e.g. "8.1.0.0" //ServerVersion attribute may return "unknown" //if server was created but not yet started. for (int i=0; i<version.length(); i++) { char c = version.charAt(i); if (!(Character.isDigit(c) || (c == '.'))) { return false; } } return true; } private String getWeblogicVersion() { String version = getAttribute("WeblogicVersion"); if (version == null) { return null; } StringTokenizer tok = new StringTokenizer(version); while (tok.hasMoreTokens()) { String s = tok.nextToken(); if (isValidVersion(s)) { return s; } } return null; } private ObjectName getServerRuntime() { Hashtable attributes = new Hashtable(); attributes.put("Type", "ServerRuntime"); attributes.put("Name", getName()); attributes.put("Location", getName()); try { return new ObjectName(this.discover.getDomain(), attributes); } catch (MalformedObjectNameException e) { //wont happen. throw new IllegalArgumentException(e.getMessage()); } } private ObjectName getJVMRuntime() { String jvm = getAttribute(ATTR_JVM_RUNTIME); if (jvm == null) { return null; } try { return new ObjectName(jvm); } catch (MalformedObjectNameException e) { //wont happen. throw new IllegalArgumentException(e.getMessage()); } } private ObjectName getSSL() { Hashtable attributes = new Hashtable(); attributes.put("Type", "SSL"); attributes.put("Name", getName()); attributes.put("Server", getName()); try { return new ObjectName(this.discover.getDomain(), attributes); } catch (MalformedObjectNameException e) { //wont happen. throw new IllegalArgumentException(e.getMessage()); } } private void getSSLAttrs(MBeanServer mServer) { try { //SSLListenPort attribute only exists in ServerRuntimeMBean //so we have to get it for the nodes via the SSLMBean Object port = mServer.getAttribute(getSSL(), ATTR_LISTEN_PORT); this.attrs.put(ATTR_SSL_LISTEN_PORT, port.toString()); } catch (Exception e) { //unlikely/ok } } private ObjectName getLogMBean() { Hashtable attributes = new Hashtable(); attributes.put("Name", getName()); attributes.put("Location", getName()); attributes.put("ServerConfig", getName()); attributes.put("Type", "LogConfig"); try { return new ObjectName(this.discover.getDomain(), attributes); } catch (MalformedObjectNameException e) { //wont happen. throw new IllegalArgumentException(e.getMessage()); } } public boolean getAttributes(MBeanServer mServer, ObjectName name) { setName(name.getKeyProperty("Name")); setVersion(getDiscover().getVersion()); //type version if (!super.getAttributes(mServer, name, SERVER_ATTRS)) { return false; } if (isAdminPortEnabled()) { //gone in 9.1+ super.getAttributes(mServer, name, new String[] { ATTR_ADMIN_OVERRIDE_PORT }); } ObjectName runtimeName = getServerRuntime(); ObjectName logName = getLogMBean(); boolean isAdminName = getName().equals(this.discover.getAdminName()); if (isAdminName) { //this is the admin server instance super.getAttributes(mServer, runtimeName, SERVER_RUNTIME_ATTRS); super.getAttributes(mServer, getJVMRuntime(), JVM_RUNTIME_ATTRS); super.getAttributes(mServer, logName, LOG_ATTRS); if (getSSLListenPort() == null) { getSSLAttrs(mServer); } configureUrl(); } else { getSSLAttrs(mServer); //this is a node server configureUrl(); try { MBeanServer nodeServer = this.discover.getMBeanServer(this.url); this.isRunning = super.getAttributes(nodeServer, runtimeName, SERVER_RUNTIME_ATTRS); if (this.isRunning) { if (getJVMRuntime() == null) { this.isRunning = false; } else { super.getAttributes(nodeServer, getJVMRuntime(), JVM_RUNTIME_ATTRS); } super.getAttributes(nodeServer, logName, LOG_ATTRS); } configureUrl(); //attributes may differ now (e.g. ListenAddress) } catch (Exception e) { //ok; server is not running. this.isRunning = false; } } String serverVersion = getAttribute("ServerVersion"); if (isValidVersion(serverVersion)) { this.wlsVersion = serverVersion.substring(0, 3); } else if ((serverVersion == null) || serverVersion.equals("unknown")) { //6.1 does not have a ServerVersion attribute. //9.1 might be == "unknown" this.wlsVersion = getWeblogicVersion(); } if (!this.isRunning) { return true; } /* //6.1 does not have the AdminServer attribute. //PeopleSoft may have AdminServer = true for nodes. String adminServer = getAttribute("AdminServer"); if (adminServer != null) { this.isAdmin = "true".equals(adminServer); } */ this.isAdmin = isAdminName; //XXX if node is started by the nodemanager //this value is different than when started by hand File path = new File(getAttribute("CurrentDirectory")); if (path.getName().equals(".")) { path = path.getParentFile(); } this.cwd = path; return true; } public String getMBeanAlias() { return "Location"; } public String getMBeanType() { return MBEAN_TYPE; } public String getQualifiedName() { return this.discover.getDomain() + " " + getName(); } public String getResourceType() { String type; if (this.isAdmin) { type = WeblogicProductPlugin.ADMIN_NAME; } else { type = WeblogicProductPlugin.SERVER_NAME; } String version = getDiscover().getVersion(); return TypeBuilder.composeServerTypeName(type, version); } public String getIdentifier() { //domain + serverName is unique in weblogic return getResourceFullName(); } public String getInstallPath() { return new File(this.cwd, getName()).toString(); } public File getCwd() { return this.cwd; } public void setCwd(File value) { this.cwd = value; } public boolean isAdmin() { return this.isAdmin; } public boolean isRunning() { return this.isRunning; } protected String getControlProgram() { String ctl; if (!this.isRunning) { return ""; } if (this.cwd.getName().equals("nodemanager")) { ctl = ""; } else { try { ctl = new File(this.cwd, WeblogicDetector.NODE_START).getCanonicalPath(); } catch (IOException ex) { ctl = new File(this.cwd, WeblogicDetector.NODE_START).getPath(); log.debug(ex); } } return ctl; } public void configureAdminProps(Properties props) { props.setProperty(WeblogicMetric.PROP_ADMIN_URL, this.discover.getAdminURL()); props.setProperty(WeblogicMetric.PROP_ADMIN_USERNAME, this.discover.getUsername()); props.setProperty(WeblogicMetric.PROP_ADMIN_PASSWORD, this.discover.getPassword()); } public void configure(Properties props) { configureAdminProps(props); if (!this.isAdmin) { props.setProperty(WeblogicMetric.PROP_SERVER_URL, this.url); } props.setProperty(WeblogicMetric.PROP_DOMAIN, this.discover.getDomain()); props.setProperty(WeblogicMetric.PROP_SERVER, getName()); String jvmType; if (getJVMRuntime() != null) { jvmType = getJVMRuntime().getKeyProperty("Type"); } else { jvmType = this.jvmType; //server is not running } props.setProperty(WeblogicMetric.PROP_JVM, jvmType); String log = getAttribute("FileName"); if (log != null) { String cur = "." + File.separator; if (log.startsWith(cur)) { log = log.substring(2); } log = this.cwd + File.separator + log; props.setProperty(WeblogicLogFileTrackPlugin.PROP_FILES_SERVER, log); } } public String[] getCustomPropertiesNames() { return CPROP_ATTRS; } private int getOrder(ServerQuery s) { if (s.isAdmin()) { return 1; } if (s.isRunning()) { return 2; } return 3; } public int compare(Object s1, Object s2) { return getOrder((ServerQuery)s1) - getOrder((ServerQuery)s2); } public void sort(List servers) { Collections.sort(servers, this); } }