JavaScript 到 Java 小程序 - 工作
这是我原帖的延续:javascript-to-java-applet-using-deployjava-js-to-run-commandline
我对 Java 还很陌生.我想创建一个 Java Applet,它允许我的 JavaScript 将命令行传递给 Java Applet.这只会在我的开发机器上运行 - 无需提醒我这是什么安全问题.用例是我的 ExtJS 应用程序有一个内省器,它允许我显示类.我希望能够单击一个类,将相关路径名传递给 Applet,然后在 Eclipse 中打开该文件进行编辑.
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.
经过多次失败的测试后,我发现这是可行的.感谢 Andrew Thompson 和下面提到的其他人.
After many failed tests this is what I found works. Thanks to Andrew Thompson and others mentioned below.
似乎有两条路径,我已经设法让它们都正常工作.我把他们都包括在这里.路径1是执行带有参数的程序(例如D:/Eclipse/eclipse.exe --launcher.openFile C:/sites/test.js
),路径2是设置Win7打开Eclipse当一个 *.js 文件被打开时(即将 *.js 与 Eclipse 关联).
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).
安全免责声明:请记住,路径 1 在公共服务器上是完全不安全的 - 通过 JavaScript 传递格式或删除命令或任何其他恶作剧相对容易!!
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!!
对于像我这样的 Java 新手,我会尽可能明确地说明步骤.
For Java newbies like me I will be as explicit as I can about the steps.
用于执行程序的类.感谢:https://stackoverflow.com/用户/80389/corgrath
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();
}
}
}
使用 Eclipse,我将这两个类导出到一个名为 runcombo.jar 的 jar 文件,该文件与以下 HTML 文件位于同一文件夹中.然后我对 jar 进行了自我签名,这也是安全问题所必需的.我发现本教程对这个过程很有帮助.http://www.jade-cheng.com/uh/ta/signed-applet-tutorial/.
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/.
HTML 和 JavaScript 测试页:
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>
注意小程序是在调用JS函数的时候添加到DOM中的.这是使用 Java 安全性的一部分,可以避免上述导致小程序停止运行的安全问题.还要注意,有两个 JS 函数调用来匹配不同的类.
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.
再次感谢所有帮助我完成这项工作的人.现在我可以回到最初的目的——完成我的 Ext Introspector!
Thanks again to everyone who helped my get this working. Now I can get back to the original purpose - to finish my Ext Introspector!
穆雷
你不需要每次都创建一个新的applet实例,使用applet的mayscript标签就可以告诉浏览器允许java script与applet通信.
you do not need to make a new instance of the applet every time, using the mayscript tag for applet you can tell the browser to allow java script to applet communication.
你也应该清理init方法
Also you should clean up the init method
<head>
<script type="text/javascript">
//whatToDo can be from an input box
//in applet check if its del or rmdir or move or delete at a minimum
function callJavaCmd (whatToDo) {
// call the MessageBox method of the applet
var applet = document.getElementById ("myApplet");
applet.command (whatToDo);
}
</script>
</head>
<body>
<applet id="myApplet" code="Your.class" codebase="/base/"
mayscript="mayscript" style="width:300px; height:50px;">
</applet>
参考 http://help.dottoro.com/lhbkaqko.php 和 http://docs.oracle.com/javase/6/docs/technotes/guides/plugin/developer_guide/java_js.html 旧的 netscape 类是每个 JVM (netscape.javascript.) 的一部分
Ref http://help.dottoro.com/lhbkaqko.php and http://docs.oracle.com/javase/6/docs/technotes/guides/plugin/developer_guide/java_js.html The old netscape classes are part of every JVM (netscape.javascript.)