星期五, 10月 29, 2004

Embedded a Scripting Engine in Java Apps

在開發應用系統時,使用者有時往往會需要動態地執行程序或更新某些參數。
例如像是電信業的計費公式為了因應三不五時要推出特惠方案而更動、
或是銀行業核准信用貸款的判斷準則等。

但這個時候您可能又不想大費周章地自已搞一套Parser
來解析處理這些公式或規則,
嘿嘿~那麼最好的選擇就是內嵌一個Scripting Engine進來。
而且目前開源項目中已有許多使用Java實作出來各種語法的
Scripting Engine可供我們選擇囉~

更棒的是不但如此,大部份開放源碼的Scripting Engine
還支援了BSF(Bean Scripting Framework)。
http://jakarta.apache.org/bsf/index.html
不過講起來Java的世界就這點很奇怪,Framework特別多,
啥米東東不來個Framework這些人身上好像是會癢 :p

好了~再廢話我怕您會想扁我。言歸正傳…而這個BSF又是個啥米東東哩?
簡單講嘛沒啥就是提供一個共通的介面
將各家不同實作的Scripting Engine包裝起來。
於是乎我們可以很輕易地在系統中切換各種不同Scripting語法,
不過有個前提是這些Scripting Engine有支援BSF。

如此一來便可輕鬆提供多種不同語法供使用者選擇,
這一點相信可帶給系統使用者很大的便利。
甚或是我們可以內建一些predefine function
讓使用者能更直覺地用邏輯概念來組合出其所需的功能出來。

下面介紹一下,小弟實驗過確認可在BSF下執行正常的幾個Scripting Engine:

Rhino: JavaScript for Java

http://www.mozilla.org/rhino/index.html

註記:
雖說目前FAQ上寫支援BSF的版本為Rhino 1.5R2 or Rhino 1.5R3。
但經實測似乎只有Rhino 1.5R2這版可運行正常。


JRuby: Ruby for Java

http://jruby.sourceforge.net/index.shtml


Jython: Python for Java

http://www.jython.org/index.html


BeanShell: Lightweight Scripting for Java

http://www.beanshell.org

註記:
若是您覺得您不太想去重新學習或適應另一套Scripting語法,
想使用一個支援Java語法的Scripting Engine的話。
您可以選擇使用BeanShell。


最後提供一個Expression Evaluator的範例程式,大家可以參考試試看囉 ^_^
對了!!!執行前要記得將各個要用到的
Scripting Engine相對應的jar檔設定到classpath下喔~

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.apache.bsf.*;

