Basically I want to be able to do be able to parse a JavaScript-like syntax. For example:
var results = system.function('example');
if(results == "hello") {
console_print("ding dong.");
}
So basically you get it, results will be a "string" and system.function will call a Java method, and those results will go into the results string.
I want to be able to do basic math, and validation in this as well, but I want this done in Java. Any ideas?
If you're willing to use JavaScript (not just JavaScript-like), and you're using Java 1.6+, then you can use the Scripting API:
import javax.script.*;
public class Main {
public static void main (String[] args) throws Exception {
String source =
"var system = new Array(); \n" +
"system['foo'] = function(s) { return 'hello'; } \n" +
" \n" +
"var results = system.foo('example'); \n" +
" \n" +
"if(results == \"hello\") { \n" +
" print(\"ding dong.\"); \n" +
"} \n";
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.eval(source);
}
}
which will print:
ding dong.
to the console.
And to invoke Java methods from the scripting language, you could give BeanShell a try:
package test;
import bsh.Interpreter;
public class Main {
public static void foo(Object param) {
System.out.println("From Java, param=" + param);
}
public static void main (String[] args) throws Exception {
Interpreter i = new Interpreter();
i.eval("a = 3 * 5; test.Main.foo(a);");
}
}
which will print:
From Java, param=15
The core interpreter JAR of BeanShell is only 143 KB: more lightweight than that will be difficult, IMO.
I think you can use Rhino for this. Rhino is an javascript engine that can be embedded in java.
Related
I have a php code as shown below which validates the answer at Line A which user enters in a html form.
When user enters any answer with apostrophe in the html input field form, I am getting the error message Secret Answer is Invalid.
For example: On entering Hello World', I am getting the error message Secret Answer is Invalid from Line Z.
//response
$response_error = new error();
$response_error->field = SECRET_response;
if($response != "" && $service->validAnswer($answer) != 'true'){ // Line A
$response_error->inError = true;
$response_error->errorMessage = SECRET_response.ISINVALID; // Line Z
} else {
$response_error->inError = false;
}
The Java code/method belonging to the validAnswer method used at Line A above is:
public static boolean validAnswer(String answer) {
Pattern a = Pattern.compile("^(?=.*\\S)[a-zA-Z0-9éèàêâçîëïÇÉÔÂÊÎÔÛËÏÀùÙ!#%&$%*\\- ]+$"); // Line B
Matcher b = a.matcher(answer);
logger.info("validAnswer: mmatches(): " + (b.matches()) + " a: " + a);
return b.matches();
}
Problem Statement:
I am wondering what changes I need to make in the java code above so that it takes apostrophe in the html input form.
This is what I have tried in the Java code:
I have put ' in at the end of [ ] inside of it. On trying that, it doesn't seem to work.
public static boolean validAnswer(String answer) {
Pattern a = Pattern.compile("^(?=.*\\S)[a-zA-Z0-9éèàêâçîëïÇÉÔÂÊÎÔÛËÏÀùÙ!#%&$%*\\-' ]+$"); // Line A
Matcher b = a.matcher(answer);
logger.info("validAnswer: mmatches(): " + (b.matches()) + " a: " + a);
return b.matches();
}
Calling Java from PHP just to use a regex is very weird and inefficient. PHP has regex support of course, so you don't need Java for that.
Anyway, your latest code works perfectly:
import java.util.regex.*;
public class Test
{
public static boolean validAnswer(String answer)
{
Pattern a = Pattern.compile("^(?=.*\\S)[a-zA-Z0-9éèàêâçîëïÇÉÔÂÊÎÔÛËÏÀùÙ!#%&$%*\\-' ]+$");
Matcher b = a.matcher(answer);
return b.matches();
}
public static void main(String args[])
{
System.out.println(validAnswer("Hello World'"));
}
}
Output:
true
So I guess you didn't recompile your code after modifying it.
I have a logging function in CSharp and Java that I use in walking the stack. How do I make each log print to a new line only. Below are my Java and CSharp Functions.
public static void LogFunctionCall(String parameters){
Object trace = Thread.currentThread().getStackTrace()[3];
android.util.Log.i("##################" + trace.toString()+ "", parameters );
}
the java version is this
public static void LogFunctionCall(string parameters,
[System.Runtime.CompilerServices.CallerMemberName] string methodName = "",
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
var stackFrame = new StackFrame(1);
var callerMethod = stackFrame.GetMethod();
var className = callerMethod.DeclaringType;
System.Diagnostics.Trace.WriteLine("CCCCCCCCCCCCCCCC" + " " + className + " " + methodName + " " + sourceLineNumber + " " + parameters + "\n");
}
I code on a windows machine.
Please where exactly do I need to place the new line character. I tried this
public static void LogFunctionCall(String parameters){
Object trace = Thread.currentThread().getStackTrace()[3];
android.util.Log.i("##################" + trace.toString()+ "", parameters + "\n" );
}
but I still saw some of the logs being clumped up on a single line.
Instead of \n, try \r\n (carriage return and newline). Some text editors will display differently, so the newline may be in there, but whatever app you're using to read the logs might not be displaying it correctly.
You could also try
System.lineSeparator();
I've seen instances where the /n won't work but the lineSep does.
Also, because it hasn't been mentioned, Environment.NewLine will give you the new line character that is configured for the current environment.
Is there a way to get and use an extended Java class from JavaScript (Nashorn)?
What I am trying to do is to extend a Java class in Nashorn and then pass it back to Java. For example, we define a class which extends another class in JS:
var SomeClass= Java.type("com.test.SomeClass");
var MySomeClass = Java.extend(SomeClass, {
aMethod1: function() {
print("m1");
},
aMethod2: function() {
print("m2");
},
});
Then I've tried to get this extended object in Java like so: Object mySomeClass = scriptEngine.get("MySomeClass");
However, I am unable to make any method calls on this object in Java. It always throws an exception when I am trying to cast it to a base class - com.test.SomeClass.
Is it possible to use an extended class created in Nashorn (JS) in Java?
Here is a working example extending ArrayList:
String script = "(function() {\n" +
" var ArrayList = Java.type('java.util.ArrayList')\n" +
" var ArrayListExtender = Java.extend(ArrayList)\n" +
" var list = new ArrayListExtender() {\n" +
" get: function(idx) {\n" +
" return idx >= list.size() ? " +
"'no such value' : Java.super(list).get(idx);\n" +
" }\n" +
" }\n" +
" return list;\n" +
"} ());";
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
#SuppressWarnings("unchecked")
List<String> result = (List<String>) engine.eval(script);
result.add("gotcha");
System.out.println(result.get(0));
System.out.println(result.get(10));
You don't state what exception you are getting but the problem is likely in how you consume or use the type. Note that neither Java.type nor Java.extend return a java.lang.Class - these methods return an internal Nashorn type with an undocumented API.
Hi I have been struggling to get the 'getenv' to work. it will keep on returning "Exception in thread "main" java.lang.UnsupportedOperationException". I have been reading about the ProcessBuilder but i am not quite sure on how and where to implement it based on my code below.
What I want to exactly do is, to set a variable ("REGRESSION_STATUS", "UPDATED") and ("REGRESSION_STATUS", "OUTDATED") when the condition is met, and return the value "UPDATED" and "OUTDATED" as appropriate when executed through the cmd in Windows.
public static void main(String[] args) throws ClassNotFoundException {
String run_type = args[0];
String inputFile = args[1];
System.out.println("RUN TYPE = " + run_type);
System.out.println("INPUT FILE = " + inputFile);
MiniData data = getValue(run_type, "LEM");
if(run_type.equals("BUILD")){
System.out.println("Script = " + data.getScript());
}
else if (run_type.equals("DEPLOY")){
System.out.println("Script = " + data.getScript());
}
else if (run_type.equals("REGRESSION")){
System.out.println("Runtime Version (DB) = " + data.getRuntime());
String file_name =inputFile;
if(data.getRuntime().equals(getRuntimeVersion(file_name)))
{
System.out.println("The version is up-to-date");
System.getenv().put("REGRESSION_STATUS", "UPDATED");
System.getenv().put("REGRESSION_VER", data.getRuntime());
}
else
{
System.out.println("This version is outdated");
System.getenv().put("REGRESSION_STATUS", "OUTDATED");
System.getenv().put("REGRESSION_VER", data.getRuntime() );
}
}
else {
System.out.println("You have not the correct value. Enter either BUILD/DEPLOY/REGRESSION");
}
}
Thanks!
The System.getenv() method returns an unmodifiable view of the environment variables. You cannot use it to set environment variables like you're doing here.
The only time you can "set" environment variables is when you are creating an environment for a child process, using the ProcessBuilder class or the Runtime.exec method, but even then you are not modifying your copy of the environment.
You must use C putenv and JNI, there is no way to do that from Java.
I want to generate an antlr lexer at runtime -- that is, generate the grammar and from the grammar generate the lexer class, and its supporting bits at runtime. I am happy to feed it into the the java compiler, which is accessible at runtime.
Here's a quick and dirty way to:
generate a combined (!) ANTLR grammar .g file given a String as grammar-source,
and create a Parser & Lexer from this .g file,
compile the these Parser & Lexer .java files,
create instances of the Parser & Lexer classes and invoke the entry point of the parser.
Main.java
import java.io.*;
import javax.tools.*;
import java.lang.reflect.*;
import org.antlr.runtime.*;
import org.antlr.Tool;
public class Main {
public static void main(String[] args) throws Exception {
// The grammar which echos the parsed characters to theconsole,
// skipping any white space chars.
final String grammar =
"grammar T; \n" +
" \n" +
"parse \n" +
" : (ANY {System.out.println(\"ANY=\" + $ANY.text);})* EOF \n" +
" ; \n" +
" \n" +
"SPACE \n" +
" : (' ' | '\\t' | '\\r' | '\\n') {skip();} \n" +
" ; \n" +
" \n" +
"ANY \n" +
" : . \n" +
" ; ";
final String grammarName = "T";
final String entryPoint = "parse";
// 1 - Write the `.g` grammar file to disk.
Writer out = new BufferedWriter(new FileWriter(new File(grammarName + ".g")));
out.write(grammar);
out.close();
// 2 - Generate the lexer and parser.
Tool tool = new Tool(new String[]{grammarName + ".g"});
tool.process();
// 3 - Compile the lexer and parser.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, System.out, System.err, "-sourcepath", "", grammarName + "Lexer.java");
compiler.run(null, System.out, System.err, "-sourcepath", "", grammarName + "Parser.java");
// 4 - Parse the command line parameter using the dynamically created lexer and
// parser with a bit of reflection Voodoo :)
Lexer lexer = (Lexer)Class.forName(grammarName + "Lexer").newInstance();
lexer.setCharStream(new ANTLRStringStream(args[0]));
CommonTokenStream tokens = new CommonTokenStream(lexer);
Class<?> parserClass = Class.forName(grammarName + "Parser");
Constructor parserCTor = parserClass.getConstructor(TokenStream.class);
Parser parser = (Parser)parserCTor.newInstance(tokens);
Method entryPointMethod = parserClass.getMethod(entryPoint);
entryPointMethod.invoke(parser);
}
}
Which, after compiling and running it like this (on *nix):
java -cp .:antlr-3.2.jar Main "a b c"
or on Windows
java -cp .;antlr-3.2.jar Main "a b c"
, produces the following output:
ANY=a
ANY=b
ANY=c
You'll have to use org.antlr.Tool() class to get it working.
You can check ANTLRWorks source code on github to have an idea how to use it, specifically the generate() method here:
ErrorListener el = ErrorListener.getThreadInstance();
ErrorManager.setErrorListener(el);
String[] params;
if(debug)
params = new String[] { "-debug", "-o", getOutputPath(), "-lib", window.getFileFolder(), window.getFilePath() };
else
params = new String[] { "-o", getOutputPath(), "-lib", window.getFileFolder(), window.getFilePath() };
new File(getOutputPath()).mkdirs();
Tool antlr = new Tool(Utils.concat(params, AWPrefs.getANTLR3Options()));
antlr.process();
boolean success = !el.hasErrors();
if(success) {
dateOfModificationOnDisk = window.getDocument().getDateOfModificationOnDisk();
}
lastError = el.getFirstErrorMessage();
el.clear();
ErrorManager.removeErrorListener();
return success;
Have you tried calling org.antlr.Tool.main(String[]) with an appropriate String[] argument?
If that's too cumbersome, you could reverse engineer the Tool class (source code) to figure out how it works, and how to do the specific tasks you need to do.