/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2007, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.apmrouter.monitor.script; import org.helios.apmrouter.monitor.script.rhino.INativeArray; import org.helios.apmrouter.monitor.script.rhino.INativeObject; import org.helios.apmrouter.monitor.script.rhino.IScriptableObject; import org.helios.apmrouter.monitor.script.rhino.NativeFactory; import org.json.JSONArray; import org.json.JSONObject; import java.util.*; /** * <p>Title: JSONNativeizer</p> * <p>Description: Utility class to marshall between native Rhino objects and java JSON objects.</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.monitor.script.JSONNativeizer</code></p> */ public class JSONNativeizer { /** * Creates a new native javascript object from the passed JSON object * @param json The JSON object to convert * @return a native Rhino javascript object */ public static Object toNative(JSONObject json) { return toNative(json, null); } /** * Creates a new native javascript object from the passed JSON object * @param json The JSON object to convert * @param jsObject An existing native Rhino javascript object which is created anew if null. Used for a recusrive parse * @return a native Rhino javascript object */ public static Object toNative(JSONObject json, Object jsObject) { if(json==null) return null; try { INativeObject no = null; if(jsObject==null) { no = NativeFactory.newNativeObject(); } else { no = NativeFactory.newNativeObject(jsObject); } for(String key : JSONObject.getNames(json)) { if(key==null) continue; Object obj = json.get(key); if(obj == JSONObject.NULL) { no.putProperty(key, null); } else if(obj instanceof JSONArray) { no.putProperty(key, toNative((JSONArray)obj)); } else if(obj instanceof JSONObject) { no.putProperty( key, toNative((JSONObject)obj, null)); } else { no.putProperty(key, obj); } } return no.getUnderlying(); } catch (Exception ex) { //ex.printStackTrace(System.err); throw new RuntimeException("Failed to convert json to native" , ex); } } /** * Creates a new native javascript array from the passed JSON array * @param json The JSON array to convert * @return a native Rhino javascript array */ public static Object toNative(JSONArray json) { try { Object[] vars = new Object[json.length()]; for(int i = 0; i < json.length(); i++) { Object obj = json.get(i); if(obj == JSONObject.NULL) { continue; } else if(obj instanceof JSONArray) { vars[i] = toNative((JSONArray)obj); } else if(obj instanceof JSONObject) { vars[i] = toNative((JSONObject)obj, null); } else { vars[i] = obj; } } return NativeFactory.newNativeArray(vars).getUnderlying(); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * Converts the passed ScriptableObject to a {@link JMXScriptRequest} array * @param o The rhino native object * @return an array of {@link JMXScriptRequest}s */ public static JMXScriptRequest[] fromNative(Object o) { if(o==null) throw new IllegalArgumentException("The passed object was null", new Throwable()); IScriptableObject no = NativeFactory.convertToNative(o); Set<JMXScriptRequest> requests = new HashSet<JMXScriptRequest>(); if(no instanceof INativeArray) { INativeArray na = (INativeArray)no; for(int i = 0; i < na.size(); i++) { Collections.addAll(requests, fromNative(na.get(i))); } } else if(no instanceof INativeObject) { String mbs = null; if(no.hasProperty(JMXScriptRequest.KEY_MBEAN_SERVER)) { mbs = no.getProperty(JMXScriptRequest.KEY_MBEAN_SERVER).toString(); } String objName = no.getProperty(JMXScriptRequest.KEY_OBJECT_NAME).toString(); Set<String> attrs = new HashSet<String>(); Map<String, String[]> compositeNames = new HashMap<String, String[]>(); Object attrObj = no.getProperty(JMXScriptRequest.KEY_ATTRIBUTES); if(attrObj instanceof INativeArray) { INativeArray na = (INativeArray)attrObj; for(int i = 0; i < na.size(); i++) { Object a = na.get(i); if(a instanceof INativeObject) { INativeObject co = (INativeObject)a; compositeNames.put(co.getProperty(JMXScriptRequest.KEY_COMPOSITES).toString(), getPathFromNative(co)); } else { attrs.add(na.get(i).toString()); } } } else if(attrObj instanceof INativeObject) { INativeObject co = (INativeObject)attrObj; compositeNames.put(co.getProperty(JMXScriptRequest.KEY_COMPOSITES).toString(), getPathFromNative(co)); } else if(attrObj instanceof CharSequence) { attrs.add(attrObj.toString()); } else { throw new RuntimeException("Unexpected type in JSON request Attribute array [" + attrObj.getClass().getName() + "]", new Throwable()); } JMXScriptRequest jmxRequest = new JMXScriptRequest(mbs, objName, compositeNames, attrs.toArray(new String[attrs.size()])); requests.add(jmxRequest); } else { throw new RuntimeException("Unexpected type in JSON request [" + no.getClass().getName() + "]", new Throwable()); } JMXScriptRequest[] done = requests.toArray(new JMXScriptRequest[requests.size()]); return done; } /** * Extracts an array of {@link JMXCalculator}s from the passed object * @param calculatorNode The native object to extract from * @return an array of {@link JMXCalculator}s */ protected static JMXCalculator[] extractCalculators(IScriptableObject calculatorNode) { Set<JMXCalculator> calcs = new HashSet<JMXCalculator>(); if(calculatorNode instanceof INativeObject) { calcs.add(extractCalculator((INativeObject)calculatorNode)); } else if(calculatorNode instanceof INativeArray) { INativeArray arr = (INativeArray)calculatorNode; for(int i = 0; i < arr.size(); i++) { Collections.addAll(calcs, extractCalculators((IScriptableObject)arr.get(i))); } } else { throw new RuntimeException("Unexpected type in calculator object [" + calculatorNode.getClass().getName() + "]", new Throwable()); } return calcs.toArray(new JMXCalculator[calcs.size()]); } /** * Extracts a {@link JMXCalculator} from the passed object * @param no The native object proxy to extract from * @return a JMXCalculator */ protected static JMXCalculator extractCalculator(INativeObject no) { String name = no.getProperty(JMXCalculator.KEY_NAME).toString(); Object groupObject = no.getProperty(JMXCalculator.KEY_GROUP); String[] group = null; if(groupObject==null || groupObject.getClass().getSimpleName().equals("UniqueTag")) { group = new String[0]; } else if(groupObject instanceof CharSequence) { group = new String[]{groupObject.toString()}; } else if(groupObject.getClass().getSimpleName().equals("NativeArray") ) { INativeArray narr = NativeFactory.newNativeArray(groupObject); group = extractStringArray(narr); } else { throw new RuntimeException("Type of group not recognized", new Throwable()); } String functionName = no.getProperty(JMXCalculator.KEY_FUNCTION).toString(); JMXScriptRequest[] queries = fromNative(no.getProperty(JMXCalculator.KEY_QUERY)); JMXCalculator calc = new JMXCalculator(name, group, functionName, queries); if(no.hasProperty(JMXCalculator.KEY_XPARAM)) { INativeObject xparams = NativeFactory.newNativeObject(no.getProperty(JMXCalculator.KEY_XPARAM)); for(Object key: xparams.getAllIds()) { calc.addXParam(key.toString(), xparams.getProperty(key.toString()).toString()); } } return calc; } /** * Extracts a string array from a native array * @param array The native array * @return an array of strings */ public static String[] extractStringArray(INativeArray array) { int size = array.size(); String[] arr = new String[size]; for(int i = 0; i < size; i++) { arr[i] = array.get(i).toString(); } return arr; } /** * Extracts the path from a native object * @param no the native object * @return A string array representing the path */ protected static String[] getPathFromNative(INativeObject no) { Object path = no.getProperty(JMXScriptRequest.KEY_PATH); if(path instanceof INativeArray) { INativeArray na = (INativeArray)path; String[] arr = new String[na.size()]; for(int i = 0; i < na.size(); i++) { arr[i] = na.get(i).toString(); } return arr; } return new String[]{path.toString()}; } // public static void log(Object msg) { // System.out.println(msg); // } }