How to wait for user action in Sparkle updater(java app)? - java

So I have SparkleAcrivator class
public class SparkleActivator {
private static boolean sparkleLibLoaded = false;
//private String downloadLink;
private String menuItemTitle;
public native static void initSparkle(String pathToSparkleFramework,
boolean updateAtStartup,
int checkInterval,
/*String downloadLink,*/
String menuItemTitle);
private boolean updateAtStartup = true;
private int checkInterval = 86400;
public SparkleActivator(/*String downloadLink, */String menuItemTitle) {
//this.downloadLink = downloadLink;
this.menuItemTitle = menuItemTitle;
}
public void start() throws Exception {
try {
if(!SparkleActivator.sparkleLibLoaded) {
System.loadLibrary("sparkle_init");
SparkleActivator.sparkleLibLoaded = true;
}
} catch (Exception ex) {
ex.printStackTrace();
return;
}
initSparkle(System.getProperty("user.dir") + "/../../Frameworks/Sparkle.framework",
updateAtStartup, checkInterval, /*downloadLink, */menuItemTitle);
}
}
And main class where I start my standalone application and use Sparkle
public static void main(final String... args) {
if (Helper.isOsx()) {
try {
sparkleActivator.start();
} catch (Exception e) {
new ExceptionHandler(true, 19).handleException(new NotFountSparkleInitException());
return;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
initApp();
}
});
}
else {
}
There problem is Sparkle and my app starts almost simultaneously, but I need wait for action from user in Sparkle window and then start my app.
Thank for any help.

What we know is that Sparkle updater requires to be called on the main thread (i.e. GUI thread). Therefore, your app needs to be running to call it. I don't think there is an obvious way to solve this problem. However,...
One way that you can circumvent the issue is to set your app's visibility to false until the user has finished interacting with your updater.
For example, you can add an event listener to your JNI or add listeners to your updater thread. However, the listener on the thread needs to return on user actions instead of when finished.

Related

Generic Thread which could be paused/resumed and execute user's Runnable Actions

AIM : To make a generic Thread class that is independent of the parent calling it, can be started/stopped/paused/resumed by the parent class calling it and perform user defined tasks (via runnable)
MY RESEARCH :
SO_1
SO_2
SO_3
SO_4
SO_5
SomeBlog
SomeBlog2
OracleBlog
Problem : from what i have understood:
Starting a background thread: threadObj.start() will execute statements of run() function of a class implementing Runnable Interface.
Stopping a background thread : threadObj.interrupt() will stop a thread from executing
Pausing a thread : threadObj.wait() will pause the thread,although, it requires additional synchronised lock mechanism
Resuming a thread :threadObj.notifyAll() will release resume the object, after handling the synchronised lock mechanism
Thus based on this, i wrote a generic Thread class that is supposed to run a user's set of tasks and play/pause/resume/stop via ui buttons, BUT ITS NOT WORKING:
Generic Thread.java
public class PausibleThread extends Thread {
public static final String TAG ="PausibleThread>>";
#Nullable
PausibleRunnable runnable ;
public PausibleThread(#Nullable Runnable target) {
super(target);
PausibleRunnable r = new PausibleRunnable(target);
runnable=r;
}
#Override
public synchronized void start() { super.start(); }
public synchronized void stopThread(){ this.interrupt(); }
public synchronized void pauseThread(){ runnable.pause(); }
public synchronized void resumeThread(){ runnable.resume(); }
PausibleRunnable.java:
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class PausibleRunnable implements Runnable {
private Object lockerObject;
private boolean isPaused;
private boolean isFinished;
public static final String TAG="PausibleRunnable";
#Nullable
Runnable usrAction = null;
public PausibleRunnable(#NonNull Runnable usrAction) {
lockerObject = new Object();
isPaused = false;isFinished = false;
this.usrAction = usrAction;
}
public void run() {
while (!isFinished) {
if(isPaused) {
runPauseLoop();
}
else {
runUserAction();
isFinished=true;
}
}
}
private void runPauseLoop() {
synchronized (lockerObject) {
while (isPaused) {
try { lockerObject.wait(); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
private void runUserAction() {
if(usrAction !=null){ usrAction.run(); }
else { Log.e(TAG, "run: userAction is NULL" ); }
}
public void pause() {
synchronized (lockerObject) { isPaused = true; }
}
public void resume() {
synchronized (lockerObject) {
isPaused = false;
lockerObject.notifyAll();
}
}
}
Ui creating a Pausible Thread and implementing various functions of it:
//full class implementation at : https://paste.ubuntu.com/p/cTpW5Wt3Fy/
int totalRunTime = 20 * 5;
Pausible thread bgThread;
private void initThread() {
Runnable r = () -> {
try {
while (totalRunTime > 0) {
Thread.sleep(500);
totalRunTime--;
updateUi();
}
}
catch (Exception e) { e.printStackTrace(); }
};
bgThread = new PausibleThread(r);
}
private void updateUi() {
String data = "TotalRunTime=" + totalRunTime;
runOnUiThread(() -> tvTerminal.setText(data));
}
#Override
public void onClick(View v) {
if (bgThread == null) {
makeShortToast("Can't perform action, bg thread is null");
return;
}
if (v.getId() == fabPause.getId()) {bgThread.pauseThread(); }
else if (v.getId() == fabResume.getId()) { bgThread.resumeThread(); }
else if (v.getId() == fabStop.getId()) { bgThread.stopThread(); }
else if (v.getId() == fabStart.getId()) { bgThread.start(); }
}
But this does not work. Why? I am taking a wild guess here, but i think the runnable is only running user's action to run a big sized loop and not repeatedly checking for play/pause. So what am i supposed to do?
ui sample image : https://i.imgur.com/kmj3Bwt.png
You asked: "But this doesn't work. Why?"
I answer:
Your solution does not work because you are always running in the loop inside runUserAction. You never break out of that loop to check if you are paused.
I'm afraid you'll have to remodel your solution to run usrAction in shorter loops, otherwise you will either lose state (assuming you interrupt that loop from outside), which will end up in undefined behavior, OR you will only break out of it when it's over, OR you'll pause your loop at states you don't really want to pause at [e.g. while making a network call -- after resumed you'll get a SocketTimeoutException].
I'd suggest you to go with the former approach as it's more elegant.
Edit:
Another possible solution: every iteration inside the usrAction check for PausableThread's state, i.e. see whether it's paused, stopped or whatever.
Try this:
PausableRunnable.java
public synchronized boolean canContinue() throws Exception {
synchronized (lockerObject) {
if (isPaused) {
lockerObject.wait();
}
if (isFinished) {
return false;
}
return true;
}
}
PausableThread.java
public boolean canContinue() throws Exception {
return runnable.canContinue();
}
and the Application.java
private void initThread() {
Runnable r = () -> {
try {
while (totalRunTime > 0) {
if (bgThread.canContinue()) { // <--- !!!!!!
Thread.sleep(200);
totalRunTime--;
updateUi();
}
}
}
catch (Exception e) { e.printStackTrace(); }
};
bgThread = new PausibleThread(r);
}
This way you can run your application Runnable and still obey PausableThread's states at the times the runnable can tollereate. I.e. before/after transaction or other piece of calculation that is not supposed to be interrupted.
Edit 2:
feel free to lose ´synchronized´ modifier on methods like pause or resume, since you are already operating inside synchronized blocks in them.

remove ListenerAdapter with a timer

so I have the following problem, I want to make a minigame on a text channel, the problem is, I want to create some sort of timeout so that people don't create multiple "listenerAdapter" instances that will just overload the bot.
the command I use to load my game event (ListenerAdapter is as follows).
#Override
public void handle(List<String> args, GuildMessageReceivedEvent event) {
// TODO Auto-generated method stub
TextChannel channel = event.getChannel();
channel.sendMessage("please type \"joingame\" to join! ").queue();
event.getJDA().addEventListener(new MinigameEvent(channel, event.getAuthor(), event));
}
then , the code I use for loading players in, is the following:
public class MinigameEvent extends ListenerAdapter {
private final long channelId, authorId;
private final int players=3;
private ArraySet<User> users;
private String textMsg;
private Message target;
private GuildMessageReceivedEvent outTimerEvent;
private boolean cancelEvent;
public MinigameEvent(MessageChannel channel, User author, GuildMessageReceivedEvent outTimerEvent) {
this.channelId = channel.getIdLong();
this.authorId = author.getIdLong();
this.outTimerEvent=outTimerEvent;
cancelEvent=false;
this.timeOut(channel);
users=new ArraySet<User>();
users.add(author);
textMsg=("registered users: "+author.getName());
channel.sendMessage(textMsg).queue((new Consumer<Message>()
{
#Override
public void accept(Message t)
{
target = t;
}
}));
}
#Override
public void onMessageReceived(MessageReceivedEvent event) {
if(event.getAuthor().isBot()) {
return;
}
//not respond on other channels
if (event.getChannel().getIdLong() != channelId) {
return;
}
MessageChannel channel = event.getChannel();
String content = event.getMessage().getContentRaw();
if(content.equalsIgnoreCase("joingame")) {
users.add(event.getAuthor());
textMsg=textMsg+", "+event.getAuthor().getName();
target.editMessage(textMsg).queue();
if(users.size()==players) {
event.getChannel().sendMessage("starting").queue();
event.getJDA().removeEventListener(this);
}
}
if(content.equalsIgnoreCase("cancel") && event.getAuthor().getIdLong()==authorId) {
cancelEvent=true;
event.getJDA().removeEventListener(this);
event.getChannel().sendMessage("this game has been canceled").queue();
}
}
private void timeOut(MessageChannel channel) {
Timer timer = new Timer();
TimerTask cooldown = new TimerTask() {
#Override
public void run() {
if(cancelEvent) {
return;
}
if(users.size()<players) {
outTimerEvent.getJDA().removeEventListener(this);
try {
destroyEvent();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
channel.sendMessage("not enough players, the game has been cancelled").queue();
}else {
return;
}
}
};
timer.schedule(cooldown, 10000L);
}
private void destroyEvent() throws Throwable {
this.finalize();
}
}
when I get to 3 people, the Listener adapter stops working as intended, also when the author of the event (the one who used the !minigame command) types cancel. but when the timer goes off, it sends the message indicating the game has been cancelled, but the listener adapter is still running, if someone tries to join after, it will allow him to do so.
I currently solved the issue by using the finalize method, but I thought that you could just do something like event.getJDA().removeEventListener(this);
Your problem is that your this refers to the nearest class declaration. In this case this is the anonymous class created by your new TimeTask() { .... To refer to the outer class which actually is registered as the listener you have to use MinigameEvent.this instead.
Read More
I would highly recommend using a lambda expression instead which doesn't have this problem. Another thing to note is your use of timer which will result in thread leaks because they are never shutdown by your code (How to cleanup a timer). Even better would be to use a single ScheduledExecutorService which you should re-use to schedule everything you need rather than creating a new one for every task. This can then be shutdown once your process ends (like the onShutdown event in JDA which is fired when shutdown() is called).

BlackBerry class equivalent to AsyncTask?

My requirement is to have a thread that maintains a socket connection between a BlackBerry device and a server and exchanges commands, similar to request and response.
My problem is that I need to have this thread running in the background all the time and keep the UI available to the user. So, when there is a command from the server, this thread parses it and updates the UI and also if there's an action from the BlackBerry user, it sends it to the server and the server in turn handles it.
I developed the same application in Android using AsyncTask and it's working well. But in BlackBerry, as there's no such class, I used the invokeLater() option. The communication works fine between the server and the BB device, but the UI is frozen on the BlackBerry.
Anyone have any idea how to get this right?
Vishal is on the right track, but a little more is needed to match Android's AsyncTask. Since enums and generics aren't available with Java 1.3 on BlackBerry, you can't match the Android API perfectly.
But, you could do something like this (not tested ... this is just a starting point for you):
import net.rim.device.api.ui.UiApplication;
public abstract class AsyncTask {
public static final int FINISHED = 0;
public static final int PENDING = 1;
public static final int RUNNING = 2;
private int _status = PENDING;
private boolean _cancelled = false;
private Thread _worker;
/** subclasses MUST implement this method */
public abstract Object doInBackground(Object[] params);
protected void onPreExecute() {
// default implementation does nothing
}
protected void onPostExecute(Object result) {
// default implementation does nothing
}
protected void onProgressUpdate(Object[] values) {
// default implementation does nothing
}
protected void onCancelled() {
// default implementation does nothing
}
protected void onCancelled(Object result) {
onCancelled();
}
public final int getStatus() {
return _status;
}
public final boolean isCancelled() {
return _cancelled;
}
public final boolean cancel(boolean mayInterruptIfRunning) {
if (_status == FINISHED || _cancelled) {
return false;
} else {
_cancelled = true;
if (mayInterruptIfRunning && _status == RUNNING) {
// NOTE: calling Thread.interrupt() usually doesn't work
// well, unless you don't care what state the background
// processing is left in. I'm not 100% sure that this is how
// Android's AsyncTask implements cancel(true), but I
// normally just cancel background tasks by letting the
// doInBackground() method check isCancelled() at multiple
// points in its processing.
_worker.interrupt();
}
return true;
}
}
protected final void publishProgress(final Object[] values) {
// call back onProgressUpdate on the UI thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
onProgressUpdate(values);
}
});
}
private void completeTask(final Object result) {
// transmit the result back to the UI thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
// TODO: not sure if status should be FINISHED before or after onPostExecute()
_status = FINISHED;
}
});
}
public AsyncTask execute(final Object[] params) throws IllegalStateException {
if (getStatus() != PENDING) {
throw new IllegalStateException("An AsyncTask can only be executed once!");
} else {
try {
onPreExecute();
_worker = new Thread(new Runnable() {
public void run() {
try {
// run background work on this worker thread
final Object result = doInBackground(params);
completeTask(result);
} catch (Exception e) {
// I believe if Thread.interrupt() is called, we'll arrive here
completeTask(null);
}
}
});
_status = RUNNING;
_worker.start();
} catch (Exception e) {
// TODO: handle this exception
}
}
return this;
}
}
Also, it's important to keep in mind the Threading Rules for Android's AsyncTask, which apply to the above implementation, too:
Threading rules
There are a few threading rules that must be followed
for this class to work properly:
The AsyncTask class must be loaded on the UI thread. This is done
automatically as of JELLY_BEAN.
The task instance must be created on
the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result),
doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a
second execution is attempted.)
You can create a Class that extends my implementation of class AsyncTask. Good Luck :)
Here the methods onPreExecute, onPostExecute are executed on UI thread and doInBackground is called on worker thread. Since onPreExecute, onPostExecute are abstract you can override them and provide your implementation like showing and dismissing progress dialog.
The sequence in which methods get's executed is
1) onPreExecute
2) doInBackground
3) onPostExecute
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
public abstract class AsyncTask {
Runnable runnable;
Thread threadToRun;
public abstract void onPreExecute();
public abstract void onPostExecute();
public abstract void doInBackground();
public void execute() {
try {
runnable = new Runnable() {
public void run() {
// TODO Auto-generated method stub
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
// TODO Auto-generated method stub
onPreExecute();
}
});
doInBackground();
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
// TODO Auto-generated method stub
onPostExecute();
}
});
}
};
threadToRun = new Thread(runnable);
threadToRun.start();
} catch (Exception e) {
// TODO: handle exception
Dialog.alert("Async Error Occured. " + e.toString());
}
}
}

