PT ##143653365 + PT ##143653925: simple main class that identifies running boot apps and tries to find the port information

This commit is contained in:
Martin Lippert
2017-05-12 11:08:41 +02:00
parent 97c6b2acc1
commit a383fb607b
8 changed files with 263 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>commons-boot-app-cli</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,3 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8

View File

@@ -0,0 +1,5 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.8

View File

@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@@ -0,0 +1,37 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>commons-boot-app-cli</artifactId>
<name>commons-boot-app-cli</name>
<description>Common code related to 'accessing running boot apps in a cli-like style'</description>
<parent>
<groupId>org.springframework.ide.vscode</groupId>
<artifactId>commons-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.8.1</version>
</dependency>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.8.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,164 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.boot.app.cli;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.json.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
/**
* @author Martin Lippert
*/
@SuppressWarnings("restriction")
public class SpringBootAppCLI {
public static void main(String[] args) throws Exception {
List<VirtualMachineDescriptor> list = VirtualMachine.list();
for (VirtualMachineDescriptor vmd : list) {
VirtualMachine vm = VirtualMachine.attach(vmd);
Properties props = vm.getSystemProperties();
String classpath = (String) props.get("java.class.path");
String[] cpElements = getClasspath(classpath);
boolean isSpringBoot = contains(cpElements, "spring-boot");
boolean isSpringBootActuator = contains(cpElements, "spring-boot-actuator");
if (isSpringBoot) {
printBootAppDetails(vmd, vm, isSpringBootActuator);
}
}
}
private static void printBootAppDetails(VirtualMachineDescriptor vmd, VirtualMachine vm,
boolean isSpringBootActuator) throws IOException {
System.out.println("Spring Boot App: " + vmd.id());
System.out.println("Name: " + vmd.displayName());
System.out.println("Actuators available: " + isSpringBootActuator);
String jmxConnect = vm.startLocalManagementAgent();
System.out.println("JMX Connection: " + jmxConnect);
JMXConnector jmxConnector = null;
try {
JMXServiceURL serviceUrl = new JMXServiceURL(jmxConnect);
jmxConnector = JMXConnectorFactory.connect(serviceUrl, null);
try {
String port = getPort(jmxConnector);
System.out.println("Runs on port: " + port);
}
catch (InstanceNotFoundException e) {
System.out.println("Port not available");
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (jmxConnector != null) jmxConnector.close();
}
System.out.println();
}
private static boolean contains(String[] cpElements, String element) {
for (String cpElement : cpElements) {
if (cpElement.contains(element)) {
return true;
}
}
return false;
}
private static String[] getClasspath(String classpath) {
List<String> classpathElements = new ArrayList<>();
if (classpath != null) {
StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator);
while (tokenizer.hasMoreTokens()) {
String classpathElement = tokenizer.nextToken();
classpathElements.add(classpathElement);
}
}
return (String[]) classpathElements.toArray(new String[classpathElements.size()]);
}
private static String getPort(JMXConnector jmxConnector) throws Exception {
MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();
String port = getPortViaAdmin(connection);
if (port != null) {
return port;
}
else {
return getPortViaActuator(connection);
}
}
private static String getPortViaAdmin(MBeanServerConnection connection) throws Exception {
try {
String DEFAULT_OBJECT_NAME = "org.springframework.boot:type=Admin,name=SpringApplication";
ObjectName objectName = new ObjectName(DEFAULT_OBJECT_NAME);
Object o = connection.invoke(objectName,"getProperty", new String[] {"local.server.port"}, new String[] {String.class.getName()});
return o.toString();
}
catch (InstanceNotFoundException e) {
System.out.println("Admin management bean not available");
return null;
}
}
private static String getPortViaActuator(MBeanServerConnection connection) throws Exception {
try {
String environment = getEnvironment(connection);
System.out.println("Environment: " + environment);
JSONObject env = new JSONObject(environment);
if (env != null) {
JSONObject portsObject = env.getJSONObject("server.ports");
if (portsObject != null) {
String portValue = portsObject.getString("local.server.port");
return portValue;
}
}
}
catch (InstanceNotFoundException e) {
System.out.println("Actuator not available: Spring Boot actuators not enabled");
}
return null;
}
private static String getEnvironment(MBeanServerConnection connection) throws Exception {
String DEFAULT_OBJECT_NAME = "org.springframework.boot:type=Endpoint,name=environmentEndpoint";
ObjectName objectName = new ObjectName(DEFAULT_OBJECT_NAME);
Object result = connection.getAttribute(objectName, "Data");
return new ObjectMapper().writeValueAsString(result);
}
}

View File

@@ -19,6 +19,7 @@
<module>commons-cf</module>
<module>commons-maven</module>
<module>commons-gradle</module>
<module>commons-boot-app-cli</module>
</modules>
<repositories>