public class ExpressionEvaluator
extends JFrame implements java.awt.event.ActionListener {
private JPanel ivjContentsPane = null;
private BorderLayout ivjContentsPaneBorderLayout = null;
private JLabel ivjLabel1 = null;
private JPanel ivjPanel1 = null;
private GridLayout ivjPanel1GridLayout = null;
private JPanel ivjPanel2 = null;
private BorderLayout ivjPanel2BorderLayout = null;
private JPanel ivjPanel3 = null;
private GridLayout ivjPanel3GridLayout = null;
private JPanel ivjPanel4 = null;
private JButton ivjButtonClearResults = null;
private JButton ivjButtonClearScript = null;
private JButton ivjButtonEvaluate = null;
private JComboBox ivjLanguageChoice = null;
private JTextArea ivjTextAreaResults = null;
private JTextArea ivjTextAreaScript = null;
private String language = "javascript";
BSFManager _mgr = null;
Hashtable _htEngines = null;

public ExpressionEvaluator() {
super();
initialize();
}

public ExpressionEvaluator(String title) {
super(title);
initialize();
}

public void actionPerformed(java.awt.event.ActionEvent e) {
if ( (e.getSource() == getButtonClearResults())) {
try {
getTextAreaResults().setText("");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

}
if ( (e.getSource() == getButtonEvaluate())) {
try {
this.buttonEvaluateClick();
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

}
if ( (e.getSource() == getButtonClearScript())) {
try {
getTextAreaScript().setText("");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

}

}

public void buttonEvaluateClick() {
evaluate();
}

public void evaluate() {

language = getLanguageChoice().getName();
String scriptText = getTextAreaScript().getText();

System.out.println("Evaluating: {\n" + scriptText + "\n}");
System.out.println("Language: " + language);
Object oResult = null;
try {
getTextAreaResults().setForeground(java.awt.Color.black);
oResult = _mgr.eval(language, "Evaluator", 0, 0, scriptText);
}
catch (Exception ex) {
getTextAreaResults().setForeground(java.awt.Color.red);
oResult = "Exception: " + ex.getMessage();
ex.printStackTrace();
}
System.out.println("oResult:’" + oResult + "’");
getTextAreaResults().setText(oResult.toString());
}

private JButton getButtonClearResults() {
if (ivjButtonClearResults == null) {
try {
ivjButtonClearResults = new JButton();
ivjButtonClearResults.setName("ButtonClearResults");
ivjButtonClearResults.setText("Clear results");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjButtonClearResults;
}

private JButton getButtonClearScript() {
if (ivjButtonClearScript == null) {
try {
ivjButtonClearScript = new JButton();
ivjButtonClearScript.setName("ButtonClearScript");
ivjButtonClearScript.setText("Clear script");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjButtonClearScript;
}

private JButton getButtonEvaluate() {
if (ivjButtonEvaluate == null) {
try {
ivjButtonEvaluate = new JButton();
ivjButtonEvaluate.setName("ButtonEvaluate");
ivjButtonEvaluate.setBackground(Color.lightGray);
ivjButtonEvaluate.setText("Evaluate");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjButtonEvaluate;
}

private JPanel getContentsPane() {
if (ivjContentsPane == null) {
try {
ivjContentsPane = new JPanel();
ivjContentsPane.setName("ContentsPane");
ivjContentsPane.setLayout(getContentsPaneBorderLayout());
ivjContentsPane.setBackground(new Color(172, 179, 191));
getContentsPane().add(getPanel2(), "North");
getContentsPane().add(getPanel1(), "Center");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjContentsPane;
}

private java.awt.BorderLayout getContentsPaneBorderLayout() {
java.awt.BorderLayout ivjContentsPaneBorderLayout = null;
try {
ivjContentsPaneBorderLayout = new java.awt.BorderLayout();
ivjContentsPaneBorderLayout.setVgap(10);
ivjContentsPaneBorderLayout.setHgap(10);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

return ivjContentsPaneBorderLayout;
}

public BSFEngine getEngine(String langname) {
if (_htEngines != null) {
return (BSFEngine) (_htEngines.get(langname));
}
return null;
}

private JLabel getLabel1() {
if (ivjLabel1 == null) {
try {
ivjLabel1 = new JLabel();
ivjLabel1.setName("Label1");
ivjLabel1.setFont(new java.awt.Font("dialog", 1, 12));
ivjLabel1.setText("Language");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjLabel1;
}

private JComboBox getLanguageChoice() {
if (ivjLanguageChoice == null) {
try {
ivjLanguageChoice = new JComboBox();
ivjLanguageChoice.setName("javascript");
ivjLanguageChoice.setBackground(Color.white);
ivjLanguageChoice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox) e.getSource();
ivjLanguageChoice.setName( (String) cb.getSelectedItem());

}
});
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjLanguageChoice;
}

private JPanel getPanel1() {
if (ivjPanel1 == null) {
try {
ivjPanel1 = new JPanel();
ivjPanel1.setName("Panel1");
ivjPanel1.setLayout(getPanel1GridLayout());
getPanel1().add(getTextAreaScript(),
getTextAreaScript().getName());
ivjPanel1.add(getTextAreaResults());
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjPanel1;
}

private java.awt.GridLayout getPanel1GridLayout() {
java.awt.GridLayout ivjPanel1GridLayout = null;
try {
ivjPanel1GridLayout = new java.awt.GridLayout(2, 1);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

return ivjPanel1GridLayout;
}

private JPanel getPanel2() {
if (ivjPanel2 == null) {
try {
ivjPanel2 = new JPanel();
ivjPanel2.setName("Panel2");
ivjPanel2.setLayout(getPanel2BorderLayout());
getPanel2().add(getPanel3(), "South");
getPanel2().add(getPanel4(), "North");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjPanel2;
}

private java.awt.BorderLayout getPanel2BorderLayout() {
java.awt.BorderLayout ivjPanel2BorderLayout = null;
try {
ivjPanel2BorderLayout = new java.awt.BorderLayout();
ivjPanel2BorderLayout.setVgap(5);
ivjPanel2BorderLayout.setHgap(5);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

return ivjPanel2BorderLayout;
}

private JPanel getPanel3() {
if (ivjPanel3 == null) {
try {
ivjPanel3 = new JPanel();
ivjPanel3.setName("Panel3");
ivjPanel3.setLayout(getPanel3GridLayout());
getPanel3().add(getButtonEvaluate(),
getButtonEvaluate().getName());
getPanel3().add(getButtonClearScript(),
getButtonClearScript().getName());
getPanel3().add(getButtonClearResults(),
getButtonClearResults().getName());
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjPanel3;
}

private java.awt.GridLayout getPanel3GridLayout() {
java.awt.GridLayout ivjPanel3GridLayout = null;
try {
ivjPanel3GridLayout = new java.awt.GridLayout();
ivjPanel3GridLayout.setColumns(3);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}

return ivjPanel3GridLayout;
}

private JPanel getPanel4() {
if (ivjPanel4 == null) {
try {
ivjPanel4 = new JPanel();
ivjPanel4.setName("Panel4");
ivjPanel4.setLayout(new java.awt.BorderLayout());
getPanel4().add(getLabel1(), "West");
getPanel4().add(getLanguageChoice(), "Center");
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjPanel4;
}

private JTextArea getTextAreaResults() {
if (ivjTextAreaResults == null) {
try {
ivjTextAreaResults = new JTextArea();
ivjTextAreaResults.setName("TextAreaResults");
ivjTextAreaResults.setBackground(Color.lightGray);
ivjTextAreaResults.setFont(new java.awt.Font(
"monospaced", 1, 12));
ivjTextAreaResults.setEditable(false);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjTextAreaResults;
}

private JTextArea getTextAreaScript() {
if (ivjTextAreaScript == null) {
try {
ivjTextAreaScript = new JTextArea();
ivjTextAreaScript.setName("TextAreaScript");
ivjTextAreaScript.setBackground(Color.white);
ivjTextAreaScript.setEditable(true);
}
catch (java.lang.Throwable ivjExc) {
handleException(ivjExc);
}
}
return ivjTextAreaScript;
}

private void handleException(Throwable exception) {

System.out.println(
"--------- UNCAUGHT EXCEPTION ---------");
exception.printStackTrace(System.out);
}

private void initConnections() {
getButtonClearResults().addActionListener(this);
getButtonEvaluate().addActionListener(this);
getButtonClearScript().addActionListener(this);
}

private void initialize() {
setName("ExpressionEvaluator");
setTitle("BSF Expression Evaluator");
setSize(426, 240);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cp = this.getContentPane();

cp.setLayout(new BorderLayout());
cp.setBackground(new java.awt.Color(228, 223, 228));
cp.setForeground(new java.awt.Color(0, 48, 104));
cp.add(getContentsPane(), "Center");

initConnections();
initializeBSF();
}

protected void initializeBSF() {
if (_mgr == null) {

System.out.println("Initializing");
_mgr = new BSFManager();
_mgr.registerScriptingEngine("", "", new String[] {});
getLanguageChoice().addItem("javascript");
getLanguageChoice().addItem("ruby");
getLanguageChoice().addItem("jython");
getLanguageChoice().addItem("beanshell");
}
}

public static void main(java.lang.String[] args) {
try {
ExpressionEvaluator aExpressionEvaluator = new
ExpressionEvaluator();
aExpressionEvaluator.setVisible(true);
}
catch (Throwable exception) {
exception.printStackTrace();
}
}
}

沒有留言: