Home | History | Annotate | Download | only in resources
      1 /*
      2  * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  *   - Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  *
     11  *   - Redistributions in binary form must reproduce the above copyright
     12  *     notice, this list of conditions and the following disclaimer in the
     13  *     documentation and/or other materials provided with the distribution.
     14  *
     15  *   - Neither the name of Oracle nor the names of its
     16  *     contributors may be used to endorse or promote products derived
     17  *     from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * This source code is provided to illustrate the usage of a given feature
     34  * or technique and has been deliberately simplified. Additional steps
     35  * required for a production-quality application, such as security checks,
     36  * input validation and proper error handling, might not be present in
     37  * this sample code.
     38  */
     39 
     40 /*
     41  * This is a collection of utilities for Monitoring
     42  * and management API.
     43  *
     44  * File dependency:
     45  *    conc.js -> for concurrency utilities
     46  */
     47 
     48 // At any time, we maintain atmost one MBeanServer
     49 // connection. And so, we store the same as a global
     50 // variable.
     51 var mmConnection = null;
     52 
     53 function jmxConnect(hostport) {
     54     if (mmConnection != null) {
     55         // close the existing connection
     56         try {
     57             mmConnection.close();
     58         } catch (e) {
     59         }
     60     }
     61 
     62     var JMXServiceURL = javax.management.remote.JMXServiceURL;
     63     var JMXConnectorFactory = javax.management.remote.JMXConnectorFactory;
     64 
     65     var urlPath = "/jndi/rmi://" + hostport + "/jmxrmi";
     66     var url = new JMXServiceURL("rmi", "", 0, urlPath);
     67     var jmxc = JMXConnectorFactory.connect(url);
     68     // note that the "mmConnection" is a global variable!
     69     mmConnection = jmxc.getMBeanServerConnection();
     70 }
     71 jmxConnect.docString = "connects to the given host, port (specified as name:port)";
     72 
     73 function mbeanConnection() {
     74     if (mmConnection == null) {
     75         throw "Not connected to MBeanServer yet!";
     76     }
     77 
     78     return mmConnection;
     79 }
     80 mbeanConnection.docString = "returns the current MBeanServer connection";
     81 
     82 /**
     83  * Returns a platform MXBean proxy for given MXBean name and interface class
     84  */
     85 function newPlatformMXBeanProxy(name, intf) {
     86     var factory = java.lang.management.ManagementFactory;
     87     return factory.newPlatformMXBeanProxy(mbeanConnection(), name, intf);
     88 }
     89 newPlatformMXBeanProxy.docString = "returns a proxy for a platform MXBean";
     90 
     91 /**
     92  * Wraps a string to ObjectName if needed.
     93  */
     94 function objectName(objName) {
     95     var ObjectName = Packages.javax.management.ObjectName;
     96     if (objName instanceof ObjectName) {
     97         return objName;
     98     } else {
     99         return new ObjectName(objName);
    100     }
    101 }
    102 objectName.docString = "creates JMX ObjectName for a given String";
    103 
    104 /**
    105  * Creates a new (M&M) Attribute object
    106  *
    107  * @param name name of the attribute
    108  * @param value value of the attribute
    109  */
    110 function attribute(name, value) {
    111     var Attribute = Packages.javax.management.Attribute;
    112     return new Attribute(name, value);
    113 }
    114 attribute.docString = "returns a new JMX Attribute using name and value given";
    115 
    116 /**
    117  * Returns MBeanInfo for given ObjectName. Strings are accepted.
    118  */
    119 function mbeanInfo(objName) {
    120     objName = objectName(objName);
    121     return mbeanConnection().getMBeanInfo(objName);
    122 }
    123 mbeanInfo.docString = "returns MBeanInfo of a given ObjectName";
    124 
    125 /**
    126  * Returns ObjectInstance for a given ObjectName.
    127  */
    128 function objectInstance(objName) {
    129     objName = objectName(objName);
    130     return mbeanConnection().objectInstance(objectName);
    131 }
    132 objectInstance.docString = "returns ObjectInstance for a given ObjectName";
    133 
    134 /**
    135  * Queries with given ObjectName and QueryExp.
    136  * QueryExp may be null.
    137  *
    138  * @return set of ObjectNames.
    139  */
    140 function queryNames(objName, query) {
    141     objName = objectName(objName);
    142     if (query == undefined) query = null;
    143     return mbeanConnection().queryNames(objName, query);
    144 }
    145 queryNames.docString = "returns QueryNames using given ObjectName and optional query";
    146 
    147 /**
    148  * Queries with given ObjectName and QueryExp.
    149  * QueryExp may be null.
    150  *
    151  * @return set of ObjectInstances.
    152  */
    153 function queryMBeans(objName, query) {
    154     objName = objectName(objName);
    155     if (query == undefined) query = null;
    156     return mbeanConnection().queryMBeans(objName, query);
    157 }
    158 queryMBeans.docString = "return MBeans using given ObjectName and optional query";
    159 
    160 // wraps a script array as java.lang.Object[]
    161 function objectArray(array) {
    162     return Java.to(array, "java.lang.Object[]");
    163 }
    164 
    165 // wraps a script (string) array as java.lang.String[]
    166 function stringArray(array) {
    167     return Java.to(array, "java.lang.String[]");
    168 }
    169 
    170 // script array to Java List
    171 function toAttrList(array) {
    172     var AttributeList = Packages.javax.management.AttributeList;
    173     if (array instanceof AttributeList) {
    174         return array;
    175     }
    176     var list = new AttributeList(array.length);
    177     for (var index = 0; index < array.length; index++) {
    178         list.add(array[index]);
    179     }
    180     return list;
    181 }
    182 
    183 // Java Collection (Iterable) to script array
    184 function toArray(collection) {
    185     if (collection instanceof Array) {
    186         return collection;
    187     }
    188     var itr = collection.iterator();
    189     var array = new Array();
    190     while (itr.hasNext()) {
    191         array[array.length] = itr.next();
    192     }
    193     return array;
    194 }
    195 
    196 // gets MBean attributes
    197 function getMBeanAttributes(objName, attributeNames) {
    198     objName = objectName(objName);
    199     return mbeanConnection().getAttributes(objName,stringArray(attributeNames));
    200 }
    201 getMBeanAttributes.docString = "returns specified Attributes of given ObjectName";
    202 
    203 // gets MBean attribute
    204 function getMBeanAttribute(objName, attrName) {
    205     objName = objectName(objName);
    206     return mbeanConnection().getAttribute(objName, attrName);
    207 }
    208 getMBeanAttribute.docString = "returns a single Attribute of given ObjectName";
    209 
    210 // sets MBean attributes
    211 function setMBeanAttributes(objName, attrList) {
    212     objName = objectName(objName);
    213     attrList = toAttrList(attrList);
    214     return mbeanConnection().setAttributes(objName, attrList);
    215 }
    216 setMBeanAttributes.docString = "sets specified Attributes of given ObjectName";
    217 
    218 // sets MBean attribute
    219 function setMBeanAttribute(objName, attrName, attrValue) {
    220     var Attribute = Packages.javax.management.Attribute;
    221     objName = objectName(objName);
    222     mbeanConnection().setAttribute(objName, new Attribute(attrName, attrValue));
    223 }
    224 setMBeanAttribute.docString = "sets a single Attribute of given ObjectName";
    225 
    226 // invokes an operation on given MBean
    227 function invokeMBean(objName, operation, params, signature) {
    228     objName = objectName(objName);
    229     params = objectArray(params);
    230     signature = stringArray(signature);
    231     return mbeanConnection().invoke(objName, operation, params, signature);
    232 }
    233 invokeMBean.docString = "invokes MBean operation on given ObjectName";
    234 
    235 /**
    236  * Wraps a MBean specified by ObjectName as a convenient
    237  * script object -- so that setting/getting MBean attributes
    238  * and invoking MBean method can be done with natural syntax.
    239  *
    240  * @param objName ObjectName of the MBean
    241  * @param async asynchornous mode [optional, default is false]
    242  * @return script wrapper for MBean
    243  *
    244  * With async mode, all field, operation access is async. Results
    245  * will be of type FutureTask. When you need value, call 'get' on it.
    246  */
    247 function mbean(objName, async) {
    248     var index;
    249     objName = objectName(objName);
    250     var info = mbeanInfo(objName);
    251     var attrs = info.attributes;
    252     var attrMap = new Object;
    253     for (index in attrs) {
    254         attrMap[attrs[index].name] = attrs[index];
    255     }
    256     var opers = info.operations;
    257     var operMap = new Object;
    258     for (index in opers) {
    259         operMap[opers[index].name] = opers[index];
    260     }
    261 
    262     function isAttribute(name) {
    263         return name in attrMap;
    264     }
    265 
    266     function isOperation(name) {
    267         return name in operMap;
    268     }
    269 
    270     return new JSAdapter() {
    271         __has__: function (name) {
    272             return isAttribute(name) || isOperation(name);
    273         },
    274         __get__: function (name) {
    275             if (isAttribute(name)) {
    276                 if (async) {
    277                     return getMBeanAttribute.future(objName, name);
    278                 } else {
    279                     return getMBeanAttribute(objName, name);
    280                 }
    281             } else {
    282                 return undefined;
    283             }
    284         },
    285         __call__: function(name) {
    286             if (isOperation(name)) {
    287                 var oper = operMap[name];
    288 
    289                 var params = [];
    290                 for (var j = 1; j < arguments.length; j++) {
    291                     params[j-1]= arguments[j];
    292                 }
    293 
    294                 var sigs = oper.signature;
    295 
    296                 var sigNames = new Array(sigs.length);
    297                 for (var index in sigs) {
    298                     sigNames[index] = sigs[index].getType();
    299                 }
    300 
    301                 if (async) {
    302                     return invokeMBean.future(objName, name, params, sigNames);
    303                 } else {
    304                     return invokeMBean(objName, name, params, sigNames);
    305                 }
    306             } else {
    307                 return undefined;
    308             }
    309         },
    310         __put__: function (name, value) {
    311             if (isAttribute(name)) {
    312                 if (async) {
    313                     setMBeanAttribute.future(objName, name, value);
    314                 } else {
    315                     setMBeanAttribute(objName, name, value);
    316                 }
    317             } else {
    318                 return undefined;
    319             }
    320         }
    321     };
    322 }
    323 mbean.docString = "returns a conveninent script wrapper for a MBean of given ObjectName";
    324 
    325 if (this.application != undefined) {
    326     this.application.addTool("JMX Connect",
    327         // connect to a JMX MBean Server
    328         function () {
    329             var url = prompt("Connect to JMX server (host:port)");
    330             if (url != null) {
    331                 try {
    332                     jmxConnect(url);
    333                     alert("connected!");
    334                 } catch (e) {
    335                     error(e, "Can not connect to " + url);
    336                 }
    337             }
    338         });
    339 }
    340