📄 browser.java
字号:
package com.gameislive.browser;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.util.Vector;
import java.util.Stack;
import java.util.Hashtable;
import javax.microedition.lcdui.*;
import javax.microedition.io.HttpConnection;
import com.gameislive.browser.element.*;
/**
*
* @author pan
*
*/
public class Browser implements Runnable,CommandListener{
static final byte LOAD_STEP_NOTHING = 0;
static final byte LOAD_STEP_CONNECTION = 1;
static final byte LOAD_STEP_CONTENT = 2;
static final byte LOAD_STEP_PARSER = 3;
public int fontHeight;
/**
* 当图片无法加载时,显示的图片(表示无效图片)
*/
Image noneImage;
Font font;
String urlBase;
String urlRoot;
Cache cache;
/**
* browser在canvas中的位置
*/
int x,y;
/**
* browser的大小
*/
public int width,height;
/**
* 当前的http请求
*/
public HttpRequest curRequest;
/**
* curRequest请求是否需要发送出去
*/
private byte loadStep;
/**
* 保存Cookies信息
*/
private Hashtable cookies = new Hashtable();
/**
* 默认的编码
*/
private String encoding="UTF-8";
private Display display;
/**
* 保存历史请求URL的堆栈
*/
private Stack historyUrl;
private WapRender wapRender;
private Command inputOk = new Command("确定",Command.OK,0);
private Command inputBack = new Command("返回",Command.BACK,1);
private TextBox inputTextBox;
private List selectList;
public Browser(int x,int y,int w,int h,Display display){
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.display = display;
font = Font.getFont(Font.FACE_SYSTEM,Font.STYLE_PLAIN,Font.SIZE_SMALL);
fontHeight = font.getHeight();
Tools.font = font;
try{
noneImage = Image.createImage("/noneimg.png");
}catch(Exception e){
e.printStackTrace();
}
historyUrl = new Stack();
wapRender = new WapRender(this);
// 默认创建64k的缓冲池来保存图片数据
cache = new Cache(64 * 1024);
}
public void setEncoding(String enc){
encoding = enc;
}
public String getEncoding(){
return encoding;
}
/**
* 返回上一请求页面
* @return
*/
public HttpRequest getLastRequest(){
if(historyUrl.size()>0){
return (HttpRequest)historyUrl.elementAt(historyUrl.size()-1);
}
return null;
}
/**
* 默认的GET请求
* @param url
*/
public void request(String url){
if(url!=null && !url.equals("")){
// 如果旧的请求不为空,则保存之,以便将来可以返回
if(curRequest!=null){
historyUrl.push(curRequest);
}
curRequest = new HttpRequest(url,HttpConnection.GET,null,null);
loadStep = LOAD_STEP_CONNECTION;
if(cardid!=null && !cardid.equals("")){
curRequest.setFragment(cardid);
cardid = null;
}
}
}
private void request(HttpRequest req){
curRequest = req;
loadStep = LOAD_STEP_CONNECTION;
}
/**
* 返回上一请求的页面
*/
public void back(){
if(historyUrl.size()>0){
request((HttpRequest)historyUrl.pop());
}
}
public void execute(){
if(loadStep == LOAD_STEP_NOTHING){
// nothing to do
}else if(loadStep == LOAD_STEP_PARSER){
// nothing to do
}else if(loadStep == LOAD_STEP_CONNECTION){
// 打开连接线程
new Thread(this).start();
}
}
/**
* 连接线程,请求服务器,加载图片等资源<br>
* 有新请求时,该线程才会被打开
*/
public void run(){
// 开始请求服务器
loadStep = LOAD_STEP_CONTENT;
String errorMsg = null;
byte[] buffer = null;
try{
buffer = flushRequest();
}catch(Exception e){
e.printStackTrace();
errorMsg = e.getMessage();
}
// 开始渲染
loadStep = LOAD_STEP_PARSER;
if(buffer==null){
String str = "Error!<br/>"
+ "Document <a href=\"" + curRequest.getUrl()
+ "\">"+curRequest.getUrl()+"</a> Can't found!<br/>"
+ "<br/>you can use proxy or cmnet and try again.";
str = str + "<br/>" + errorMsg;
renderString(str);
}else{
// 渲染一个页面
renderByteArray(buffer,encoding);
}
//renderLocalDocument("/info.htm");
// 请求完毕
loadStep = LOAD_STEP_NOTHING;
// 处理onevent标记的事件
if(onEvent)
{
executeOnEvent();
// onevent事件执行完毕,清空onEventParaTable
onEventParaTable.clear();
onEventParaTable = null;
onEvent = false;
}
}
/**
* 是否执行onevent标记事件
*/
private boolean onEvent;
/**
* 保存onevent标记事件参数的hashtable
*/
private Hashtable onEventParaTable;
/**
* 提示有onevent事件执行
* @param table
*/
void onEvent(Hashtable table){
onEvent = true;
onEventParaTable = table;
}
/**
* 执行onevent标记的事件,四种:<br>
* -onenterbackward<br>
* -onenterforward<br>
* -onpick<br>
* -ontimer
*/
void executeOnEvent(){
// 获得onevent类型
String type = (String)onEventParaTable.get("type");
if(type!=null && !type.equals("")){
if(type.equals("onenterforward")){
String href = (String)onEventParaTable.get("href");
request(getUrl(href));
}else if(type.equals("onenterbackward")){
}else if(type.equals("ontimer")){
}else if(type.equals("onpick")){
}
}
}
/**
* 发送请求,获取服务器响应,并设置可能的cookie
* @return
* @throws Exception
*/
byte[] flushRequest()throws Exception{
byte[] buffer = null;
getUrlRootAndBase(curRequest.getUrl());
// 检查是否返回session id
String sessionid = null;
if(urlBase!=null){
sessionid = (String)cookies.get(urlBase);
if(sessionid!=null) curRequest.addHeader("Cookie", sessionid);
}
buffer = HttpConnector.sendHttpRequest(curRequest, "",this);
sessionid = HttpConnector.getLastResponseCookie();
// 设置cookie
if(sessionid!=null && !sessionid.equals("")){
cookies.put(urlBase, sessionid);
}
return buffer;
}
/**
* 渲染本地文档
* @param filename
*/
public void renderLocalDocument(String filename){
try{
InputStream is = this.getClass().getResourceAsStream(filename);
byte buffer[] = new byte[is.available()];
is.read(buffer);
renderByteArray(buffer,null);
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 渲染一段字符串
* @param string
*/
public void renderString(String string){
renderByteArray(string.getBytes(),null);
}
/**
* 用指定的编码格式渲染缓冲区byte[]内的文档
* @param buffer
* @param encoding
*/
void renderByteArray(byte[] buffer,String encoding){
// 将缓冲区内的数据转换成流,以便解释文档
ByteArrayInputStream bais = null;
InputStreamReader isr = null;
bais = new ByteArrayInputStream(buffer, 0, buffer.length);
try {
if(encoding!=null && !encoding.equals("")){
isr = new InputStreamReader(bais, encoding);
}else{
isr = new InputStreamReader(bais);
}
} catch (Exception e) {
e.printStackTrace();
isr = new InputStreamReader(bais);
}
// tmpVector保存的已经是wml文档了
// 标准的wml文档格式,如下边:
// <?xml version="1.0" encoding="utf-8"?>
// <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
// <wml>
// <head>
// <meta http-equiv="Cache-Control" content="no-cache" />
// </head>
// <card id="forward" title="">
// <onevent type="onenterforward">
// <go href="signonForm.do" />
// </onevent>
// <p align="left">
// ...
// </p>
// </card>
// </wml>
Vector tmpVector = Tools.ToDocument(isr);
//#if DEBUG
//# System.out.println("==============[WML Document]============");
//# for(int i=0;i<tmpVector.size();i++){
//# System.out.println((String)tmpVector.elementAt(i));
//# }
//# System.out.println("========================================");
//#endif
renderVector(tmpVector);
}
/**
* vector里保存的是整理好的标准wml文档
* @param vector
*/
void renderVector(Vector vector){
Vector pendingRenderTag = null;
try{
pendingRenderTag = Tag.Tree(vector);
//#if DEBUG
//# for(int i=0;i<pendingRenderTag.size();i++ ){
//# Object obj =pendingRenderTag.elementAt(i);
//# System.out.println(obj.toString());
//# }
//#endif
maxElementNum = pendingRenderTag.size();
}catch(Exception e){
e.printStackTrace();
}
// 渲染前先重设Render
wapRender.reset();
if(curRequest!=null){
wapRender.explainTag(pendingRenderTag,curRequest.getFragment());
}else{
wapRender.explainTag(pendingRenderTag,null);
}
}
/**
* 获得请求的URL的base和root,以便以后及载如图片之类的资源<br>
* 例如,url为 http://zg.gameislive.com/cn/gamedev/pan/t1.wml<br>
* 那么将获得:<br>
* URL root: http://zg.gameislive.com/<br>
* URL base: http://zg.gameislive.com/cn/gamedev/pan/<br>
* @param url
*/
void getUrlRootAndBase(String url){
urlRoot = Tools.GetURLRoot(url);
String tempURL = "";
int commaIndex = url.indexOf('?');
if (commaIndex != -1) {
tempURL = url.substring(0, commaIndex);
} else {
tempURL = url;
}
//commaIndex = tempURL.lastIndexOf('/');
//urlBase = tempURL.substring(0, commaIndex + 1);
urlBase = Tools.GetURLBase(tempURL);
//#if DEBUG
//# System.out.println("[URL root]: "+urlRoot);
//# System.out.println("[URL base]: "+urlBase);
//#endif
}
private String cardid;
/**
* 当请求的地址不完整时(可能是相对路径),可通过该方法补充完整的URL<br>
* 注意,需要和urlBase,urlRoot一起使用<br>
* 使用时必须先getUrlRootAndBase(String)
* @param s
* @return
*/
public String getUrl(String s) {
if (s.startsWith("http://")) {
return s;
}
int index = s.indexOf('#');
if (index!=-1) {
cardid = s.substring(index+1);
return curRequest.getUrl();
}
if (s.startsWith("/") || s.startsWith("\\")) {
s = s.substring(1);
return urlRoot + s;
} else {
return urlBase + s;
}
}
/**
* 发送一个HTTP请求,加载图片,目前支持三种图片格式: <br/>
* -image/png <br/>
* -image/gif <br/>
* -image/jpeg <br/>
* @param s url
*/
Image loadImage(String s) {
try {
Image image = null;
// read local resource
if(s.startsWith("res:")){
String filename = Tools.RepString(s, "res:", "");
image = Image.createImage(filename);
return image;
}
byte buffer[] = null;
s = Tools.RepString(s, "&", "&");
s = getUrl(s);
String type = null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -