Skip to content

Instantly share code, notes, and snippets.

@lorenzoongithub
Last active April 10, 2017 08:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lorenzoongithub/7273902ac628b2761f46de2d0c2a31cd to your computer and use it in GitHub Desktop.
Save lorenzoongithub/7273902ac628b2761f46de2d0c2a31cd to your computer and use it in GitHub Desktop.
xr.js - A Nashorn JavaScript function to navigate inside the structure of any Java object. Designed for nudge4j. https://lorenzoongithub.github.io/nudge4j/
function xr(oj, name) {
var arrayLength = java.lang.reflect.Array.getLength;
var isStaticField = function(field) {
return java.lang.reflect.Modifier.isStatic(field.getModifiers());
}
/**
* Returns true if the input appears to represent a Class, false otherwise.
*
* isShortCutForClass(java.lang.String) --> true
* isShortCutForClass(java.lang.String.class) --> true
* isShortCutForClass(Java.type(java.lang.String.class)) --> true
*
* isShortCutForClass('java.lang.String') --> false
* isShortCutForClass(java.lang.StringX) --> false
*
**/
function isShortCutForClass(x) {
if (Java.isJavaFunction(x)) {
return ((''+x).indexOf('[JavaClass ')===0);
}
if (Java.isJavaObject(x)) {
if (x.getClass == undefined) return false;
return (x.getClass() == java.lang.Class.class);
}
return false;
}
/**
* If it is a Java Object (e.g HashMap, Thread, StringBuilder) returns its class.
* If it is a Nashorn shortcut for a JavaClass (e.g. java.util.HashMap) returns the represented class
* All other cases it returns null.
*/
function getClassFor(x) {
if (Java.isJavaFunction(x)) {
var str = ''+x;
if (str.indexOf('[JavaClass ')===0) {
return java.lang.Class.forName( str.substring(11, str.length - 1));
}
}
if (Java.isJavaObject(x)) {
if (x.getClass == undefined) return null;
var cz = x.getClass();
return (cz != java.lang.Class.class) ? cz : x;
}
return null;
}
if (oj === null) return 'Error: null';
var cz = getClassFor(oj);
if (cz === null) {
return "Error: Not a Java Object nor a Class";
}
//
// class is an array.
//
if (cz.isArray()) {
if (cz == oj) return cz.getComponentType().getSimpleName() + '[]'; // e.g. $(java.lang.Class.forName('int[]');
if (name == null) return cz.getComponentType().getSimpleName() + '[' + arrayLength(oj) + ']';
if (name == 'length') return arrayLength(oj);
var index;
try {
index = java.lang.Integer.parseInt(''+name,10)
} catch (e) {
return 'Error: Invalid index';
}
return (index >= 0 && index < arrayLength(oj)) ? java.lang.reflect.Array.get(oj, index) : 'Error: Out of bounds';
}
var isClass = isShortCutForClass(oj)
//
// listing the fields.
//
if (name == undefined) {
var fs = {};
while (true) {
var fields = cz.getDeclaredFields();
for (var i = 0; i < fields.length; i++) {
if ( isClass && isStaticField(fields[i])) fs[fields[i].getName()] = 1;
if (!isClass && !isStaticField(fields[i])) fs[fields[i].getName()] = 1;
}
cz = cz.getSuperclass();
if (cz === null) break;
}
var array = [];
for ( var i in fs) {
array.push(i);
}
array.sort();
return array.join('\n');
}
//
// getting a field.
//
while (true) {
var field;
try {
field = cz.getDeclaredField(name);
} catch (eee) {
cz = cz.getSuperclass();
if (cz === null) {
return 'Error: not a valid field';
}
continue;
}
if (isStaticField(field) == false && isClass) {
return 'Error: Attempt to access a non static field';
}
field.setAccessible(true);
var v = field.get(oj);
field.setAccessible(false);
return v;
}
}
@lorenzoongithub
Copy link
Author

lorenzoongithub commented Mar 11, 2017

you can use it in Nashorn/Console jjs or in nudge4j. Just Type:

// load the x-rays
load('https://gist.githubusercontent.com/lorenzoongithub/7273902ac628b2761f46de2d0c2a31cd/raw/a80b9369f3b63517da5eba4d962d3632cc26882c/xr.js');

// use the x-rays :-)
xr(java.lang.Thread.currentThread());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment