If i have a js object such as below stored in a js file
var _sampleProcessor = {
process: function(data){
...
}
}
How would i use Apache Rhino to call the process function?
// sb holds the contents of the js file
Context cx = Context.enter();
Scriptable scope = cx.initStandardObjects();
cx.evaluateString(scope, sb.toString(), "Test", 1, null);
Object processor = scope.get("sampleProcessor ", scope);
if (processor == Scriptable.NOT_FOUND) {
System.out.println("processor is not defined.");
}
Getting to the root of the object is easy, but how do i traverse the object tree to get at the process function property
Thanks in advance
This sample does a few things. Pulls out the sampleProcessor as your example does, and also pulls out the process property and executes that function.
It also shows adding Java objects into the scope so they can be used - the System.out object in the example.
package grimbo.test.rhino;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
public class InvokeFunction {
public static void main(String[] args) {
String sb = "var sampleProcessor = {\n" + " process: function(data){\n out.println(0); return 1+1;\n }\n" + "}";
Context cx = Context.enter();
Scriptable scope = cx.initStandardObjects();
Object out = Context.javaToJS(System.out, scope);
ScriptableObject.putProperty(scope, "out", out);
cx.evaluateString(scope, sb.toString(), "Test", 1, null);
// get the sampleProcessor object as a Scriptable
Scriptable processor = (Scriptable) scope.get("sampleProcessor", scope);
System.out.println(processor);
// get the process function as a Function object
Function processFunction = (Function) processor.get("process", processor);
System.out.println(processFunction);
// execute the process function
Object ob = cx.evaluateString(scope, "sampleProcessor.process()", "Execute process", 1, null);
System.out.println(ob);
}
}
Output:
[object Object]
org.mozilla.javascript.gen.Test_1#b169f8
0.0
2
Related
Use eclipse milo to connect a OPCUA server, can use browse to get the method nodes, and then how to get the DataType of method arguments?
Just like:
final BrowseDescription browseDesc = new BrowseDescription(nodeIdRoot, BrowseDirection.Forward,
Identifiers.References, true, uint(NodeClass.Method.getValue()),
uint(BrowseResultMask.All.getValue()));
BrowseResult browseResult = client.browse(browseDesc).get();
for (final ReferenceDescription rf : browseResult.getReferences()) {
final NodeId childId = rf.getNodeId().local().orElse(null);
List<Node> nodes = client.getAddressSpace().browse(childId).get();
for (Node node : nodes) {
// Now, I get the Node of method.
// How to get the method arguments data types?
system.out.println("need Input types {}" /*, InputArgument */);
system.out.println("will get Output types {}" /*, OutputArgument */);
}
}
Method Nodes have HasProperty References to Property Nodes named InputArguments and/or OutputArguments, as long as that method receives input or output arguments.
If you read the Value Attribute if these Nodes you'll get an Argument[] describing the arguments (Name, DataType, ValueRank, ArrayDimensions, Description).
UaMethodNode has getInputArguments and getOutputArguments calls on it that can help as well:
UaMethodNode methodNode = (UaMethodNode) client.getAddressSpace().getNodeInstance(methodId).get();
CompletableFuture<Argument[]> iaf = methodNode
.getInputArguments()
.exceptionally(ex -> new Argument[0]);
CompletableFuture<Argument[]> oaf = methodNode
.getOutputArguments()
.exceptionally(ex -> new Argument[0]);
iaf.thenAcceptBoth(oaf, (ia, oa) -> {
System.out.println("inputArgs: " + Arrays.toString(ia));
System.out.println("outputArgs: " + Arrays.toString(oa));
});
i'm curious is it possible to path java object (in any type (java/class/jar)) to REngine? till now i'm successfully executing an operation from java to R or vice versa. for example: i have my custom jar files which i'm using in RStudio, i wish to have same opportunity from java code as well.
above code is from RStudio
bellow code is from java
String javaVector="c(1,2,3,4,5)";
Rengine rengine = new Rengine(new String[]{"-no-save"}, false, null);
rengine.eval("rVector <-"+javaVector);
rengine.eval("meanVal=mean(rVector)");
double mean = rengine.eval("meanVal").asDouble();
REXP rexp = rengine.eval("meanVal");
System.out.println("Mean of given vector is <-"+mean);
rengine.eval(String.format("greeting <- '%s'", "Hello R World"));
REXP result = rengine.eval("greeting");
System.out.println("Greeting from R: "+result.asString());
i will answer my question. if someone is interested in answer. so to path java object from java code to R script you can do next: first pick the object you want to work with, for example :
public class RAccess{
static public Object getObject(String id){
return test;
}
static TestClass test = new TestClass();
}
public class TestClass{
String message;
public void setMessage(String value){
message = value;
}
}
after evaluate R script exactly like you do it in R console or RStudio, just put it in curly braces.
REXP x = re.eval(rCode3);
System.out.println(RAccess.test.message);
static String rCode3 =
"{ \n" +
"library(rJava) \n" +
".jinit() \n" +
"obj <- .jcall(\"jriTest/RAccess\", \"Ljava/lang/Object;\", \"getObject\", \"id\") \n" +
".jcall(obj, \"V\", \"setMessage\", \"hello from R\") \n" +
"}";
jriTest is a package name.
I am trying to wait until masonry has fully loaded with this code in Java
String javaScript = "function defer() {"
+"if (window.jQuery.masonry)"
+"{ return true }"
+"else"
+"{ return false }"
+"}; defer()";
boolean isMasonryLoaded=false;
while(!isMasonryLoaded)
{
isMasonryLoaded = (boolean)(((JavascriptExecutor)driver).executeScript(javaScript));
}
However i get NullPointerException at while(!isMasonryLoaded)
Any ideas ?
May be your script function defer() does not define before calling, you should try using executeAsyncScript as below :-
String javaScript = "var callback = arguments[0];"+
"function defer() {if (window.jQuery.masonry){ "+
"callback(true) }else{ callback(false) }}; defer()";
boolean isMasonryLoaded=false;
while(!isMasonryLoaded)
{
isMasonryLoaded = (boolean)(((JavascriptExecutor)driver).executeAsyncScript(javaScript));
}
Hope it helps..:)
I'm working on an Android app "native written in java"
and I'm getting a response from a server the response is a javascript function
I need to use this function to do some calculations inside my native java code.
any ideas how to do so.
sample response :
function logic_1(surveyString, responseValuesString) {
var survey = eval(surveyString);
var responseValues = eval(responseValuesString);
var target = new Object();
if (isChosen(128133225, responseValues)) {
target.id = 2;
}
if (! target.id) {
target.id = 2;
}
return target;
}
I've previously used Rhino successfully to execute JavaScript code on Android:
http://www.mozilla.org/rhino/
Here's an example of how to return values from a complex type:
String strFunction =
"function add(x,y){ " +
"return { " +
"id:x+y " +
"}; " +
"}";
Context context = Context.enter();
ScriptableObject scope = context.initStandardObjects();
context.evaluateString(scope, strFunction, "test", 1, null);
Function functionAdd = (Function)scope.get("add");
NativeObject untypedResult = (NativeObject)functionAdd.call(context, scope, scope, new Object[] { 1, 2 });
double id = (Double)untypedResult.get("id", untypedResult);
The important part is the last two lines, where we call the JavaScript function, treat the result as a NativeObject, and then retrieve the value of the 'id' property from that object.
Maybe you just need to use a JavaScript auto executing function like this:
(function(x, y){
var result;
result = x + y; // do some calculations
return result;
})(1 , 2); // you can set your parameters from Java
and 1, 2 are just two parameters from Java
I have a piece of Java code in a String.
String javaCode = "if(polishScreenHeight >= 200 && " +
"polishScreenHeight <= 235 && polishScreenWidth >= 220) { }";
Is it possible to convert this Java String to a Java statement and run it? Possibly using Java reflection?
As has already been suggested you can compile, save and run code on the fly using the Compiler API.
Another neat alternative would be to use beanshell. Beanshell is no longer actively developed, but I can vouch for it's reliability, I've used it successfully in multiple production projects.
Use BeanShell. There's a page on how to use it from Java.
Beanshell (as Boris suggested) is a way to "execute" java source code. But it looks like, you want to "execute" fragments that can interact with the compiled classes. Your example contains variabe names.
Reflection will definitly not help, because reflection targets classes ("classfiles").
You could try to define a complete class ("valid java source file"), compile it and load it (url classloader). Then you should be able to use the methods from that "live generated class". But once a class is loaded, you can't get rid of it (unload), so this will work only once (AFAIK).
As far as I know there is no simple way to do this.
However, in Java 6 onwards, you can compile source code for complete classes using javax.tools.Compiler. The compiled classes can then be loaded and executed. But I don't think this will achieve what you want.
Another way would be to execute your code as Groovy code, see this for an example.
you can use this code to run method from using this code
new Statement(Object target, String methodName, Object[] arguments).execute();
import java.beans.Statement;
public class HelloWorld {
public void method_name(String name) {
System.out.println(name);
}
public static void main(String[] args) throws Exception {
HelloWorld h = new HelloWorld();
new Statement(h, "method_name", new Object[]{"Hello world"}).execute();
}
}
Please reevaluate your design and this should be your last alternative.
You should validate the sanity of the String which will be executed to avoid future injection attack.
Now If you can have the String as JavaScript then below code should help,
public class EvalScript {
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// below JS function is executed.
/*
* student object value will be provided by the program as the JSON String.
function checkStudentElgibility(student){
if(student.age >= 10 && student.currentGrade >= 5){
return true;
}
}
// student object value will be provided by the program as the JSON String
checkStudentElgibility(student);
*/
String studentJsonString = "{\n" +
" \"age\" : 10,\n" +
" \"currentGrade\" : 5\n" +
"}";
String javaScriptFunctionString = "function checkStudentElgibility(student){\n" +
" if(student.age >= 10 && student.currentGrade >= 5){\n" +
" return true;\n" +
" }\n" +
"}\n" +
"checkStudentElgibility(student);";
StringBuilder javaScriptString = new StringBuilder();
javaScriptString.append("student=");
javaScriptString.append(studentJsonString);
javaScriptString.append("\n");
javaScriptString.append(javaScriptFunctionString);
Object object = engine.eval(javaScriptString.toString());
System.out.println(object);
// You can also pass the object as follows,
// evaluate JavaScript code that defines an object with one method
engine.eval("var obj = new Object()");
engine.eval("obj.hello = function(name) { print('Hello, ' + name)
}");
// expose object defined in the script to the Java application
Object obj = engine.get("obj");
// create an Invocable object by casting the script engine object
Invocable inv = (Invocable) engine;
// invoke the method named "hello" on the object defined in the
// in js Object with "Script Method" as parameter
inv.invokeMethod(obj, "hello", "Script Method!");
// You can also use Java Objects as Java script object and you can also pass Objects as reference inside Java script function
String jsString = " var obj = new Object()\n" +
" var ArrayList = Java.type(\"java.util.ArrayList\");\n" +
" var customSizeArrayList = new ArrayList(16);\n" +
" obj.hello = function(name) { \n" +
" customSizeArrayList(name); \n" +
" print('Hello, ' + name) \n" +
" }";
}
}
Reference :
https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/javascript.html#A1147187
Try the JavaCompiler API.
Someone else answered this way better than I could, though:
Convert String to Code
Be careful before actually using something like this...
It is not Java, but as pgras has already suggested you could use GrooyScript like so :
Binding binding = new Binding();
GroovyShell shell = new GroovyShell(binding);
String[] strings = new String[]{"World", "Groovy"};
shell.setVariable("args", strings);
String script = "return \"Hello \" + args[1]";
String value = (String) shell.evaluate(script);
System.out.println(value); // Hello Groovy