I am using ScriptEngineManager in my grails application to execute javascript code.
When I execute this javascript:
var x = new java.util.ArrayList([1, 2, 3])
log(x[55])
With this code:
try {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript")
return engine.eval(javascript)
} catch (ScriptException jsEx) {
// Exception is added in outer function to the log
throw new JavascriptException(jsEx.getMessage(), jsEx)
} catch (Exception e) {
throw new JavascriptException("UNEXPECTED Exception in invokeJavaScript " + e.getMessage(), e)
}
I get a java.lang.IndexOutOufBoundsExceptionin the Excpetion e. This is okay, but I want to know which line in the javascript the error occured.
Is there a possibility to get the last successful line from javascript code?
I found a workaround for my problem. I parse the stacktrace of the exception so I get the line number:
//this method gives me the stacktrace as string
String trace = helperService.stacktraceToString(e)
String line = ""
trace.eachLine {
if (it.contains("<eval>")) {
line = " at line " + it.substring(it.lastIndexOf("<eval>:"), it.length() -1).replace("<eval>:", "")
}
}
Related
I have a springboot app that calls a .jsx script. It is a simple script, just read a JSON file and print some values on console.
My problem is when I try to get the output and log on my springboot app.
When I run the script using ExtendToolkit Script, I get the follow info on console:
Id: 6989996500
Result: undefined
But, when I run through Springboot, the output is:
Exit status: 0
Output: [TypeQuest] Timestamp=2023-02-01T05:00:19.434 ThreadId=6304 Type=TQ_WARN Component=TQFontManager Description="Not using user-specific cache directory; using: C:\Users\lnrei\AppData\Roaming\Adobe\typequest.2"
Here is my spring code:
`
try {
String[] command = {"C:\\Program Files\\Adobe\\Adobe Photoshop 2022\\Photoshop.exe",
"-r",
"C:\\Users\\lnrei\\OneDrive\\Documentos\\Projeto\\Photoshop Scripts\\scriptPSthumbnail.jsx"};
//Process process = new ProcessBuilder(command).start();
Process process = Runtime.getRuntime().exec(command);
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while((line = reader.readLine()) != null)
output.append(line + "\n");
int exit = process.waitFor();
System.out.println("Exit status: " + exit);
System.out.println("Output: " + output);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}`
As you can see, I trying to use process.getInputStream() to catch the output and sendo to a string.
Here is my .jsx file:
`
#include "json2.js";
var contentPath = "C:/Users/lnrei/OneDrive/Documentos/Projeto/content/content.json";
var contentFile = new File(contentPath);
if(contentFile.exists) {
contentFile.open("r");
var jsonStr = contentFile.read ();
contentFile.close ();
var content = JSON.parse(jsonStr);
$.writeln ("Id: " + content.matchId)
} else {
$.writeln ("Error handling the file!");
}
$.writeln();
photoshop.quit();`
I am looking to split a string similar to this:
"I/ContentValues: InputLine {"batchcomplete":"","query":{"pages":{"24437894":{"pageid":24437894,"ns":0,"title":"Boston","thumbnail":{"source":"https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Massachusetts_State_House_-_panoramio_%281%29.jpg/250px-Massachusetts_State_House_-_panoramio_%281%29.jpg","width":250,"height":166},"pageimage":"Massachusetts_State_House_-_panoramio_(1).jpg"}}}}
All I want is the hyperlink to the image:
https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Massachusetts_State_House_-panoramio%281%29.jpg/250px-Massachusetts_State_House_-panoramio%281%29.jpg
It's easy to do it in C. By using the right(":",7) and it will parse out everything past the 7th ":".
But, I cannot seem to find anything similar in Java.
I have tried the following code without any success:
Code that captures the HTML String
bandName = artist.artistName;
bandName = bandName.replace(' ','_');
try {
getUrlSource("https://en.wikipedia.org/w/api.php?action=query&titles="+bandName+"&prop=pageimages&format=json&pithumbsize=250");
} catch (IOException e) {
e.printStackTrace();
}
My Attempt to Parse it out
private void getUrlSource(String site) throws IOException {
URL url = new URL(site);
Log.i(TAG, "Web Address " + site);
URLConnection urlc = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
urlc.getInputStream(), "UTF-8"));
String inputLine;
StringBuilder a = new StringBuilder();
while ((inputLine = in.readLine()) != null)
a.append(inputLine);
Log.i(TAG, "InputLine " + a);
in.close();
String value = a.substring(a.indexOf("source\":")+1,
a.indexOf("\",", a.indexOf(",")+1));
Log.i(TAG, "Web Address " + value);
//webView.loadUrl(value);
}
Logcat
2020-10-08 13:29:09.328 18746-18746/com.rvogl.androidaudioplayer I/TetheringManager: registerTetheringEventCallback:com.rvogl.androidaudioplayer
2020-10-08 13:29:09.346 18746-18851/com.rvogl.androidaudioplayer W/chromium: [WARNING:dns_config_service_posix.cc(341)] Failed to read DnsConfig.
2020-10-08 13:29:09.423 18746-18746/com.rvogl.androidaudioplayer I/ContentValues: Web Address https://en.wikipedia.org/w/api.php?action=query&titles=Boston&prop=pageimages&format=json&pithumbsize=250
2020-10-08 13:29:09.469 18746-18759/com.rvogl.androidaudioplayer I/roidaudioplaye: Background concurrent copying GC freed 9670(1027KB) AllocSpace objects, 3(60KB) LOS objects, 49% free, 4107KB/8214KB, paused 268us total 159.378ms
2020-10-08 13:29:09.689 18746-18746/com.rvogl.androidaudioplayer I/ContentValues: InputLine {"batchcomplete":"","query":{"pages":{"24437894":{"pageid":24437894,"ns":0,"title":"Boston","thumbnail":{"source":"https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Massachusetts_State_House_-_panoramio_%281%29.jpg/250px-Massachusetts_State_House_-_panoramio_%281%29.jpg","width":250,"height":166},"pageimage":"Massachusetts_State_House_-_panoramio_(1).jpg"}}}}
2020-10-08 13:29:09.690 18746-18746/com.rvogl.androidaudioplayer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.rvogl.androidaudioplayer, PID: 18746
java.lang.StringIndexOutOfBoundsException: String index out of range: -17
at java.lang.AbstractStringBuilder.substring(AbstractStringBuilder.java:935)
at java.lang.StringBuilder.substring(StringBuilder.java:77)
at com.rvogl.androidaudioplayer.fragments.ArtistDetailsFragment.getUrlSource(ArtistDetailsFragment.java:165)
at com.rvogl.androidaudioplayer.fragments.ArtistDetailsFragment.setDetails(ArtistDetailsFragment.java:124)
at com.rvogl.androidaudioplayer.fragments.ArtistDetailsFragment.onCreateView(ArtistDetailsFragment.java:100)
Any assistance would be greatly appreciated
In the part you use the substring I use a method like this.
public static StringBuilder cutImg(StringBuilder split){
int start=split.indexOf("\"source\":")+new String("\"source\":").length();
split.delete(0, start);
split.delete(split.indexOf(","), split.length());
return split;
}
There are many methods to do it and I still don't understad the complete syntax of the URL so it can throw you exceptions if the syntax is different.
I'm making a website with a game on it. For the game i need to send data trought sockets. Everything is working fine with loading the page but I can't get the handshaking to work.
class ServerClient {
public ServerClient() {
handshake();
}
private void handshake() {
try {
String line;
String key = "";
boolean socketReq = false;
while (true) {
line = input.readLine();
if (line.startsWith("Upgrade: websocket"))
socketReq = true;
if (line.startsWith("Sec-WebSocket-Key: "))
key = line;
if (line.isEmpty())
break;
}
if (!socketReq)
socket.close();
String encodedKey = DatatypeConverter.printBase64Binary(
MessageDigest.getInstance("SHA-1")
.digest((key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes()));
System.out.println(encodedKey);
output.println("HTTP/1.1 101 Switching Protocols");
output.println("Upgrade: websocket");
output.println("Connection: Upgrade");
output.println("Sec-WebSocket-Accept: " + encodedKey);
output.flush();
output.close(); // output = new PrintWriter(
// Socket.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}
The socketReq variable is there because I don't want anyone to connect to localhost:25580 straight from their browser.
My send and receive functions are in different Threads and they will be started after the handshake.
The result of new WebSocket("ws://localhost:25580") in JS is
WebSocket connection to 'ws://localhost:25580/' failed: Error during WebSocket handshake: net::ERR_CONNECTION_CLOSED
I was having
Error during WebSocket handshake: Incorrect 'Sec-WebSocket-Accept' header value
but I guess I changed something in the code.
I searched for hours trought Article 1 and Article 2 and from other sites. Just couldn't get the whole thing to work properly.
I don't get the point of the keys and why we have to encode them.
The socket is connected to the browser and I am getting the headers from it.
Host: localhost:25580
Sec-WebSocket-Key: iWLnXKrA3fLD6h6UGMIigg==
How does the handshaking work?
You are getting a net::ERR_CONNECTION_CLOSED error, because you are closing the connection with output.close().
If you want to keep the connection open, obviously don't close it during a handshake.
Done!
Found the answers from http://blog.honeybadger.io/building-a-simple-websockets-server-from-scratch-in-ruby/ and It's working perfectly!
The code:
public ClientSocket(Socket socket) {
try {
this.socket = socket;
this.input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.output = new PrintWriter(socket.getOutputStream());
handshake();
}
private void handshake() {
try {
String line;
String key = "";
while (true) {
line = input.readLine();
if (line.startsWith("Sec-WebSocket-Key: ")) {
key = line.split(" ")[1];
System.out.println("'" + key + "'");
}
if (line == null || line.isEmpty())
break;
}
output.println("HTTP/1.1 101 Switching Protocols");
output.println("Upgrade: websocket");
output.println("Connection: Upgrade");
output.println("Sec-WebSocket-Accept: " + encode(key));
output.println();
output.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
private String encode(String key) throws Exception {
key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
byte[] bytes = MessageDigest.getInstance("SHA-1").digest(key.getBytes());
return DatatypeConverter.printBase64Binary(bytes);
}
Now I just have to decode the messages.
I'm trying to call a JavaScript function from Java code. My code is as follows:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
String script = baseUrl + "UIConfigurator/includes/js/DataCaptureFramework.js";
try {
LOGGER.info("evaluating engine");
LOGGER.info(script);
URL url1 = new URL(script);
LOGGER.info("url1 "+url1.getPath()+url1);
BufferedReader in = new BufferedReader(
new InputStreamReader(url1.openStream()));
String inputLine = null;
StringBuffer buffer = new StringBuffer();
while ((inputLine = in.readLine()) != null)
buffer.append(inputLine);
LOGGER.info(buffer.toString());
engine.eval(buffer.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
LOGGER.error(e.toString());
LOGGER.error("Throwing error in the catch part");
}
Invocable inv = (Invocable) engine;
try {
LOGGER.info("invoking function");
inv.invokeFunction("displayDataCapturePopUp("+user.getOrgId()+","+user.getId()+","+session.getLoginType()+");");
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ScriptException e) {
// TODO Auto-generated catch block
LOGGER.error("throwing error in catch block of invoking engine and function");
}
When I run this code it gives me the following error:
11:53:50,847 ERROR [Login] javax.script.ScriptException:
sun.org.mozilla.javascript.internal.EcmaError: ReferenceError:
"jQuery" is not defined. (#1) in at
line number 1 11:53:50,847 ERROR [Login] Throwing error in the catch
part 11:53:50,848 INFO [Login] invoking function 11:53:50,848 ERROR
[STDERR] java.lang.NoSuchMethodException: no such method:
displayDataCapturePopUp(301,1373864,0);
I tried a lot of things but still cannot get rid of this. Please tell me what I'm doing wrong. I'm trying to call the below function from JavaScript.
function displayDataCapturePopUp(orgId,userId,loginTypeId){ jQuery(" <link/>", {rel: "stylesheet",type: "text/css",href:
"/UIConfigurator/includes/css/librarycss/jquery-ui.min.css"}).appendTo("head"); jQuery("<link/>", {rel: "stylesheet",type: "text/css",href:
"/UIConfigurator/includes/css/DataCaptureFramework.css"}).appendTo("head"); jQuery("<link/>", {rel: "stylesheet",type: "text/css",href:
"/UIConfigurator/includes/css/librarycss/tooltipster.css"}).appendTo("head"); jQuery("<link/>", {rel: "stylesheet",type: "text/css",href:
"/UIConfigurator/includes/css/librarycss/jquery.alerts.css"}).appendTo("head");
jQuery.getScript('/UIConfigurator/includes/js/UiAjaxInteraction.js',function() {
jQuery.getScript('/iONjsLib/js/jquery-ui-1.10.4.min.js',function() {
jQuery.getScript('/iONjsLib/js/jquery.tooltipster.min.js',function() {
jQuery.getScript('/UIConfigurator/includes/js/libraryjs/jquery.alerts.js',function() {
jQuery.getScript('/iONjsLib/js/jquery.blockUI.js',function() {
getDataCapturePopUpDetails(orgId,userId,loginTypeId); }
);
}
);
}
);
}
);
}
);
}
ScriptEngine runs JavaScript in an entirely separate environment, with no access to your browser. It looks like you're trying to use it to show some kind of popup in your browser; this will not work. If you need to control your browser remotely, you need to use a different API, not ScriptEngine.
I have to call a javascript function named function startPolling() and created into hill.js file (/Demo MM/src/main/webapp/static/assets/js/hill.js) from java code. How can i do?Thanks
I'm using this code but receive exception
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
if (!(engine instanceof Invocable)) {
System.out.println("Invoking methods is not supported.");
return "500";
}
Invocable inv = (Invocable) engine;
String scriptPath = "/Demo MM/src/main/webapp/static/assets/js/hill.js";
try {
engine.eval("load('" + scriptPath + "')");
} catch (ScriptException e) {
return "500";
}
Make sure you are in the correct working directory to begin with. I get your code working.
To output working directory:
System.out.println("Working Directory = " +
System.getProperty("user.dir"));