/** * Copyright (C) 2008 Jeff Mesnil * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.jmesnil.jmx; import static java.lang.Character.isLowerCase; import static org.mozilla.javascript.Context.getUndefinedValue; import static org.mozilla.javascript.Context.jsToJava; import java.util.HashMap; import java.util.Map; import javax.management.Attribute; import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import org.mozilla.javascript.Context; import org.mozilla.javascript.FunctionObject; import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; public class ScriptableMBean extends ScriptableObject { private final ObjectName on; private final Map<String, String> attributes = new HashMap<String, String>(); private final MBeanServerConnection mbsc; public ScriptableMBean(ObjectName objectName, MBeanServerConnection conn) throws Exception { this.on = objectName; this.mbsc = conn; MBeanInfo mbeanInfo = mbsc.getMBeanInfo(on); for (MBeanAttributeInfo attribute : mbeanInfo.getAttributes()) { String attrName = attribute.getName(); if (attrName.length() >= 1 && isLowerCase(attrName.charAt(1))) { String attrNameStartingWithLowerCase = attrName.substring(0, 1) .toLowerCase() + attrName.substring(1, attrName.length()); attributes.put(attrNameStartingWithLowerCase, attrName); } else { // the attribute starts with 2 characters in upper case, use it // as it is: attributes.put(attrName, attrName); } } for (final MBeanOperationInfo opInfo : mbeanInfo.getOperations()) { final String funcName = opInfo.getName(); final String[] signature = new String[opInfo.getSignature().length]; for (int i = 0; i < opInfo.getSignature().length; i++) { signature[i] = opInfo.getSignature()[i].getType(); } FunctionObject func = new FunctionObject(opInfo.getName(), this .getClass().getMethod("toString", new Class[0]), this) { @Override public Object call(Context arg0, Scriptable arg1, Scriptable arg2, Object[] args) { Object[] convertedArgs = new Object[args.length]; try { for (int i = 0; i < args.length; i++) { convertedArgs[i] = jsToJava(args[i], Object.class); } return mbsc.invoke(on, funcName, convertedArgs, signature); } catch (Exception e) { e.printStackTrace(); return getUndefinedValue(); } } }; put(funcName, this, func); } } @Override public String getClassName() { return "ScriptableMBean"; } public boolean has(String name, Scriptable arg1) { if (attributes.containsKey(name)) { return true; } else { return super.has(name, arg1); } } public Object get(String name, Scriptable arg1) { if (attributes.containsKey(name)) { try { Context context = Context.getCurrentContext(); Scriptable scope = ScriptRuntime.getTopCallScope(context); return context.getWrapFactory().wrap(context, scope, mbsc.getAttribute(on, attributes.get(name)), Object.class); } catch (Exception e) { e.printStackTrace(); return getUndefinedValue(); } } else { return super.get(name, arg1); } } public void put(String name, Scriptable arg1, Object value) { if (attributes.containsKey(name)) { try { mbsc.setAttribute(on, new Attribute(attributes.get(name), value)); } catch (Exception e) { e.printStackTrace(); } } else { super.put(name, arg1, value); } } public Object getDefaultValue(Class arg0) { return "[object ScriptableMBean for " + on + "]"; } }