This is a continuation of my original post here: javascript-to-java-applet-using-deployjava-js-to-run-commandline
I am pretty new to Java. I want to create a Java Applet that will allow my JavaScript to pass a commandline to the Java Applet. This will only ever be run on my development machine - no need to remind me what a security issue that is. The use-case is that I have an introspector for my ExtJS app that allows me to display the classes. I want to be able to click a class, pass the relevant pathname to the Applet and have that file open in Eclipse for editing.
After many failed tests this is what I found works. Thanks to Andrew Thompson and others mentioned below.
It seems there are two paths and I have managed to get them both working. I include them both here. Path 1 is to execute a program with parameters (eg D:/Eclipse/eclipse.exe --launcher.openFile C:/sites/test.js
) and Path 2 is to set Win7 to open Eclipse when a *.js file is opened (ie associate *.js with Eclipse).
SECURITY DISCLAIMER: Remember that Path 1 is completely insecure on a public server - it would be relatively easy to pass a format or delete command or any other mischief via the JavaScript!!
For Java newbies like me I will be as explicit as I can about the steps.
Class for executing programs. Thank you to: https://stackoverflow.com/users/80389/corgrath
package systemcmd;
import java.applet.Applet;
import java.io.*;
public class Runcmd extends Applet {
private static final long serialVersionUID = 1L;
public void init() {
// It seems that even though this command is not executed when the
// applet is run via JS we still need to refer to the exec command here,
// I presume so it is linked? If I comment these out altogether, the
// applet doesnt work. Either of the following will suffice.
// FYI. Just betraying my Java newbie status! :-)
//exec("notepad c:/sites/test.txt");
exec("calc");
}
// From https://stackoverflow.com/questions/1068271/signed-applet-gives-accesscontrolexception-access-denied-when-calling-from-jav
// Thank you !!!
public void exec(String command) {
try {
// launch EXE and grab stdin/stdout and stderr
Process process = Runtime.getRuntime().exec(getParameter("command"));
// OutputStream stdin = process.getOutputStream();
InputStream stderr = process.getErrorStream();
InputStream stdout = process.getInputStream();
// clean up if any output in stdout
String line = "";
BufferedReader brCleanUp = new BufferedReader(new InputStreamReader(stdout));
while ((line = brCleanUp.readLine()) != null) {
//System.out.println ("[Stdout] " + line);
}
brCleanUp.close();
// clean up if any output in stderr
brCleanUp = new BufferedReader(new InputStreamReader(stderr));
while ((line = brCleanUp.readLine()) != null) {
//System.out.println ("[Stderr] " + line);
}
brCleanUp.close();
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
Class for running programs associated with files:
package systemcmd;
import java.applet.Applet;
import java.awt.Desktop;
import java.io.*;
public class Launchapp extends Applet {
private static final long serialVersionUID = 1L;
public void init() {
// It seems that even though this command is not executed when the
// applet is run via JS we still need to refer to the exec command here,
// I presume so it is linked? If I comment these out altogether, the
// applet doesnt work. Either of the following will suffice.
// FYI. Just betraying my Java newbie status! :-)
//launch("notepad c:/sites/test.txt");
launch("calc");
}
// From https://stackoverflow.com/questions/1068271/signed-applet-gives-accesscontrolexception-access-denied-when-calling-from-jav
// Thank you !!!
public void launch(String command) {
try {
Desktop.getDesktop().open(new File(getParameter("command")));
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
Using Eclipse, I exported those two classes to one jar file called runcombo.jar located in the same folder as the following HTML file. I then self signed the jar which is necessary for the security issues also. I found this tutorial helpful with that process. http://www.jade-cheng.com/uh/ta/signed-applet-tutorial/.
The HTML and JavaScript test page:
<html>
<head>
<script type="text/javascript">
function exec( command ) {
var applet = "<object type='application/x-java-applet' height='100' width='100' name='jsApplet'><param name='code' value='systemcmd.Runcmd'/><param name='archive' value='runcombo.jar' /><param name='mayscript' value='true'/><param name='command' value='" + command + "'/>Applet failed to run. No Java plug-in was found.</object>";
var body = document.getElementsByTagName("body")[0];
var div = document.createElement("div");
div.innerHTML = applet;
body.appendChild(div);
}
function launch( command ) {
var applet = "<object type='application/x-java-applet' height='100' width='100' name='jsApplet'><param name='code' value='systemcmd.Launchapp'/><param name='archive' value='runcombo.jar' /><param name='mayscript' value='true'/><param name='command' value='" + command + "'/>Applet failed to run. No Java plug-in was found.</object>";
var body = document.getElementsByTagName("body")[0];
var div = document.createElement("div");
div.innerHTML = applet;
body.appendChild(div);
}
</script>
</head>
<body>
<a href="#" onclick="exec('notepad c:/sites/test.txt');">Exec Notepad</a>
<br> <a href="#" onclick="exec('calc');">Exec Calculator</a>
<br> <a href="#" onclick="exec('D:/Eclipse/eclipse.exe --launcher.openFile C:/sites/test.js');">Exec Eclipse with command line parms</a>
<br> <a href="#" onclick="launch('C:/sites/test2.txt');">Launch Notepad via *.txt association</a>
<br> <a href="#" onclick="launch('C:/sites/test2.js');">Launch Eclipse via *.js association</a>
</body>
</html>
Note that the applet is added to the DOM when the JS functions are called. This is part of working with the Java security and avoids the aforementioned security issues that stopped the applet from running. Note also that there are two JS function calls to match the different classes.
Thanks again to everyone who helped my get this working. Now I can get back to the original purpose - to finish my Ext Introspector!
Murray