問題的提出:
假定我們的HTML 頁中有一些表單需要處理,並且我們需要初始化數據庫中的字段,我們該怎麼辦?標准的解決辦法就是使用CGI腳本或是使用Java Servlet等服務器端程序,但是你有沒有想過,還可以編寫一個腳本程序使你可以用JavaScript直接調用服務器端Java程序進行任何計算的結果,就像下面代碼中列的那樣:
<html>
我們的表單<br>
<form>
<input type="text" name="textField"><br>
<input type="button" value="Click" onClick="updateField();">
</form>
<script>
function updateField()
{
document.forms[0].textField.value=java.dbConnection.getData('SQL_expr');
}
</script>
</html>
所以,當用戶點擊按鈕,該程序就會調用Java的dbConnection類,然後就可以在JavaScript應用程序中使用Java返回的結果了。上面的程序只是更新了textField的值,我們不必刷新整個頁面。由於這個程序也不是JSP文件,所以不必把你的頁面編譯成Java Servlet。
你還可以使用調用某些Java函數返回的結果替代段落中的文字;在一個非常大的HTML表中,你可以使用同樣的方法,只要更新一行信息:
<script language="JavaScript">
function changeCol()
{
document.all.quote.rows[0].cells[1].innerText=java.Stock.getQuote('Wayne');
}
</script>
<table id="quote" border=1>
<tr><td>Wayne</td><td>123</td></tr>
<tr><td>Another one</td><td>34</td></tr>
</table>
怎麼樣,能夠直接在JavaScript中嵌入Java對象的調用,而且可以保證你的頁面的其它部分不會被改變,你一定對這個問題比較感興趣吧。好吧,現在就讓我們用Java Servlet來實現它吧。
工作原理
我的構思是使用Java Servlet編寫一個JinJ(Java in JavaScript)程序,能夠讓 HTML 頁面內整合 Java 類和 JavaScript腳本,將所有使用JavaScript調用Java函數的HTML頁面都傳送到這個Servlet中處理,JinJ將即時產生帶有Java applet的隱藏幀,這個applet起著橋梁的作用,用來和Java通訊,它的大小還不到2KB,為了調用對象,Applet使用HTTP連接同一個JinJ Servlet。JinJ用相應的JavaScript結構來替換所有的Java調用(其實每一個調用前都有前綴java),並且保持頁面的其它部分不變。所以,為了能夠讓JinJ正確識別,你的JavaScript代碼中的任何Java調用,都要使用如下的結構: java.object_name.function_name(list_of_parameters) 其中:
java:是一個標准的前綴:
object_name:是一個變量名,保存某些Java類的實例(在後面,我們會詳細的探討如何創建/定義這樣的變量),比如說它可以是一個類名。
function_name:是一個Java類的函數名。
list_of_parameters:是調用的函數的參數列表(可以為空)。
下面也將會探討如何把參數傳給Java,每個參數顯然是某個JavaScript表達式。你也可以使用預編譯頁,換句話說就是在使用HTML頁面之前編譯它。
服務器實現
在談編程之前我還想說一說JinJ的服務器實現。在你的服務器中需要兩個組成部分:JINJ servlet和bridge applet.。你所有需要被整合的HTML頁面都是被JinJ servlet預處理,你可以通過以下方法實現:
a)把你的頁面當作一個參數傳遞給JinJ servlet
所以你可以把你HTML頁中如下的超鏈接<a href="mypage.html">我的頁面</a>改為:<a href="http://myhost/servlet/JinJ?mypage.html" target="_top">我的頁面</a>
JinJ servlet 隨即把所有的Java調用轉化成JavaScript,然後產生頁面並輸出出來。
b)定義某種映射。舉例來說,這裡我們設置Servlet調用擴展名為.JinJ的文件 (這裡介紹的方法針對運行於NT上的JSWDK,你所使用的Servelt系統的具體定義映射的方法請參看你的用戶指南)
JinJ.code=JinJ
JinJ.initparams=servlet=http://myhost/servlet/JinJ, root=c:\\jswdk\\webpages objects=c:\\jswdk\\obj.txt,
codebase=http://myhost/
設置了以後,你就可以使用http://myhost/some_file.JinJ然後JinJ servlet將會自動被調用了
Servlet參數
為了讓JinJ正常運行,還應當能夠為JinJ servlet設置一些全局參數,這也是我們在編程是應當注意到的問題。對於JSWDK, Servlet屬性是參數'initparams'的一部分;對於Tomcat,則應當編輯系統中的web.xml
1)需要設置JinJ servlet的路徑,參數名是servlet,就像這樣:
http://your_host:port/servlet/JINJ
2) 需要設置存放HTML頁的根目錄,參數名是root,其值就像這樣: /home/webpages (或c:\webpages) (默認值是一個空的字符串)。 例如,如果你的根目錄是:/home/webpages,並且你使用http://host/servlet/JINJ?myfile.htm 的話,那你的真實的文件名是/home/webpages/myfile.htm
3) 需要設置你定義的Java對象的文件的完全目錄,參數名是objects,其值只是一個存放在你的服務器中的一個文件的文件名。
4) 需要設置用於java applet的codebase,參數名是codebase,定義了存放applet的類的路徑,比如http://your_host/ 。
以下為Tomcat中web.xml 中的相應設置:
<servlet>
<servlet-name>JinJ</servlet-name>
<servlet-class>JinJ</servlet-class>
<init-param>
<param-name>servlet</param-name>
<param-value>http://your_host/servlet/JinJ</param-value>
</init-param>
<init-param>
<param-name>root</param-name>
<param-value>path_to_the_root_directory</param-value>
</init-param>
<init-param>
<param-name>objects</param-name>
<param-value>path_to_your_objects_file</param-value>
</init-param>
<init-param>
<param-name>codebaset</param-name>
<param-value>http://your_host/</param-value>
</init-param>
</servlet>
在編程時還應當注意實現讀取對象文件中所包含的對象,或創建新的Java對象
1. 在初始化JinJ Servlet時將創建一些Java對象,因此你必須在某個文本文件中定義這些對象,並且在參數objects中設置這個文件的路徑,這是一個文本文件,每一行描述了一個元素(空行和以#或//開頭的行將被忽略),使用下面的格式來描述參數:
object_name=new class_name(list_of_parameters);
換句話說,它很象每次調用類構造器的new操作符,object_name 是就是某個你將在JavaScript中使用到的標識符,例如:
file://數據池
A=new dbPool(5);
file://哈希表
B=new java.util.Hashtable();
或者使用你自己定義的包和類:c=new myPackage.myClass(true);
然後在JavaScript中,你就可以使用它們了,如A.connect(),其中connect() 是類dbPool的一個函數,或者使用B.put('key',value)
注意:
1)你的類應當放在你的CLASSPATH指定的目錄下面。
2)你可以使用類名作為對象名 (不過這必須在沒有重名的情況下,因為對象名必須是唯一的),如:dbPool=new dbPool();
2. 為了更優化程序,應當在編程的時候就預建一些對象組成標准化庫,通過標准化庫,你可以在運行中創建/刪除對象的實例,查看存在的對象等。
下面就是我們需要實現的標准化庫(預定義的對象) ,對象名是JinJ,所以服務器端名為JinJ的實例將會被自動創建,這給類中有下面幾個函數:
public boolean create(String object_name,String class_name,list_of_constructors_parameters);
public void delete(String object_name);
public boolean exists(String object_name);
public String id();
public int random(int n1, int n2);
public String rewriteURL(document,String id_name);
public String rewriteURL(document,String id_name,String id_value);
create(創建):能夠讓你在運行時創建某個對象的實例:
參數為:
- 新的對象名
- 類名
- 參數列表 (如果你使用默認構造函數的時候,可以為空)。
返回值:
- 根據創建的接過返回true 或 false
例如:
<script language="JavaScript">
<!--創建myHash 作為一個新的哈希表Hashtable -->
java.JinJ.create("myHash","java.util.Hashtable");
<!-- 使用myHash -->
java.myHash.put('key1','shop1');
</script>
delete:讓你刪除任何對象的實例。
參數為:
- 對象名
例如:
<script language="JavaScript">
<!-- 刪除myHash -->
java.JinJ.delete("myHash");
</script>
exists:查看對象的實例是否存在。
參數為:
- 對象名
返回值:
true 或 false
例如:
<script language="JavaScript">
if (java.JinJ.exists("myHash")=='false')
{
<!--創建myHash 作為一個新的哈希表Hashtable -->
java.JinJ.create(myHash,"java.util.Hashtable");
<!--使用myHash -->
java.myHash.put('key1','shop1');
}
</script>
id: 返回唯一的標示符,比如你可以在支持session的程序中使用這個函數。
Random: 從給定的數域中返回隨機值:
例如:
<script language="JavaScript">
var sessionId=java.JinJ.id();
<!-- 從1到10中的隨機數 -->
var randValue=java.JinJ.random(1,10);
</script>
rewriteURL:能夠讓你使用session。你可以用<a href="some_url? id_name=id_value">你的鏈接</a>來替代<a href="some_url">你的鏈接</a>這同樣適用於任何形式的動作。你可以只設置一個參數名,參數值將自動生成,也可以同時設置參數名和參數值:
例如:
<script language="JavaScript">
<!--添加sessionId=某個值到這個鏈接 -->
java.JinJ.rewriteURL(document,'sessionId');
<!-- 添加 id=12345 到這個鏈接-->
java.JinJ.rewriteURL(document,'id',12345);
</script>
我們還要能夠分析讀入Java函數的參數,對於一個參數我們必須知道它的數據類型,為了簡單起見,我們就認為有四種數據類型整型,浮點型,布爾型其余的全歸於字符串型,你可以看到,這在程序中都有相應的解釋。
例如:
<!-- 我們假定A(int,float,String,boolean) -->
java.myClass.myFunc(2, 5.6, a123, true);
為了保證你傳遞的參數是一個字符串型的值的話,請你使用"或者',如:
<!--總是作為字符串型數據傳遞-->
java.myClass.myFunc("256");
函數返回的結果問題
如果Java函數的類型為void的話,那麼將返回給JavaScript一個空字符串,在別的情況下(如果不是數組),將返回Java對象的字符型返回值。如果你的Java函數返回數組或者向量(Vector)或枚舉(Enumeration),結果將被表示為JavaScript中的數組。例如:在類dbpool中,你如果有某個函數performQuery(some_sql_string)來通過JDBC來調用SQL查詢,將轉換ResultSet成為數組(或向量)然後把這個數組返回給JavaScript。
res=java.dbpool.performQuery("select * from emp");
first=res[0];
second=res[1];
程序還應該實現控制台(JINJ控制台),這樣你就可以直接從浏覽器中運行這個Servlet,並且可以創建/刪除對象,相應的命令是: http://your_host/servlet/JINJ?your_password
或者,如果你使用擴展名映射JinJ的話,則::
http://your_host/your_file.JinJ?your_password ,這些都應當在程序中體現,你可以在servlet的初始化參數中設置口令,參數名是admin. 如:
JINJ.code=JINJ
JINJ.initparams=admin=secret,
servlet=http://myhost/servlet/JINJ,
root=/home/www/pub,
objects=/home/load/obj.txt,
codebase=http://myhost/
默認的密碼值是abcd,所以使用JINJ?abcd 將運行管理員界面,通過這一頁,你可以刪除或者創建新的對象的實例。
下面,然我們來看看具體在Java代碼上如何實現我們的構思:
JinJ.java
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class JinJ extends HttpServlet
{ public JinJ()
{
}
public void init(ServletConfig servletconfig)//初始化
throws ServletException
{
super.init(servletconfig);
inst = new Hashtable();
cls = new Hashtable();
NEWLINE = System.getProperty("line.separator"); file://獲取行分割符在本系統中的屬性值,例如在UNIX下為
separator = System.getProperty("file.separator");//獲取文件分割符在本系統中的屬性值,例如在UNIX下為/
if((THIS_SERVLET = getInitParameter("servlet")) == null)
file://getInitParameter方法,返回一個字符串,包含命名的初始化參數的值,如果參數不存在則為空。
THIS_SERVLET = "";
if((admin = getInitParameter("admin")) == null)
admin = "abcd";
if((DOCUMENT_ROOT = getInitParameter("root")) == null)
DOCUMENT_ROOT = "";
if(DOCUMENT_ROOT.length() > 0 && !DOCUMENT_ROOT.endsWith(separator))
file://如果DOCUMENT_ROOT的長度為正值,並且不以文件分割符結尾則
DOCUMENT_ROOT = DOCUMENT_ROOT + separator;
if((CODEBASE = getInitParameter("codebase")) == null)
CODEBASE = "";
JAVA_FILE = getInitParameter("objects");
if(JAVA_FILE != null && inst != null)
loadJava(JAVA_FILE);
}
private void loadJava(String s)
{
System.out.println("從" + s +"調用Java對象 ");
try
{
BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(new FileInputStream(s)));
file://創建一個文件輸入流緩沖區
String s1;
file://開始分析文件
while((s1 = bufferedreader.readLine()) != null)//每次讀入一行
{
s1 = s1.trim(); file://把字符串兩端的空格去掉
/*********************************************************
* 如果以";"結尾則去掉";"
**********************************************************/
if(s1.endsWith(";"))
s1 = s1.substring(0, s1.length() - 1).trim();
/*****************************************************************************
* 如果s1的長度大於零,並且第一個字符不為#和//,則調用processLine處理這一行參數
******************************************************************************/
if(s1.length() > 0 && s1.charAt(0) != '#' && !s1.startsWith("//"))
processLine(s1);
}
bufferedreader.close();
return;
}
catch(Exception _ex)
{
return;
}
}
private void processLine(String s)
{
/**************************************************************************
*取得這一行中第一次出現等號的下標值,如果沒出現等號則返回-1
*如果沒有等號,則輸出錯誤信息
**************************************************************************/
int i = s.indexOf("=");
if(i <= 0 || i == s.length() - 1)
{
System.out.println("不能處理此行信息: " + s);
return;
}
String s1 = s.substring(0, i).trim();//s1為s中等號前的字符串
String s2 = s.substring(i + 1).trim();//s2為s中等號後的字符串
if(s2.startsWith("new "))//判斷s2是否以new開頭,如new class_name(list_of_parameters);
s2 = s2.substring("new".length()).trim();
if(s1.length() == 0 || s2.length() == 0)
{
System.out.println("不能處理此行信息: " + s);
return;
}
if(inst.get(s1) != null) file://為了防止重復定義類名
{
System.out.println("重復命名 " + s1);
return;
}
i = s2.indexOf("(");
if(i <= 0 && !s2.endsWith(")"))
{
System.out.println("不能處理此行信息:" + s);
return;
}
String s3 = s2.substring(0, i).trim();//s3為新定義的類名
s2 = s2.substring(i + 1, s2.length() - 1).trim();//s2為參數列表
if(inst.size() < 5)
processLine1(s1, s3, s2, s);
}
private String prepareString(String s)
{
if(s == null)
return null;
if(s.length() < 2)
return s;
if(s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"') file://如果字符串s以"開頭,又以"結尾,則把兩頭的"去掉
return s.substring(1, s.length() - 1);
if(s.startsWith("'") && s.endsWith("'"))//如果字符串s以'開頭,又以'結尾,則把兩頭的"去掉
return s.substring(1, s.length() - 1);
else
return s;
}
private boolean processLine1(String s, String s1, String s2, String s3)
{ file://創建一個Object類的實例
Object obj[] = {
null, null
};
Class class1;
if((class1 = (Class)cls.get(s1)) == null)
try
{
class1 = Class.forName(s1);//返回具有s1指定的類名的類的Class描述符
cls.put(s1, class1); file://放回哈西表
}
catch(Exception _ex)
{
System.out.println("不能裝載類 " + s1);
return false;
}
obj[0] = class1;
if(s2.length() == 0)
{
try
{
obj[1] = class1.newInstance();// 創建類的新實例
}
catch(NoSuchMethodError _ex)
{
System.out.println("不能創建對象的實例 " + s3);
return false;
}
catch(Exception _ex)
{
System.out.println("不能創建對象的實例 " + s3);
return false;
}
inst.put(s, ((Object) (obj)));
}
else
{
Object obj1[] = getParamArray(s2, 0); file://取得參數列表
if(obj1 == null)
{
System.out.println("不能處理這行參數: " + s3);
return false;
}
try
{
Constructor cons = class1.getConstructor((Class[])obj1[0]);//使用參數列表構建類構建器
if(class1 == null)
{
System.out.println("不能創建對象的實例 " + s3);
return false;
}
obj[1] = cons.newInstance((Object[])obj1[1]);
inst.put(s, ((Object) (obj)));
}
catch(Exception _ex)
{
System.out.println("不能創建對象的實例 " + s3);
return false;
}
}
return true;
}
private Object[] getParamArray(String s, int i) file://取得s中所包含的參數列表,存入一個Object數組中
{
String s1 = s.trim(); file://去除末尾的空格
String s6 = ",";
Vector vector = new Vector();
if(s1.length() > 0)
{
if(s1.charAt(0) == '(')//去掉(
s1 = s1.substring(1);
if(s1.endsWith(")"))//去掉)
s1 = s1.substring(0, s1.length() - 1);
String s2 = s1.trim(); file://去掉字符串後的空格
if(s2.length() == 0 && i == 0) file://如果s2長度為零,說明沒有參數
return null;
String s4;
if(s2.length() > 0)
{
if(s2.charAt(0) == '"')//如果s2以"開頭,則用\"代替
s6 = "\"";
else
if(s2.charAt(0) == '\'')//如果s2以\'開頭,則用'代替
s6 = "'";
else
s6 = ",";
s4 = s2.substring(0, 1); file://取得s2的第一個字符
s2 = s2.substring(1);//取得s2的第二個字符往後的字符
}
else
{
s4 = "";
}
for(; s2.length() > 0; s2 = s2.substring(1))//這些語句是為了把參數表中的參數分離出來
{
String s5 = s2.substring(0, 1);//取得s2的第一個字符
if(s5.equals(s6)) file://如果s5和s6相等,即判斷s5是否為兩個參數的分隔符
{
if(s6.equals("\"") || s6.equals("'"))//如果s6為\"或',則
s4 = s4 + s6;
vector.addElement(s4); file://把s4(即一個參數值)加入vector中
s2 = s2.substring(1).trim();
s4 = "";
if(s2.length() == 0)
break;
s4 = s2.substring(0, 1);
if(s4.charAt(0) == ',')
file://如果s4以","開頭,則判斷s4是否以分隔符開頭
{
s2 = s2.substring(1).trim();
s4 = "";
if(s2.length() == 0)
break;
s4 = s2.substring(0, 1);
}
if(s4.charAt(0) == '"')
s6 = "\"";
else
if(s4.charAt(0) == '\'')
s6 = "'";
else
s6 = ",";
}
else
{
s4 = s4 + s5;
}
}
if(s4.length() > 0)
vector.addElement(s4);
}
int j = vector.size(); file://取得向量變量vector的大小,vector中保存的都是參數值
if(j == 0 && i == 0)
return null; file://沒有參數
Object aobj[] = new Object[3];
Class class1[] = new Class[j + i];
Object aobj1[] = new Object[j + i];
aobj[0] = class1;
aobj[1] = ((Object) (aobj1));
aobj[2] = new Integer(j + i);
for(int k = i; k < j + i; k++)
{
String s3 = (String)vector.elementAt(k - i);
try
file://以下的代碼是為了判斷,每個參數到底是什麼數據類型
{ file://判斷是否為整型
Integer integer = Integer.valueOf(s3);
class1[k] = Integer.TYPE;
aobj1[k] = integer;
}
catch(Exception _ex)
{
try
{ file://判斷是否為浮點型
Float float1 = Float.valueOf(s3);
class1[k] = Float.TYPE;
aobj1[k] = float1;
}
catch(Exception _ex2)
{ file://判斷是否為布爾類型
s3 = prepareString(s3);
if(s3.equals("true")) file://判斷是否為真
{
class1[k] = Boolean.TYPE;
aobj1[k] = new Boolean(true);
}
else
if(s3.equals("false")) file://判斷是否為假
{
class1[k] = Boolean.TYPE;
aobj1[k] = new Boolean(false);
}
else
{
class1[k] = class$java$lang$String == null ? (class$java$lang$String = class$("java.lang.String")) : class$java$lang$String;
aobj1[k] = s3;
}
}
}
}
vector = null;
return aobj;
}
public void doPost(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws ServletException, IOException
{
doGet(httpservletrequest, httpservletresponse);
}
public void doGet(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws ServletException, IOException
{
String s = "";
String s1 = "";
s = HttpUtils.getRequestURL(httpservletrequest).toString();
file://返回一個字符串,包含請求字符串中包含的協議名,主機名,端口號以及路徑,但是不包含請求的內容
int i;
if((i = s.indexOf("?")) > 0)//去掉s結尾的問號
s = s.substring(0, i);
s1 = httpservletrequest.getQueryString();//取的請求字符串的請求內容
if(s1 == null)
{
parseFile(s1, httpservletrequest, httpservletresponse);
return;
}
if(s1.equals(admin)) file://如果請求串等於admin
{
adminPage(httpservletrequest, httpservletresponse, s); file://進入管理員界面
return;
}
if(s1.equals("namiotde")) file://如果請求串為namiotde,則執行相應的執行命令
{
executeRequest(httpservletrequest, httpservletresponse);
return;
}
String s2 = getFromQuery(s1, "what="); file://取的動作的屬性值
if(s2.equals("hframe"))
{
getHiddenFrame(httpservletrequest, httpservletresponse);//轉到隱藏幀
return;
}
if(s2.equals("mframe"))
{
getMainFrame(s1, httpservletrequest, httpservletresponse); file://轉到主幀
return;
}
else
{
parseFile(s1, httpservletrequest, httpservletresponse);
return;
}
}
file://管理員界面,執行添加刪除對象的操作
private void adminPage(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse, String s)
throws IOException
{
PrintWriter printwriter = httpservletresponse.getWriter();
String s1 = "";
String s4 = httpservletrequest.getParameter("what"); file://返回請求串中what,即動作的屬性值
if(s4 != null)
if(s4.equals("delete")) file://如果what的值為delete,則執行相應的操作
{
for(Enumeration enumeration = httpservletrequest.getParameterNames(); enumeration.hasMoreElements();)
{
String s2 = (String)enumeration.nextElement();
if(s2.startsWith("_"))
{
inst.remove(s2.substring(1));
s1 = s1 + " " + s2.substring(1);
}
}
if(s1.length() > 0)
s1 = "刪除: " + s1;
}
else
if(s4.equals("add")) file://如果what的值為add,則執行相應的操作
{
String s5 = httpservletrequest.getParameter("oname");//取的對象名
String s6 = httpservletrequest.getParameter("JinJ"); file://取得類名
String s7 = httpservletrequest.getParameter("params"); file://取得參數
if(s5 == null)
s5 = "";
else
s5 = s5.trim();
if(s6 == null)
s6 = "";
else
s6 = s6.trim();
if(s7 == null)
s7 = "";
else
s7 = s7.trim();
if(s7.length() > 0 && !s7.startsWith("("))
s7 = "(" + s7 + ")";
if(s5.length() > 0 && s6.length() > 0 && inst.size() < 5)
{
String s3 = s5 + "=new " + s6 + s7;//寫成標准的對象實例化形式
if(processLine1(s5, s6, s7, s3))
s1 = s5 + " 被載入...";
else
s1 = "不能載入" + s3;
}
}
httpservletresponse.setContentType("text/html");
printwriter.println("<html>");
printwriter.println("<head>");
printwriter.println("<title>JinJ 控制台</title>");
printwriter.println("</head>");
printwriter.println("<body bgcolor="#FFFFFF">");
printwriter.println(setScript());
if(s1.length() > 0)
printwriter.println("<br><i>" + s1 + "</i><br>");
printwriter.println("<h2><center>對象</center></h2>");
printwriter.println("<br>");
printwriter.println(objectsTable(s));
printwriter.println("</body>");
printwriter.println("</html>");
}
private String setScript()
{
StringBuffer stringbuffer = new StringBuffer();
stringbuffer.append("<script language="JavaScript">" + NEWLINE);
stringbuffer.append("function fun(what)" + NEWLINE);
stringbuffer.append("{ document.mf.what.value=what; document.mf.submit(); }" + NEWLINE);
stringbuffer.append("</script>" + NEWLINE);
return stringbuffer.toString();
}
private String objectsTable(String s)
{
StringBuffer stringbuffer = new StringBuffer();
String s2 = "#D5E6E1";
stringbuffer.append("<form name="mf" method=post action="" + s + "?" + admin + "">" + NEWLINE);
stringbuffer.append("<input type=hidden name="what">" + NEWLINE);
stringbuffer.append("<table width=98% border=0>");
stringbuffer.append("<tr bgcolor=#CCCCFF><td nowrap></td><td nowrap>對象名</td><td nowrap>類名</td></tr>" + NEWLINE);
for(Enumeration enumeration = inst.keys(); enumeration.hasMoreElements();)
{
String s1 = (String)enumeration.nextElement();
Object aobj[] = (Object[])inst.get(s1);
stringbuffer.append("<tr bgcolor="" + s2 + "">");
stringbuffer.append("<td width=5 nowrap>");
stringbuffer.append("<input type=checkbox name="_" + s1 + "">");
stringbuffer.append("</td>");
stringbuffer.append("<td nowrap>" + s1 + "</td><td nowrap>" + aobj[0] + "</td></tr>" + NEWLINE);
if(s2.equals("#D5E6E1"))
s2 = "#F7F7F7";
else
s2 = "#D5E6E1";
}
stringbuffer.append("</table>" + NEWLINE);
stringbuffer.append("<br><br>");
stringbuffer.append("<table>" + NEWLINE);
stringbuffer.append("<tr>");
if(inst.size() > 0)
stringbuffer.append("<td align=left nowrap><input type=button value=Delete onClick="fun('delete');"></td>");
else
stringbuffer.append("<td nowrap></td>");
stringbuffer.append("<td nowrap> </td>");
stringbuffer.append("<td align=right nowrap>對象名<input type=text size=10 name="oname"> 類名<input type=text size=18 name="JinJ">參數<input type=text name="params">");
stringbuffer.append("<input type=button value=Add onClick="fun('add');"></td></tr>");
stringbuffer.append("</table>" + NEWLINE);
stringbuffer.append("</form>");
return stringbuffer.toString();
}
file://分析文件
private void parseFile(String s, HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws IOException
{
String s1 = getUrl(httpservletrequest);
String s2 = getFile(s, httpservletrequest);
httpservletresponse.setContentType("text/html");
PrintWriter printwriter = httpservletresponse.getWriter();
printwriter.println("<html>");
if(s1 == null)
{
printwriter.println("<br>找不到servlet名.請檢查初始參數");
}
else
{
printwriter.println("<frameset rows="*,100%" border=0>");
printwriter.println("<frame name="hframe" src="" + s1 + "?" + "what" + "=" + "hframe" + "">");
printwriter.println("<frame name="mframe" src="" + s1 + "?" + "what" + "=" + "mframe" + "&" + "df" + "=" + s2 + "">");
printwriter.println("</frameset>");
}
printwriter.println("</html>");
printwriter.flush();
printwriter.close();
}
private String getId()//取ID命令,使用當前的時間配合隨機數產生的是唯一值
{
String s = "";
synchronized(SessionIdLock)
{
long l = System.currentTimeMillis();
Random random = new Random();
s = String.valueOf(l);
for(int i = 1; i <= 6; i++)
s = s + (int)(1.0D + 6D * random.nextDouble());
}
return s;
}
private String randomValue(String s, String s1)//取隨機數
{
Random random = new Random();
int i;
int j;
try
{
i = Integer.parseInt(s);
j = Integer.parseInt(s1);
}
catch(Exception _ex)
{
return "對於random()無效的參數值";
}
return String.valueOf((int)((double)i + (double)j * random.nextDouble()));
}
private void executeRequest(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse) file://執行請求
throws IOException
{
String s = httpservletrequest.getParameter("params"); file://返回參數params的值
String s2 = "";
String s3 = "";
String s4 = "";
Object aobj[] = {
null, null
};
int i = s.indexOf("@#$");
String s1 = s.substring(0, i); file://取出"@#$"前的字符串
if(s.length() <= i + "@#$".length()) file://如果大於的話,說明@#$後還有其他的字符
s2 = "";
else
for(s = s.substring(i + "@#$".length()).trim(); s.length() > 0;)
{
i = s.indexOf("@#$");
if(i < 0)
{
if(s2.length() > 0)
s2 = s2 + ",";
s2 = s2 + s;
s = "";
}
else
{
if(s2.length() > 0)
s2 = s2 + ",";
s2 = s2 + s.substring(0, i);
if(s.length() <= i + "@#$".length())
s = "";
else
s = s.substring(i + "@#$".length()).trim();
}
}
i = s1.indexOf(".");
if(i > 0 && i < s1.length() - 1)
{
s3 = s1.substring(0, i);
s1 = s1.substring(i + 1);
}
if(s3.equals("j2j"))
{
if(s1.equals("exists")) file://exists命令
{
if(s2.length() == 0) file://參數為零顯然是錯誤的
{
s4 = "錯誤的標准函數調用";
}
else
{
if((i = s2.indexOf(",")) > 0)
s2 = s2.substring(0, i);
s4 = String.valueOf(inst.get(s2) != null);//判斷是否存在s2對象
}
}
else
if(s1.equals("delete")) file://delete函數
{
if(s2.length() == 0)
{
s4 = "錯誤的標准函數調用";
}
else
{
if((i = s2.indexOf(",")) > 0)
s2 = s2.substring(0, i);
inst.remove(s2); file://刪除s2對象
s4 = "";
}
}
else
if(s1.equals("create")) file://create函數,創建新的對象的實例
{
if(s2.length() == 0 || (i = s2.indexOf(",")) < 0)
{
s4 = "錯誤的標准函數調用";
}
else
{
String s8 = s2.substring(0, i); file://s8為對象名
s2 = s2.substring(i + 1);
String s9;
if((i = s2.indexOf(",")) < 0)
{
s9 = s2; file://如果沒有構造參數列表則s9(類名)就等於s2
s2 = "";
}
else
{
s9 = s2.substring(0, i); file://否則,s9(類名)為兩個逗號之間的字符串
s2 = s2.substring(i + 1); file://s2是構造參數列表
}
if((aobj = (Object[])inst.get(s8)) != null)
{
s4 = "false";
}
else
{
String s5 = s8 + "=new " + s9 + "(" + s2 + ")"; file://s5為一標准java對象實例化形式,送入processLine1處理
s4 = String.valueOf(processLine1(s8, s9, s2, s5));
}
}
}
else
if(s1.equals("id"))//id命令
s4 = getId();
else
if(s1.equals("random")) file://random命令
{
if((i = s2.indexOf(",")) < 0) file://如果沒有兩個參數的話,出錯
s4 = "錯誤的標准函數調用";
else
s4 = randomValue(s2.substring(0, i), s2.substring(i + 1)); file://取隨機值
}
else
{
s4 = "錯誤的標准函數調用";
}
}
else
if((aobj = (Object[])inst.get(s3)) == null)
{
s4 = "不能發現" + s3+ "的實例";
}
else
{
Class class1 = (Class)aobj[0];
Object obj = aobj[1];
try
{
if(s2.length() > 0)
{
Object aobj1[] = getParamArray(s2, 0); file://從s2中取出參數列表
Method method = class1.getMethod(s1, (Class[])aobj1[0]);
Object obj2 = method.invoke(obj, (Object[])aobj1[1]);
if(method.getReturnType().getComponentType() == null)
{
String s6 = method.getReturnType().toString();
if(s6.indexOf("java.util.Vector") > 0)//判斷s6中是否有java.util.Vector
{
if(obj2 == null)
{
s4 = "";
}
else
{
Vector vector = (Vector)obj2;
if(vector.size() == 0)
{
s4 = "";
}
else
{
for(int j = 0; j < vector.size(); j++)
{
s4 = s4 + "@#$";
s4 = s4 + (String)vector.elementAt(j);
}
}
}
}
else
if(s6.indexOf("java.util.Enumeration") > 0)
{
if(obj2 == null)
{
s4 = "";
}
else
{
Enumeration enumeration = (Enumeration)obj2;
if(!enumeration.hasMoreElements())
s4 = "";
else
while(enumeration.hasMoreElements())
{
s4 = s4 + "@#$";
s4 = s4 + (String)enumeration.nextElement();
}
}
}
else
if(obj2 == null)
s4 = "";
else
s4 = String.valueOf(obj2);
}
else
{
for(int k = 0; k < Array.getLength(obj2); k++)
{
s4 = s4 + "@#$";
if((obj = Array.get(obj2, k)) != null)
s4 = s4 + obj;
}
}
}
else
{
Method method1 = class1.getMethod(s1, null);
Object obj3 = method1.invoke(obj, null);
if(method1.getReturnType().getComponentType() == null)
{
String s7 = method1.getReturnType().toString();
if(s7.indexOf("java.util.Vector") > 0)
{
if(obj3 == null)
{
s4 = "";
}
else
{
Vector vector1 = (Vector)obj3;
if(vector1.size() == 0)
{
s4 = "";
}
else
{
for(int l = 0; l < vector1.size(); l++)
{
s4 = s4 + "@#$";
s4 = s4 + (String)vector1.elementAt(l);
}
}
}
}
else
if(s7.indexOf("java.util.Enumeration") > 0)
{
if(obj3 == null)
{
s4 = "";
}
else
{
Enumeration enumeration1 = (Enumeration)obj3;
if(!enumeration1.hasMoreElements())
s4 = "";
else
while(enumeration1.hasMoreElements())
{
s4 = s4 + "@#$";
s4 = s4 + (String)enumeration1.nextElement();
}
}
}
else
if(obj3 == null)
s4 = "";
else
s4 = String.valueOf(obj3);
}
else
{
for(int i1 = 0; i1 < Array.getLength(obj3); i1++)
{
s4 = s4 + "@#$";
Object obj1;
if((obj1 = Array.get(obj3, i1)) != null)
s4 = s4 + obj1;
}
}
}
}
catch(Exception _ex)
{
s4 = "不能從類 "+ class1.getName()+ "中調用"+ s1;
}
if(s4 == null)
s4 = "";
}
PrintWriter printwriter = httpservletresponse.getWriter();
httpservletresponse.setContentType("text/html");
printwriter.println(s4);
printwriter.flush();
printwriter.close();
}
private void getMainFrame(String s, HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws IOException
{
PrintWriter printwriter = httpservletresponse.getWriter();
String s1 = getFromQuery(s, "df="); file://取得數據文件所在的路徑和文件名
httpservletresponse.setContentType("text/html");
if(s1.length() == 0)
printwriter.println("<html><br>不能打開數據文件</html>");
else
try
{ file://打開數據文件
BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(new FileInputStream(s1)));
String s2;
while((s2 = bufferedreader.readLine()) != null)
{
int i;
while((i = s2.indexOf("java.")) > 0)
{
String s3 = s2.substring(0, i) + "parent." + "hframe" + ".javabridge('";
String s4;
for(s4 = s2.substring(i + "java.".length()); s4.length() > 0; s4 = s4.substring(1))
{
if(s4.charAt(0) == '(')
{
s3 = s3 + "'";
s4 = s4.substring(1);
break;
}
s3 = s3 + s4.substring(0, 1);
}
if(needComma(s4))
s3 = s3 + ",";
s2 = s3 + s4;
}
printwriter.println(s2);
}
bufferedreader.close();
}
catch(Exception _ex)
{
printwriter.println("不能讀取數據文件" + s1);
}
printwriter.flush();
printwriter.close();
}
file://取得隱藏幀
private void getHiddenFrame(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws IOException
{
String s = getId(); file://取得ID
PrintWriter printwriter = httpservletresponse.getWriter();
httpservletresponse.setContentType("text/html");
file://調用applet bridge
printwriter.println("<html>");
printwriter.println("<applet code="bridge.class" codebase="" + CODEBASE + "" width=10 height=10>");
printwriter.println("<param name="servlet" value="" + getUrl(httpservletrequest) + "">");
printwriter.println("</applet>");
printwriter.println("<script language="JavaScript">");
printwriter.println("function javabridge(fName)");
printwriter.println("{");
printwriter.println(" var s='';");
printwriter.println(" if (fName=='jinj.rewriteURL' && javabridge.arguments.length>2)");
printwriter.println(" {");
printwriter.println(" if (javabridge.arguments.length==3)");
printwriter.println(" return rewriteURL(javabridge.arguments[1],javabridge.arguments[2]);");
printwriter.println(" else");
printwriter.println(" return rewriteURL(javabridge.arguments[1],javabridge.arguments[2],javabridge.arguments[3]);");
printwriter.println(" }");
printwriter.println(" for (i=1;i<javabridge.arguments.length;i++)");
printwriter.println(" { if (s!='') { s+='@#$';}");
printwriter.println(" s+=javabridge.arguments[i]; }");
printwriter.println(" s=document.applets[0].fromJava(fName,s);");
printwriter.println(" i=s.indexOf('@#$');");
printwriter.println(" if (i<0) return s;");
printwriter.println(" ans=new Array(); s=s.substring(3); i=s.indexOf('@#$'); j=0;");
printwriter.println(" while (i>=0)");
printwriter.println(" { ans[j]=s.substring(0,i); j=j+1; s=s.substring(i+3); i=s.indexOf('@#$'); }");
printwriter.println(" ans[j]=s; return ans; ");
printwriter.println("}");
printwriter.println("function rewriteURL1(s,id)");
printwriter.println("{");
printwriter.println("if (s.indexOf('?')>0) return s+'&'+id+'='+'" + s + "';");
printwriter.println("return s+'?'+id+'='+'" + s + "';");
printwriter.println("}");
printwriter.println("function rewriteURL2(s,id,vl)");
printwriter.println("{");
printwriter.println("if (s.indexOf('?')>0) return s+'&'+id+'='+vl;");
printwriter.println("return s+'?'+id+'='+vl;");
printwriter.println("}");
printwriter.println("function rewriteURL(doc)");
printwriter.println("{");
printwriter.println(" i=rewriteURL.arguments.length;");
printwriter.println(" if (i>1)");
printwriter.println(" {");
printwriter.println(" tmp=rewriteURL.arguments[1];");
printwriter.println(" for (j=0; j<doc.links.length; j++)");
printwriter.println(" {");
printwriter.println(" s=doc.links[j].href;");
printwriter.println(" if (s.indexOf(tmp+'=')<0)");
printwriter.println(" {");
printwriter.println(" if (i==2) doc.links[j].href=rewriteURL1(s,tmp);");
printwriter.println(" else doc.links[j].href=rewriteURL2(s,tmp,rewriteURL.arguments[2]);");
printwriter.println(" }");
printwriter.println(" }");
printwriter.println(" for (j=0; j<doc.forms.length; j++)");
printwriter.println(" {");
printwriter.println(" s=doc.forms[j].action;");
printwriter.println(" if (s.indexOf(tmp+'=')<0)");
printwriter.println(" {");
printwriter.println(" if (i==2) doc.forms[j].action=rewriteURL1(s,tmp);");
printwriter.println(" else doc.forms[j].action=rewriteURL2(s,tmp,rewriteURL.arguments[2]);");
printwriter.println(" }");
printwriter.println(" }");
printwriter.println(" }");
printwriter.println(" return " + s + ";");
printwriter.println("}");
printwriter.println("</script>");
printwriter.println("</html>");
printwriter.flush();
printwriter.close();
}
private String getFile(String s, HttpServletRequest httpservletrequest)
{
String s1 = httpservletrequest.getRequestURI();
String s2 = "";
if(s1.endsWith("jinj") || s1.endsWith("JinJ.class"))
{
if(s == null)
return null;
s1 = getFromQuery(s, "df=");
if(s1.length() == 0)
s2 = s;
else
s2 = s1;
}
else
{
s2 = s1;
}
if(s2 == null)
return s2;
if(s2.length() == 0)
return s2;
if(s2.charAt(0) == '/')
s2 = s2.substring(1);
return DOCUMENT_ROOT + s2.replace('/', separator.charAt(0));
}
private String getUrl(HttpServletRequest httpservletrequest)
{
if(THIS_SERVLET.length() > 0)
return THIS_SERVLET;
String s1 = httpservletrequest.getRequestURI();
String s = HttpUtils.getRequestURL(httpservletrequest).toString();
int i;
if((i = s.indexOf("?")) > 0)
s = s.substring(0, i);
if(s1.endsWith("JinJ") || s1.endsWith("JinJ.class"))
return s;
else
return null;
}
private boolean needComma(String s) file://判斷是否缺少括號
{
String s1 = s.trim();
if(s1.length() == 0)
return true;
return s1.charAt(0) != ')';
}
private String getFromQuery(String s, String s1)
{
if(s == null)
return "";
int i;
if((i = s.indexOf(s1)) < 0)
return "";
String s2 = s.substring(i + s1.length());
if((i = s2.indexOf("&")) < 0)
return s2;
else
return s2.substring(0, i);
}
static Class class$(String s)
{
try
{
return Class.forName(s);
}
catch(ClassNotFoundException classnotfoundexception)
{
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
public static Object SessionIdLock = new Object();
private static final int HOW_LONG = 6;
private static final String CLASSNAME = "JinJ";
private static final String STDLIB = "jinj";
private static final String EXISTS = "exists";
private static final String DELETE = "delete";
private static final String CREATE = "create";
private static final String ID = "id";
private static final String RANDOM = "random";
private static final String BRIDGE = "bridge.class";
private static String NEWLINE = " ";
private static String separator;
private static final String HFRAME = "hframe";
private static final String MFRAME = "mframe";
private static final String EXECUTE = "namiotde";
private static final String ACTION = "what";
private static final String DATAFILE = "df";
private static final String PARAMS = "params";
private static final String PARAM_DELIMETER = "@#$";
private static final String SERVLET = "servlet";
private static final String ROOT = "root";
private static final String OBJECTS = "objects";
private static final String BASE = "codebase";
private static final String ADMIN = "admin";
private static final String DEFADMIN = "abcd";
private static String admin;
private static String THIS_SERVLET = "";
private static String DOCUMENT_ROOT = "";
private static String JAVA_FILE = "";
private static String CODEBASE = "";
private static final String NEW = "new";
private static final String JAVA_CALL = "java.";
private static final int TYPES = 0;
private static final int VALUES = 1;
private static final int DIM = 2;
private static final String ODD = "#D5E6E1";
private static final String EVEN = "#F7F7F7";
private static final String ADD = "add";
private static final String OBJNAME = "oname";
private static Hashtable inst = null;
private static Hashtable cls = null;
static Class class$java$lang$String;
}
bridge.java
import java.applet.Applet;
import java.io.*;
import java.net.*;
public class bridge extends Applet
{
public void init()
{
super.init();
bridge_servlet = getParameter("servlet");
}
public String fromJava(String s, String s1)
{
String s2 = "";
try
{
URL url = new URL(bridge_servlet + "?" + "namiotde");
URLConnection urlconnection = url.openConnection();
urlconnection.setDoOutput(true);
urlconnection.setDoInput(true);
urlconnection.setUseCaches(false);
urlconnection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
PrintWriter printwriter = new PrintWriter(urlconnection.getOutputStream());
printwriter.print("params=" + URLEncoder.encode(s + "@#$" + s1));
printwriter.close();
BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(urlconnection.getInputStream()));
s2 = bufferedreader.readLine();
bufferedreader.close();
}
catch(Exception _ex)
{
return "Can not connect to " + bridge_servlet;
}
return s2;
}
public bridge()
{
}
private static final String SERVLET = "servlet";
private static String bridge_servlet = "";
private static final String EXECUTE = "namiotde";
private static final String PARAMS = "params";
private static final String PARAM_DELIMETER = "@#$";
}