/**
* ICE Futures, US
*/
package org.helios.apmrouter.metric;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
import org.helios.apmrouter.jmx.ConfigurationHelper;
import org.helios.apmrouter.jmx.StringHelper;
import org.helios.apmrouter.satellite.services.attach.JVM;
/**
* <p>Title: AgentIdentity</p>
* <p>Description: Class to auto-configure the identity of the default agent for this JVM and to register identity plugins that can override the default identity locator.</p>
* <p>Company: ICE Futures US</p>
* @author Whitehead (nicholas.whitehead@theice.com)
* @version $LastChangedRevision$
* <p><code>org.helios.apmrouter.metric.AgentIdentity</code></p>
*/
public enum AgentIdentity {
/** The AgentIdentity singleton */
ID("localhost", "127.0.0.1");
/** We don't really want these host names except as a last resort */
public final Set<String> UNDEZ_HOST_NAMES;
/** The agent property name for the JVM's main class */
public static final String JVM_MAIN_CLASS = "sun.java.command";
/** The pattern for an IPV4 Octet */
public final String OCTET;
/** Pattern to match an IP V4 address */
public final Pattern IPV4_ADDRESS_PATTERN;
/**
* Creates a new AgentIdentity by divining the host name and agent name
*/
private AgentIdentity(String...undHostNames) {
UNDEZ_HOST_NAMES = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(undHostNames)));
OCTET = "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.";
IPV4_ADDRESS_PATTERN = Pattern.compile("^" + OCTET + OCTET + OCTET + OCTET + "?");
setHost();
setAgent();
}
/**
* Returns this JVM's determined host name
* @return this JVM's determined host name
*/
public String getHostName() {
return hostName;
}
/**
* Generates a formated string displaying the agent identity
* @return the agent identity
*/
public static String print() {
return new StringBuilder("Agent Identity [")
.append("\n\tAgent Name: [").append(ID.agentName).append("]")
.append("\n\tDomain Name: [").append(ID.domain).append("]")
.append("\n\tNQ Host Name: [").append(ID.host).append("]")
.append("\n\tQ Host Name: [").append(ID.hostName).append("]")
.append("\n]").toString();
}
public static void main(String[] args) {
System.out.println(print());
}
/**
* Returns this JVM's determined agent name
* @return this JVM's determined agent name
*/
public String getAgentName() {
return agentName;
}
/** This agent's default fully qualified host name */
private String hostName = null;
/** This agent's default agent name */
private String agentName = null;
/** This agent's default non-qualified host name */
private String host = null;
/** This agent's default domain name */
private String domain = null;
/**
* Tries a couple of ways of getting the fully qualified host name
*/
private void setHost() {
try {
hostName = InetAddress.getLocalHost().getCanonicalHostName();
} catch (IOException iex) {/* No Op */}
if(hostName==null || UNDEZ_HOST_NAMES.contains(hostName.trim().toLowerCase()) || hostName.contains(":") || hostName.contains("%")) {
hostName = null;
try {
for(Enumeration<NetworkInterface> enumer = NetworkInterface.getNetworkInterfaces(); enumer.hasMoreElements();) {
NetworkInterface nic = enumer.nextElement();
if(!nic.isLoopback()) {
for(InterfaceAddress ia: nic.getInterfaceAddresses()) {
hostName = ia.getAddress().getCanonicalHostName().trim().toLowerCase();
if(UNDEZ_HOST_NAMES.contains(hostName) || hostName.contains(":") || hostName.contains("%")) {
hostName = null;
continue;
}
break;
}
}
if(hostName!=null) break;
}
} catch (Exception e) {/* No Op */}
}
if(hostName==null) {
boolean isWindows = System.getProperty("os.name", "no").toLowerCase().contains("windows");
if(isWindows) hostName = System.getenv("COMPUTERNAME");
else hostName = System.getenv("HOSTNAME");
}
if(hostName==null) {
hostName = ManagementFactory.getRuntimeMXBean().getName().split("@")[1];
}
if(hostName==null) {
hostName = "UNKNOWN";
}
String[] names = buildNames(hostName);
hostName = names[2].toLowerCase();
host = names[1].toLowerCase();
domain = names[0].toLowerCase();
}
/**
* Extracts the non-qualified host name and domain from the passed name
* @param name The discovered host name
* @return and array with [0] = domain (reversed for hierarchy), [1] = the non-qualified host name, [2] = the full qualified host name (reversed for hierarchy)
*/
protected String[] buildNames(String name) {
name = name.trim();
hostName = name;
String[] ret = new String[3];
if(IPV4_ADDRESS_PATTERN.matcher(name).matches()) {
return new String[]{"", hostName, hostName};
}
if(hostName.contains(".")) {
String[] frags = hostName.replace(" ", "").split("\\.");
ret[1] = frags[0];
frags = reverseArr(frags);
ret[2] = StringHelper.fastConcatAndDelim(".", frags);
if(frags.length>1) {
String[] domain = new String[frags.length-1];
System.arraycopy(frags, 0, domain, 0, frags.length-1);
ret[0] = StringHelper.fastConcatAndDelim(".", domain);
} else {
ret[0] = "";
}
return ret;
}
return new String[]{"", hostName, hostName};
}
/**
* Reverses the order of the passed array
* @param arr The array to reverse
* @return The reversed order array
*/
protected String[] reverseArr(String[] arr) {
String[] ret = new String[arr.length];
for(int ri = arr.length-1, i = 0; i < arr.length; i++, ri--) {
ret[ri] = arr[i];
}
return ret;
}
/**
* Tries a couple of ways of getting the agent name
*/
private void setAgent() {
// Try system props, then env for the agent name property
agentName = ConfigurationHelper.getEnvThenSystemProperty("org.helios.agent", null);
if(agentName!=null && !agentName.trim().isEmpty()) {
System.setProperty("org.helios.agent", agentName);
return;
}
//System.getProperty("theice.agent.name", System.getenv("theice.agent.name"));
if(agentName==null) {
// Perhaps we're running in a jboss server
agentName = System.getProperty("jboss.server.name");
if(agentName!=null && !agentName.trim().isEmpty()) {
System.setProperty("org.helios.agent", agentName);
return;
}
}
if(agentName==null) {
agentName = System.getProperty(JVM_MAIN_CLASS, null);
if(agentName!=null && agentName.trim().isEmpty()) {
agentName = null;
} else {
agentName = JVM.cleanDisplayName(agentName);
}
}
if(agentName==null) {
try {
Class<?> clazz = Class.forName("sun.management.Agent");
clazz.getDeclaredMethod("loadManagementProperties").invoke(null);
Properties p = (Properties)clazz.getDeclaredMethod("getManagementProperties").invoke(null);
agentName = p.getProperty(JVM_MAIN_CLASS, null);
if(agentName!=null && agentName.trim().isEmpty()) {
agentName = null;
} else {
agentName = JVM.cleanDisplayName(agentName);
}
} catch (Exception ex) {
agentName = null;
}
}
if(agentName==null) {
// Ok, we'll use the PID until we implement agent naming plugins
agentName = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
}
}
/**
* Returns the non-qualified host name
* @return the non-qualified host name
*/
public String getHost() {
return host;
}
/**
* Returns the domain name which may be blank if one could not determined
* @return the domain name
*/
public String getDomain() {
return domain;
}
}