java wait() statement after catch clause

When I run the program it does not display "HIIII."
I am a novice (sort of) so please dont "hate".
Is my wait() statement wrong? Or what am I doing wrong?
Is it the ArrayIndexOutOfBounds catch clause? Please help!
[edit] oh so is it the main method?? that it doesnt do anything?
[edit] i know the wait and notify is wrong... please don't mention it.
//this is the whole class
import javax.swing.*;
import javax.swing.JOptionPane;
public class none {
static boolean game;
final static boolean on = true;
final static boolean off = false;
static boolean cheatMode;
public static void main(String[] args) {
game = on;
boolean tru = true;
try{
if(tru = Boolean.parseBoolean(args[0])){
cheatMode = on;
System.out.println("Cheats are on.");
}
}
catch(java.lang.ArrayIndexOutOfBoundsException e){
e.printStackTrace();
System.out.println("Ignore this error, it's from not running it on the command prompt.");
}
}
public class console extends Thread{
public void run(){
try{
wait();
JOptionPane.showMessageDialog(null,"HIIII");
}
catch(Exception e){
e.printStackTrace();
System.out.println("The console glitched...");
}
//hiiii
JOptionPane.showMessageDialog(null,"HIIII");
}
public class mainThingy extends Thread{
public void run() {
if(game = on)
notify();
}
}
}
}
There seems to be couple of issues
1) if(tru = Boolean.parseBoolean(args[0])){
Above statement is assignemt and not comparison. Use == operator.
2) Wait and notify should always be called from inside Synchronized blocks. Your code doesn't seem to be doing that.
I'd advise against the standard wait()-notify() structures. There are way better methods for this: the Java concurrency package.
Tutorial for Java Concurrency
API JavaDoc
JCIP, or Java Concurrency In Practice (Peierls, Bloch, Bowbeer, Holmes, Lea)
And as you seem to be in your first steps in learning Java, I'd suggest another two books:
Effective Java (Bloch)
Java puzzlers (Bloch, Gafter)
>java none true will print only Cheats are on. But your question is about printing Hiii. Isn't it ? You have got that in JOptionPane dialog inside the console class. Without initializing it how can you expect your program to print Hiii?. Also why have you written two public classes in one file ? When you are calling wait and nottify methods, you are also missing the synchronized statement. So when you start your threads console and mainThingy those will throw IllegalMonitorStateException anyways. So actually what are you trying to do ?
You main method doesn't actually start anything
wait and notify must be synchronized on the same monitor/lock
Your two threads are not sharing the same monitor/lock
if (game = on) in mainThingy is an assignment, not a check, it should be if (game == on)
UPDATE with Example
public class TestThread {
static boolean game;
final static boolean on = true;
final static boolean off = false;
static boolean cheatMode;
public static void main(String[] args) {
game = on;
boolean tru = true;
try {
if (args.length > 0) {
if (tru = Boolean.parseBoolean(args[0])) {
cheatMode = on;
System.out.println("Cheats are on.");
}
}
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
System.out.println("Ignore this error, it's from not running it on the command prompt.");
}
Console con = new Console();
con.start();
// Give time for the console thread to get started
do {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(TestThread.class.getName()).log(Level.SEVERE, null, ex);
}
} while (!con.isAlive());
System.out.println("Start main...");
Console.MainThingy main = new Console.MainThingy();
main.start();
}
public static class Console extends Thread {
// A shared lock that our two threads can communicate on...
public static final Object WAIT_LOCK = new Object();
public void run() {
try {
System.out.println("Waiting...");
// Must "own" the monitor before we can call wait
synchronized (WAIT_LOCK) {
WAIT_LOCK.wait();
}
JOptionPane.showMessageDialog(null, "HIIII");
} catch (Exception e) {
e.printStackTrace();
System.out.println("The console glitched...");
}
}
public static class MainThingy extends Thread {
public void run() {
if (game == on) {
// Must "own" the monitor before we can call notify
synchronized (WAIT_LOCK) {
System.out.println("Notify...");
WAIT_LOCK.notify();
}
}
}
}
}
}
Java Concurrency is fun, but it will bite you if you're not careful with it and treat it nicely.
Take a read through Currency in Java

