/* * Copyright (c) 2014, Paessler AG <support@paessler.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */package com.paessler.prtg.jmx.sensors.jmx; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.management.ManagementFactory; import java.util.HashMap; import java.util.Map; import javax.management.InstanceNotFoundException; import javax.management.IntrospectionException; import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.openmbean.CompositeData; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; import javax.naming.Context; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.PosixParser; import com.paessler.prtg.jmx.Logger; import com.paessler.prtg.jmx.mbean.PRTGInterface; import com.paessler.prtg.jmx.sensors.JMXSensor; import com.paessler.prtg.jmx.sensors.profile.Entry; import com.paessler.prtg.jmx.sensors.profile.Profile; import com.paessler.prtg.jmx.sensors.profile.ProfileFactory; import com.paessler.prtg.jmx.sensors.profile.Profiles; import com.paessler.prtg.jmx.sensors.profile.StringAttribute; import com.paessler.prtg.util.SystemUtility; public class JMXUtils { // ---------------------------------------------------------------------- // http://docs.oracle.com/javase/7/docs/api/javax/management/remote/rmi/package-summary.html public static String LOCAL_STRING = "local"; public static String LOCALHOST_STRING = "localhost"; public static String RMI_PORT_DEFAULT = "1099"; public static String RMI_STRING_LOCAL = "service:jmx:rmi:///jndi/rmi://localhost:"+RMI_PORT_DEFAULT+"/jmxrmi"; public static String RMI_STRING_DEFAULT = "service:jmx:{rmi|iiop}:///jndi/rmi://{TARGET_MACHINE}:{RMI_REGISTRY_PORT def:"+RMI_PORT_DEFAULT+"}/jmxrmi"; // ---------------------------------------------------------------------- public static String makeRMIString(String host, String port){ StringBuilder retVal = new StringBuilder(); retVal.append("service:jmx:rmi:///jndi/rmi://"); if(host == null){ port = "localhost"; } retVal.append(host); retVal.append(":"); if(port == null){ if("localhost".equalsIgnoreCase(host)){ port = System.getProperty(SystemUtility.SYS_PROPERTY_JMX_REMOTE_PORT); } if(port == null){ port = RMI_PORT_DEFAULT; } } retVal.append(port); retVal.append("/jmxrmi"); return retVal.toString(); } // ---------------------------------------------------------------------- public static ObjectName getObjectName(String name){ ObjectName retVal = null; try { retVal = new ObjectName(name); } catch (MalformedObjectNameException e) { } return retVal; } // ----------------------------------------------------------------------------------- /** * Get Entry for MBeanInfo * @param mbi mBeanInfo to extract from * @param objectName Name of object[mBean] * @param classname Class name of mBean * @return */ public static Entry getBeanEntry(MBeanServerConnection server, MBeanInfo mbi, ObjectName objectName, String classname){ Entry retVal = new Entry(); Object obj; retVal.setObject(objectName.toString()); retVal.setDescription(mbi.getDescription()); retVal.setComment("Class Name:"+classname); // entry.setDisplayValue(); for(MBeanAttributeInfo mbai: mbi.getAttributes()){ StringAttribute attr = new StringAttribute(); attr.setObject(mbai.getName()); attr.setDescription(mbai.getDescription()); Object type = mbai.getType(); String commentstring = ""; if(type instanceof CompositeData){ commentstring = "Composit["; CompositeData data = (CompositeData)type; commentstring = data.getCompositeType().toString(); for(Object curr: data.values()){ commentstring += ";"+curr+"["+curr.getClass().getSimpleName()+"]"; } commentstring += "]"; } else { if(type != null){ commentstring = type.toString(); } } commentstring = "type="+commentstring+",unit=COUNT"; try { obj = server.getAttribute(objectName, mbai.getName()); if(obj != null){ commentstring += "; Value="+obj.toString(); } } catch (Throwable e) { commentstring += "; Value="+e.getMessage(); } attr.setComment(commentstring); retVal.addAttribute(attr); } retVal.sort(); return retVal; } // ----------------------------------------------------------------------------------- /** * Extract all Beans for server * @param server MBean Server to extract from * @param kind Kind of Bean for output * @param tag Tag for output * @param includeselfie Include definition of Self * @return Profiles * @throws IOException */ public static Profiles getBeanProfiles(MBeanServerConnection server, String kind, String tag, boolean includeselfie) throws IOException{ Profiles retVal = new Profiles(); if(includeselfie){ PRTGInterface.getAndRegisterBean(PRTGInterface.getDefaultBeanName()); } for(ObjectInstance instance: server.queryMBeans(null, null)){ Profile prof = new Profile(); prof.setBaseclass(JMXSensor.class.getName()); prof.setName(instance.getObjectName().toString()); prof.setKind(kind); prof.setTag(kind+","+tag); try { MBeanInfo mbi = server.getMBeanInfo(instance.getObjectName()); Entry entry = getBeanEntry(server, mbi, instance.getObjectName(), instance.getClassName()); prof.addEntry(entry); } catch (IntrospectionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstanceNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ReflectionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(prof != null){ prof.sort(); } retVal.addProfile(prof); } if(retVal != null){ retVal.sort(); } return retVal; } public static class MBeanConnectionHolder { MBeanServerConnection mbc = null; JMXConnector jmxc = null; public MBeanConnectionHolder(MBeanServerConnection mbconn, JMXConnector jmxconn){ this.mbc = mbconn; this.jmxc = jmxconn; } public void finalize() throws Throwable{ close(); super.finalize(); } public MBeanServerConnection getMbc() throws IOException{ if(mbc == null){ mbc = jmxc.getMBeanServerConnection(); } return mbc; } public void setMbc(MBeanServerConnection mbc) { this.mbc = mbc; } public JMXConnector getJmxc() { return jmxc; } public void setJmxc(JMXConnector jmxc) { mbc = null; this.jmxc = jmxc; } public void close(){ mbc = null; if(jmxc != null){ try { jmxc.close(); } catch(Throwable e) {} jmxc = null; } } } // ----------------------------------------------------------------------------------- /** * Create a connection to a JMX Server * @param rmistring RMI String to server * @param username Username to login with * @param password Passeword for user * @return Connection or null on failure * @throws IOException */ public static MBeanConnectionHolder getJMXConnection(String rmistring, String username, String password) throws IOException{ MBeanConnectionHolder retVal = new MBeanConnectionHolder(ManagementFactory.getPlatformMBeanServer(), null); JMXConnector jmxc = null; if(!(rmistring == null || LOCALHOST_STRING.equalsIgnoreCase(rmistring) || LOCAL_STRING.equalsIgnoreCase(rmistring) || RMI_STRING_LOCAL.equalsIgnoreCase(rmistring))){ String[] creds = {username, password}; Map<String, Object> env = new HashMap<String, Object>(); env.put(JMXConnector.CREDENTIALS, creds); env.put(Context.SECURITY_PRINCIPAL, username); env.put(Context.SECURITY_CREDENTIALS, password); JMXServiceURL serviceURL = new JMXServiceURL(rmistring); retVal.setJmxc(JMXConnectorFactory.connect(serviceURL, env)); if(retVal.getJmxc() != null){ retVal.getMbc(); } else { retVal = null; } } return retVal; } // ----------------------------------------------------------------------------------- private static void showHelp(Options options) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("JMX scanner", options); System.exit(1); } public static boolean dumpJMXToFile(String outputfile, String rmiString, String username, String password, boolean includeselfie){ boolean retVal = false; // Profiles prof = loadProfile(null, "W:/Paessler/java/JMXMiniProbe/data/profiles/jmx/Tomcat.xml"); MBeanConnectionHolder mbsch = null; MBeanServerConnection mbsc = null; try { mbsch = getJMXConnection(rmiString, username, password); if(mbsch != null) { mbsc = mbsch.getMbc(); } } catch (IOException e) { // TODO Auto-generated catch block Logger.log("Cought Exception while Connecting to ["+rmiString+"] "+e.getMessage()); } String xml = null; if(mbsc != null){ Profiles prof = null; try { prof = getBeanProfiles(mbsc, JMXSensorDefinition.KIND, JMXSensorDefinition.TAG, includeselfie); } catch (IOException e1) { // TODO Auto-generated catch block Logger.log("Cought Exception while dumpJMXToFile ", e1); } if(prof != null){ xml = ProfileFactory.toXML(prof); if(xml != null){ if(outputfile != null){ File ofn = new File(outputfile); Logger.log("Outputting XML to ["+ofn.getAbsolutePath()+"] "); OutputStream os = null; try { os = new FileOutputStream(ofn); os.write(xml.getBytes()); retVal = true; } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if(os != null) { try { os.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } // finally } else {// if os Logger.log(xml); } } } // Close it mbsch.close(); } else { Logger.log("No Connection to JMX Server"); } return retVal; } // ----------------------------------------------------------------------------------- // -r "service:jmx:rmi:///jndi/rmi://192.168.0.172:1090/jmxrmi" -o junk.xml public static void main(String[] args) { // org.apache.log4j.BasicConfigurator.configure(); Options options = new Options(); options.addOption("r", true, "RMI String["+RMI_STRING_DEFAULT+"]"); options.addOption("o", true, "Output file"); options.addOption("u", true, "username"); options.addOption("p", true, "password"); options.addOption("s", false, "include selfie[Definition of PRTGMBean]"); if (args.length == 0) { showHelp(options); } CommandLineParser parser = new PosixParser(); CommandLine cmdLine; String rmiString = null, outputfile = null, username = null, password = null; // rmiString = "service:jmx:iiop:///jndi/rmi://192.168.0.189:2809/jndi/JMXConnector"; rmiString = "service:jmx:iiop://192.168.0.189:2809/jndi/JMXConnector"; boolean includeselfie = false; try { cmdLine = parser.parse(options, args); if (cmdLine.hasOption("r")) rmiString = cmdLine.getOptionValue("r"); if(rmiString == null) showHelp(options); outputfile = cmdLine.getOptionValue("o"); username = cmdLine.getOptionValue("u"); password = cmdLine.getOptionValue("p"); includeselfie = cmdLine.hasOption("s"); } catch (Exception e) { showHelp(options); } // Profiles prof = loadProfile(null, "W:/Paessler/java/JMXMiniProbe/data/profiles/jmx/Tomcat.xml"); if(!dumpJMXToFile(outputfile, rmiString, username, password, includeselfie)){ Logger.log("Failed to dump JMX MBeans"); } // System.out.println(prof); } }