io.hawt.jvm.local.JVMList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hawtio-local-jvm-mbean Show documentation
Show all versions of hawtio-local-jvm-mbean Show documentation
hawtio :: ${project.artifactId}
package io.hawt.jvm.local;
import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import org.jolokia.jvmagent.JvmAgent;
import org.jolokia.jvmagent.client.command.CommandDispatcher;
import org.jolokia.jvmagent.client.util.OptionsAndArgs;
import org.jolokia.jvmagent.client.util.PlatformUtils;
import org.jolokia.jvmagent.client.util.VirtualMachineHandlerOperations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JVMList implements JVMListMBean {
private static final Logger LOG = LoggerFactory.getLogger(JVMList.class);
private MBeanServer mBeanServer;
private ObjectName objectName;
protected static final Map VM_ALIAS_MAP = new HashMap<>();
protected static final Map VM_ALIAS_OVERRIDE_MAP = new HashMap<>();
static {
// Hawtio
VM_ALIAS_MAP.put("hawtio-app", "Hawtio");
VM_ALIAS_MAP.put("main.HawtioJBang", "Hawtio JBang");
// Apache Camel
VM_ALIAS_MAP.put("org.apache.camel:camel-maven-plugin:run", "Apache Camel");
VM_ALIAS_MAP.put("camel:run", "Apache Camel");
VM_ALIAS_MAP.put("main.CamelJBang", "Camel JBang");
// Quarkus
VM_ALIAS_MAP.put("quarkus-run.jar", "Quarkus");
VM_ALIAS_MAP.put("quarkus-dev.jar", "Quarkus Dev");
// Spring Boot
VM_ALIAS_MAP.put("org.codehaus.plexus.classworlds.launcher.Launcher spring-boot:run", "Spring Boot");
VM_ALIAS_MAP.put("org.springframework.boot.loader.JarLauncher shell", "Spring Boot Shell");
// IntelliJ IDEA
VM_ALIAS_MAP.put("com.intellij.idea.Main", "IntelliJ IDEA");
VM_ALIAS_MAP.put("com.intellij.rt.execution.application.AppMain", "IntelliJ IDEA");
VM_ALIAS_MAP.put("org.jetbrains.idea.maven.server.RemoteMavenServer", "IntelliJ IDEA");
VM_ALIAS_MAP.put("idea maven server", "IntelliJ IDEA");
VM_ALIAS_MAP.put("IntelliJ IDEA", "IntelliJ IDEA");
VM_ALIAS_MAP.put("org.apache.karaf.main.Main", "Apache Karaf");
VM_ALIAS_MAP.put("activemq.jar start", "Apache ActiveMQ");
VM_ALIAS_MAP.put("org.apache.catalina", "Apache Tomcat");
VM_ALIAS_MAP.put("jetty", "Jetty");
VM_ALIAS_MAP.put("org.eclipse.equinox.launcher.Main", "Eclipse Equinox");
VM_ALIAS_MAP.put("scala.tools.nsc.MainGenericRunner", "Scala REPL");
VM_ALIAS_MAP.put("org.codehaus.groovy.tools.shell.Main", "Groovy Shell");
VM_ALIAS_MAP.put("org.codehaus.groovy.tools.GroovyStarter", "Groovy Starter");
VM_ALIAS_MAP.put("jboss-eap-6.1/jboss-modules.jar", "JBoss EAP 6");
VM_ALIAS_MAP.put("wildfly", "WildFly");
VM_ALIAS_MAP.put("target/surefire", "Maven Surefire Test");
VM_ALIAS_MAP.put("org.jboss.forge.bootstrap.Bootstrap", "JBoss Forge Shell");
VM_ALIAS_OVERRIDE_MAP.put("${zk:root/http}/jolokia", "Fabric8");
}
public JVMList() {
}
public void init() {
LOG.debug("Registering JVM discovery MBean: hawtio:type=JVMList");
try {
try {
// let's just hit any errors we're going to hit before even creating the mbean
listLocalJVMs();
} catch (LinkageError e) {
// Some JVM's don't support com.sun.tools.attach.VirtualMachine
LOG.warn(
"Local JVM discovery disabled as this JVM cannot access com.sun.tools.attach.VirtualMachine due to: {}",
e.getMessage());
return;
}
if (objectName == null) {
objectName = new ObjectName("hawtio:type=JVMList");
}
if (mBeanServer == null) {
mBeanServer = ManagementFactory.getPlatformMBeanServer();
}
try {
mBeanServer.registerMBean(this, objectName);
} catch (InstanceAlreadyExistsException iaee) {
// Try to remove and re-register
LOG.info("Re-registering SchemaLookup MBean");
mBeanServer.unregisterMBean(objectName);
mBeanServer.registerMBean(this, objectName);
}
} catch (Exception e) {
LOG.warn("Exception during initialization: ", e);
throw new RuntimeException(e);
}
LOG.info("Registered JVM discovery MBean: hawtio:type=JVMList");
}
public void destroy() {
try {
if (objectName != null && mBeanServer != null) {
mBeanServer.unregisterMBean(objectName);
}
} catch (Exception e) {
LOG.warn("Exception unregistering mbean: ", e);
throw new RuntimeException(e);
}
}
@Override
public List listLocalJVMs() {
List rc = new ArrayList<>();
try {
List processes = VirtualMachine.list();
for (VirtualMachineDescriptor process : processes) {
VMDescriptorDTO dto = new VMDescriptorDTO(process);
dto.setAgentUrl(agentStatus(dto.getId()));
String alias = getVmAlias(process.displayName(), dto.getAgentUrl());
dto.setAlias(alias);
// provide fine grained url details
if (dto.getAgentUrl() != null) {
try {
URL url = new URL(dto.getAgentUrl());
dto.setScheme(url.getProtocol());
dto.setHostname(url.getHost());
dto.setPort(url.getPort());
dto.setPath(url.getPath());
} catch (Exception e) {
// ignore
}
}
rc.add(dto);
}
} catch (Exception e) {
LOG.warn("Failed to get local JVM processes due to: {}", e.getMessage());
throw new RuntimeException("Failed to get local JVM processes due to: " + e.getMessage(), e);
}
return rc;
}
private void doAction(String PID, String action) {
OptionsAndArgs options;
if (action.equals("start")) {
options = new OptionsAndArgs(CommandDispatcher.getAvailableCommands(), "--quiet", "--port", allocateFreePort(), action, PID);
} else {
options = new OptionsAndArgs(CommandDispatcher.getAvailableCommands(), "--quiet", action, PID);
}
// System.out.println("Jar file at : " + options.getJarFilePath());
VirtualMachineHandlerOperations vmHandler = PlatformUtils.createVMAccess(options);
CommandDispatcher dispatcher = new CommandDispatcher(options);
Object vm = null;
try {
vm = vmHandler.attachVirtualMachine();
dispatcher.dispatchCommand(vm, vmHandler);
} catch (Exception e) {
throw new RuntimeException("Failed to " + action + " agent in process " + PID, e);
} finally {
if (vm != null) {
try {
vmHandler.detachAgent(vm);
} catch (Exception e) {
// swallow this?
}
}
}
}
private String allocateFreePort() {
int port = 8778;
try (ServerSocket sock = new ServerSocket(0)) {
port = sock.getLocalPort();
} catch (Exception e) {
// ignore;
}
// ignore
return Integer.toString(port);
}
@Override
public void startAgent(String PID) {
doAction(PID, "start");
}
@Override
public String agentStatus(String PID) {
Object vm = null;
OptionsAndArgs options = new OptionsAndArgs(CommandDispatcher.getAvailableCommands(), "--quiet", "status", PID);
VirtualMachineHandlerOperations vmHandler = PlatformUtils.createVMAccess(options);
String agentUrl = null;
try {
vm = vmHandler.attachVirtualMachine();
agentUrl = checkAgentUrl(vm);
} catch (Exception e) {
// maybe log this
} finally {
try {
vmHandler.detachAgent(vm);
} catch (Exception e) {
// log this
}
}
return agentUrl;
}
@Override
public String agentVersion(String PID) {
return null;
}
@Override
public void stopAgent(String PID) {
doAction(PID, "stop");
}
static String getVmAlias(String displayName, String agentUrl) {
String answer = displayName;
for (String key : VM_ALIAS_MAP.keySet()) {
if (displayName.contains(key)) {
answer = VM_ALIAS_MAP.get(key);
break;
}
}
// the agent url may help indicate what the process really is
if (agentUrl != null) {
for (String key : VM_ALIAS_OVERRIDE_MAP.keySet()) {
if (agentUrl.contains(key)) {
answer = VM_ALIAS_OVERRIDE_MAP.get(key);
break;
}
}
}
return answer;
}
// borrowed these from AbstractBaseCommand for now
protected String checkAgentUrl(Object pVm) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Properties systemProperties = getAgentSystemProperties(pVm);
return systemProperties.getProperty(JvmAgent.JOLOKIA_AGENT_URL);
}
protected Properties getAgentSystemProperties(Object pVm) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class> clazz = pVm.getClass();
Method method = clazz.getMethod("getSystemProperties");
return (Properties) method.invoke(pVm);
}
}