Stopping the Rhino Engine in middle of execution

Does the Rhino engine have an api that can stop the execution of a
script fie in the middle. For example, I have a script file in which
there is an infinte loop. How can I stop the execution in the middle?
Of course, I can stop the jvm which started the Rhino engine to
excecute the script. But I don't want to kill the entire jvm session for that reason as i have started the script programatically and the Rhino Engine also running in the same JVM as my application.
Stopping the execution of running JavaScript can be done by using following way.
1) Create a dummy Debugger and attach it to the context created initially.
mContext = Context.enter();
ObservingDebugger observingDebugger = new ObservingDebugger();
mContext.setDebugger(observingDebugger, new Integer(0));
mContext.setGeneratingDebug(true);
mContext.setOptimizationLevel(-1);
The ObservingDebugger code looks as follows.
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.debug.DebugFrame;
import org.mozilla.javascript.debug.DebuggableScript;
import org.mozilla.javascript.debug.Debugger;
public class ObservingDebugger implements Debugger
{
boolean isDisconnected = false;
private DebugFrame debugFrame = null;
public boolean isDisconnected() {
return isDisconnected;
}
public void setDisconnected(boolean isDisconnected) {
this.isDisconnected = isDisconnected;
if(debugFrame != null){
((ObservingDebugFrame)debugFrame).setDisconnected(isDisconnected);
}
}
public ObservingDebugger() {
}
public DebugFrame getFrame(Context cx, DebuggableScript fnOrScript)
{
if(debugFrame == null){
debugFrame = new ObservingDebugFrame(isDisconnected);
}
return debugFrame;
}
#Override
public void handleCompilationDone(Context arg0, DebuggableScript arg1, String arg2) { } }
// internal ObservingDebugFrame class
class ObservingDebugFrame implements DebugFrame
{
boolean isDisconnected = false;
public boolean isDisconnected() {
return isDisconnected;
}
public void setDisconnected(boolean isDisconnected) {
this.isDisconnected = isDisconnected;
}
ObservingDebugFrame(boolean isDisconnected)
{
this.isDisconnected = isDisconnected;
}
public void onEnter(Context cx, Scriptable activation,
Scriptable thisObj, Object[] args)
{ }
public void onLineChange(Context cx, int lineNumber)
{
if(isDisconnected){
throw new RuntimeException("Script Execution terminaed");
}
}
public void onExceptionThrown(Context cx, Throwable ex)
{ }
public void onExit(Context cx, boolean byThrow,
Object resultOrException)
{ }
#Override
public void onDebuggerStatement(Context arg0) { } }
ObservingDebugger class will manage the boolean variable "isDisconnected" and when user clicks on the stop button (wants to stop the execution) then this variable is set to true. Once the variable is set to true as follows the Rhino Execution will immediately terminates.
observingDebugger.setDisconnected(true);
For anyone else looking for a solution, the javadoc for ContextFactory details how to stop a script running more than 10 seconds:
https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/ContextFactory.java
I execute scripts in a new thread using an ExecutorService and timed-out future.get
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(threadEvaluation);
try {
System.out.println("Started..");
future.get(100, TimeUnit.MILLISECONDS);
System.out.println("Finished!");
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Terminated!");
}
Notice that this approach will not stop the thread executing the script! In order to do so, as the thread executing your script will be notified to be interrupted, you can create a custom ContextFactory that monitors periodically this situation:
public class InterruptableContextFactory extends ContextFactory {
public static boolean initialized = false;
public static void init() {
if (!initialized) {
ContextFactory.initGlobal(new InterruptableContextFactory());
initialized = true;
}
}
#Override
protected void observeInstructionCount(Context cx, int instructionCount) {
System.out.println(instructionCount + " javascript instructions!");
if (Thread.currentThread().isInterrupted()) {
throw new Error("script execution aborted");
}
}
#Override
protected Context makeContext() {
Context cx = super.makeContext();
//set a number of instructions here
cx.setInstructionObserverThreshold(10000);
return cx;
}
}
Before creating any Context object, you need to configure your application to use this ContextFactory as default, just invoke
InterruptableContextFactory.init()
Inside your Callable's call method, you can capture the Error:
try {
cx.setOptimizationLevel(9);
cx.setInstructionObserverThreshold(10000);
ScriptableObject scope = cx.initStandardObjects();
// your code here
} catch (Error e) {
System.out.println("execution was aborted: " + e.getMessage());
} finally {
Context.exit();
}
The Rhino engine doesn't appear to have any mechanism for doing this (bad Rhino!) and it's hard to tell whether it creates threads internally, so the only solution you've got is to create a ThreadGroup, load and execute the Rhino engine and its script from inside a thread in that group, and when you want to kill it off, use ThreadGroup.stop(). Yes, it's deprecated but there's really no other way to do it given that there's no cooperation on the part of the Rhino library.

Categories

Resources