faces/ 0040755 0000766 0000766 00000000000 07425146602 012375 5 ustar kitazawa kitazawa faces/CalendarFormat.java 0100644 0000766 0000766 00000003706 07425146554 016133 0 ustar kitazawa kitazawa package jp.faces;
import java.util.*;
/**
* $BF|;~$NJ8;zNs@8@.(B
*
* @author Jun Kitazawa
* @version 0.1.3
*/
public class CalendarFormat {
private Calendar cal;
private String year;
private String month;
private String day;
private String hour;
private String minute;
private String second;
private String weekstr;
public CalendarFormat(){
cal = Calendar.getInstance();
year = Integer.toString(cal.get(Calendar.YEAR));
month = Integer.toString(cal.get(Calendar.MONTH)+1);
day = Integer.toString(cal.get(Calendar.DAY_OF_MONTH));
hour = Integer.toString(cal.get(Calendar.HOUR_OF_DAY));
minute = Integer.toString(cal.get(Calendar.MINUTE));
second = Integer.toString(cal.get(Calendar.SECOND));
if(month.length() < 2) month = "0" + month;
if(day.length() < 2) day = "0" + day;
if(hour.length() < 2) hour = "0" + hour;
if(minute.length() < 2) minute = "0" + minute;
if(second.length() < 2) second = "0" + second;
weekstr = "";
switch(cal.get(Calendar.DAY_OF_WEEK)){
case Calendar.SUNDAY:
weekstr = "Sun";
break;
case Calendar.MONDAY:
weekstr = "Mon";
break;
case Calendar.TUESDAY:
weekstr = "Tue";
break;
case Calendar.WEDNESDAY:
weekstr = "Wed";
break;
case Calendar.THURSDAY:
weekstr = "Thu";
break;
case Calendar.FRIDAY:
weekstr = "Fri";
break;
case Calendar.SATURDAY:
weekstr = "Sat";
break;
}
}
public String getDateStrFormat(){
String datestr;
// $B7n(B/$BF|(B/$BG/(B $B;~(B:$BJ,(B:$BIC(B
datestr = "[" + year
+ "/" + month
+ "/" + day
+ " "
+ hour
+ ":" + minute
+ ":" + second
+ "] ";
return datestr;
}
public String getDateTStrFormat(){
String TNodeStr = "";
return TNodeStr;
}
}
faces/ClientInfo.java 0100644 0000766 0000766 00000002550 07425146554 015277 0 ustar kitazawa kitazawa package jp.faces;
import java.util.*;
import java.io.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import org.apache.crimson.tree.*;
/**
* クライアント情報管理
*
* @author Jun Kitazawa
* @version 0.1.3
*/
public class ClientInfo {
private int nnum; // Pノードのn属性にあたる数
private String AppName; // クライアントが所属しているアプリケーションの名前
private int roomNum = -1; // クライアントが所属している部屋番号
/**
* 名前(selfname)をセットする
*
* @param n クライアントID
*/
public final void setNnum(int n){
nnum = n;
}
/**
* 名前(selfname)をゲットする
*
* @return クライアントID
*/
public final int getNnum(){
return nnum;
}
/**
* アプリケーション名をセットする
*
* @param app アプリケーション名
*/
public final void setAppName(String app){
AppName = app;
}
/**
* 部屋番号をセットする
* 部屋に入れる人数は無制限
* @param r 部屋番号
*/
public final void setRoomNum(int r){
roomNum = r;
}
/**
* アプリケーション名をゲットする
*
* @return アプリケーション名の文字列
*/
public final String getAppName(){
return AppName;
}
/**
* 部屋番号をゲットする
*
* @return アプリケーション名の文字列
*/
public final int getRoomNum(){
return roomNum;
}
}
faces/FacesClient.java 0100644 0000766 0000766 00000010111 07425146554 015415 0 ustar kitazawa kitazawa package jp.faces;
import java.net.*;
import java.io.*;
/**
* FacesServer用クライアントクラス
*
* @author Jun Kitazawa
* @version 0.1.3
* @see FacesServer
*/
public class FacesClient extends Thread {
/**
* サーバ(FacesServerクラスのインスタンス)
*/
private FacesServer srv;
/**
* クライアントソケット
*/
private Socket sock;
/**
* クライアントから送られてくるメッセージを受信するReader
*/
protected BufferedReader in;
/**
* クライアントへのメッセージを送信するWriter
*/
protected PrintWriter out;
/**
* XMLメッセージからDOMツリーを作って、各クライアントの情報を得るためのXML解析クラス
*/
private FacesXML px;
/**
* クライアントのIPを保持する文字列
*/
private String ipstr;
/**
* クライアント情報管理オブジェクト
*/
private ClientInfo ci;
/**
* FacesClientクラスのコンストラクタ
* FacesServerクラスのrunServerメソッドの中で呼ばれる
*
* @param srv サーバ(FacesServerクラスのインスタンス)
* @param sock ソケット
*/
public FacesClient(FacesServer srv, Socket sock) {
this.srv = srv;
this.sock = sock;
this.ipstr = sock.getInetAddress().getHostAddress();
ci = new ClientInfo();
px = new FacesXML(srv, this);
try {
// readerとwriterはそれぞれBufferedReader,PrintWriterでストリームをラップして生成
in = new BufferedReader(new InputStreamReader(sock.getInputStream(),"SJIS"));
out = new PrintWriter(new OutputStreamWriter(sock.getOutputStream(), "SJIS"), true);
} catch(IOException ioe) {
// 初期化失敗
srv.printServerMsg("initilization error on Client IP: " + ipstr + ". disconnected.");
ioe.printStackTrace();
// このクライアントを停止する
stopClient();
}
}
/**
* クライアント情報管理オブジェクトを得る
*/
public final ClientInfo getClientInfo(){
return ci;
}
/**
* クライアントからのメッセージを文字列に構成し
* FacesXmlオブジェクトのreadXMLメソッドに渡す
*/
public void run() {
try {
// 1文字分配列確保
char c[] = new char[1];
// クライアントからのストリームがある
while(in.read(c,0,1) != -1) {
// ストリーム用文字列バッファ
StringBuffer sb = new StringBuffer(4096);
// null文字がこなければ
while(c[0] != '\0') {
// バッファに1文字付加
sb.append(c[0]);
// さらに1文字ストリームから読み込み
in.read(c, 0 ,1);
}
// XMLメッセージ処理
px.readXML(sb.toString());
}
} catch(IOException ioe) {
// read errorが起こったので、コネクションを切断
srv.printServerMsg("read error on Client IP: " + ipstr + ". disconnected.");
} finally {
// 最後にはこのクライアントクラスを停止する
stopClient();
}
}
/**
* クライアントのIPの文字列を返すメソッド
*
* @return クライアントのIPの文字列
*/
public final String getIPStr() {
return ipstr;
}
/**
* クライアントにメッセージを送る。
* メッセージはnull文字"\0"が終端
*
* @param msg クライアントに送るメッセージ文字列
* @see FacesServer#sendToRoom(String msg, String an, int r)
*/
public void sendToClient(String msg) {
out.print(msg + "\0");
if(out.checkError()) {
srv.printServerMsg("write error on Client IP: " + ipstr + ". disconnected.");
//クライアントを停止する
stopClient();
}
}
/**
* クライアントを停止する
*
*/
private void stopClient() {
// FacesServerから自分(クライアントクラスのインスタンス)を削除
srv.deleteClient(this);
try {
in.close(); //BufferdReaderを閉じる
out.close(); // PrintWriterを閉じる
sock.close(); // ソケットを閉じる
} catch (IOException ioe) {
// 閉じるのに失敗したらその旨表示
srv.printServerMsg("connection error on Client IP: " + ipstr);
ioe.printStackTrace();
}
}
}
faces/FacesServer.java 0100644 0000766 0000766 00000023710 07425146554 015456 0 ustar kitazawa kitazawa package jp.faces;
import java.net.*;
import java.io.*;
import java.util.*;
/**
* FACEs Server--Flash用マルチユーザサーバ
*
* @author Jun Kitazawa
* @version 0.1.3
*/
public class FacesServer {
/**
* サーバソケット
*/
private ServerSocket srvsock;
/**
* 部屋情報のリスト
*/
private HashMap rooms = new HashMap();
/**
* クライアントのリスト
*/
private HashMap fclist = new HashMap();
private List numlist = new Vector();
/**
* データベース接続用
*/
private JDBC pg = null;
/**
* データベースを使用するかどうか
*/
private boolean jdbcflag = false;
/**
* XMLエラーメッセージマップ
*/
private XmlErrMap errMap;
/**
* サーバプロセスを起動し、DBへのコネクションを確立。クライアントからのapp指定が
* 無いときのためのデフォルトアプリケーション"0"の領域を用意しておく。
*
* @param port クライアントの接続を受け付けるポートの番号
*/
public FacesServer(int port) {
if(jdbcflag == true)
pg = new JDBC(); // データベース接続オブジェクト
// デフォルト(クライアントがapp要素を指定していない場合の)アプリケーション情報
RoomInfo roominfo = new RoomInfo(this); // デフォルトアプリケーション(名前は"0")
roominfo.setAppName("0");
roominfo.setRoomNum(0);
HashMap approoms = new HashMap();
approoms.put(new Integer(0),roominfo);
rooms.put("0",approoms); // アプリケーション"0"をアプリケーション配列に付加
errMap = new XmlErrMap(); // XMLエラーメッセージマップ
runServer(port);
}
/**
* XMLエラーメッセージマップを返す
*
* @return XMLエラーメッセージマップ
*/
public XmlErrMap getXmlErrMap(){
return errMap;
}
/**
* 空いている最小のクライアント番号を返す
*
* @return 空いている最小のクライアント番号
*/
private int getWaitingCnum(){
int num = 1;
while(true){
boolean check = true;
Iterator itr = numlist.iterator();
while (itr.hasNext()) {
Integer i = (Integer)itr.next();
int cnum = i.intValue();
if(cnum == num){
num++;
check = false;
break;
}
}
if(check){
numlist.add(new Integer(num));
return num;
}
}
}
/**
* データベースへの接続情報を得る
*
* @return JDBCインスタンス
*/
public final JDBC getPG(){
return pg;
}
/**
* アプリケーション情報の配列を得る
*
* @return アプリケーション情報(ClientInfoインスタンス)の配列
*/
public final HashMap getRooms(){
return rooms;
}
/**
* クライアントのリストを得る
*
* @return クライアントのリスト
*/
public final HashMap getClients(){
return fclist;
}
/**
* アプリケーション名と部屋番号から部屋情報を得る
*
* @param an アプリケーション名
* @param r 部屋番号
* @return 部屋情報
*/
public RoomInfo getRoomInfo(String an, int r){
HashMap list = (HashMap)rooms.get(an);
if(list != null){
RoomInfo ri = (RoomInfo)list.get(new Integer(r));
if(ri != null){
return ri;
}
}
return null;
}
/**
* クライアントIDからFacesClientオブジェクトを得る
*
* @param id クライアントID
* @return クライアントクラス
*/
public FacesClient getFacesClientFromID(int id){
Collection valueSet = fclist.values();
Iterator itr = valueSet.iterator();
while(itr.hasNext()){
Vector v = (Vector)itr.next();
Enumeration e = v.elements();
while(e.hasMoreElements()){
FacesClient fc = (FacesClient)(e.nextElement());
if(fc.getClientInfo().getNnum() == id){
return fc;
}
}
}
return null;
}
/**
* 接続しているクライアントのなかで同じアプリケーション名かつ同じ部屋番のクライアントすべてにメッセージを配る。
*
* @param msg 配るメッセージ文字列
* @param an アプリケーション名
* @param r 部屋番
*/
public void sendToRoom(String msg, String an , int r) {
// 同じ部屋のクライアントそれぞれにメッセージを送信していく
Vector v = (Vector)fclist.get(an);
if(v != null){
Enumeration e = v.elements();
while(e.hasMoreElements()){
FacesClient fc = (FacesClient)(e.nextElement());
//部屋番号が同じクライアントに送信
ClientInfo clinfo = fc.getClientInfo();
if(clinfo != null){
int roomnum = clinfo.getRoomNum();
if(roomnum == r){
fc.sendToClient(msg);
}
}
}
}
}
/**
* 接続しているクライアントのなかで同じアプリケーション名のクライアントすべてにメッセージを配る。
*
*
* @param msg 配るメッセージ文字列
* @param an アプリケーション名
*/
public void sendToApp(String msg, String an) {
// 同じアプリのクライアントそれぞれにメッセージを送信していく
Vector v = (Vector)fclist.get(an);
if(v != null){
Enumeration e = v.elements();
while(e.hasMoreElements()){
FacesClient fc = (FacesClient)(e.nextElement());
fc.sendToClient(msg);
}
}
}
/**
* 引数で指定されたアプリケーションの現在の利用者数を返す
*
* @param an アプリケーション名
* @return 利用者数
*/
public synchronized int appUserCount(String an){
Vector v = (Vector)fclist.get(an);
if(v != null){
return v.size();
}
else {
return 0;
}
}
/**
* 引数で指定された部屋の現在の利用者数を返す
*
* @param an アプリケーション名
* @param r 部屋番号
* @return 利用者数
*/
public synchronized int roomUserCount(String an, int r){
Vector v = (Vector)fclist.get(an);
Enumeration e = v.elements();
int clcnt = 0;
while(e.hasMoreElements()){
FacesClient fc = (FacesClient)(e.nextElement());
int roomnum = fc.getClientInfo().getRoomNum();
if(roomnum == r){
clcnt++;
}
}
return clcnt;
}
/**
* クライアントリストからクライアントを削除
*
* @param fc 削除するクライアントのインスタンス
*/
public void deleteClient(FacesClient fc) {
int clindex = fc.getClientInfo().getNnum();
String appname = fc.getClientInfo().getAppName();
int roomnum = fc.getClientInfo().getRoomNum();
// 誰か抜けたことを表示
printServerMsg(fc.getIPStr() + " disconnected.");
// クライアントリストからクライアントを削除
Vector v = (Vector)fclist.get(appname);
if(v != null){
v.remove(fc);
}
// クライアント番号リストから該当番号を削除
numlist.remove(new Integer(clindex));
// 抜けたクライアントの番号をおなじ部屋のクライアントとロビーに配信する
// 部屋番号0番の時には2重に送られないようにする
if(roomnum != 0){
sendToRoom("",appname,roomnum);
}
sendToRoom("",appname,0);
// 部屋のカウンタ処理(抜けたことによってカウンタが揃う場合用)
RoomInfo ritmp = getRoomInfo(appname, roomnum);
SyncCounters syncCount = ritmp.getSyncCounters();
List snlist = syncCount.evalRoomForDelete(appname, roomnum);
Iterator itr = snlist.iterator();
while(itr.hasNext()){
String n = (String)itr.next();
sendToRoom("",appname,roomnum);
}
RoomInfo ritmp0 = getRoomInfo(appname, 0);
if(ritmp0 != null){
ritmp0.deleteLogNode(clindex); // ロビーのLOGノード削除
}
HashMap list = (HashMap)rooms.get(appname);
Collection valueSet = list.values();
itr = valueSet.iterator();
while(itr.hasNext()){
ritmp = (RoomInfo)itr.next();
if(ritmp != null)
ritmp.deleteSelfSubNode(clindex); // 要素key=selfnameのノード削除
}
if(jdbcflag == true)
pg.puserDelete(clindex,appname,appUserCount(appname));
}
/**
* サーバの状態を表す文字列を標準出力に出す
*
* @param msg 表示するメッセージの本体
*/
public static void printServerMsg(String msg) {
// 引数文字列に、日時と改行コードを付加
msg = getDateStrFormat() + msg + "\n";
System.out.print(msg);
}
/**
* 月/日/年 時:分:秒
* というフォーマットで文字列を構成
*
* @return 日時を表すの文字列
*/
private static String getDateStrFormat(){
CalendarFormat cf = new CalendarFormat();
return cf.getDateStrFormat();
}
/**
* サーバをスタートさせて、接続を受け付ける
*
* @param port 接続を受け付けるポートの番号
*/
private void runServer(int port) {
// 起動中の文字列を表示
printServerMsg("starting server...");
if(jdbcflag == true)
pg.clearTables(); // DBのテーブル内容を全て消去
try {
// サーバソケットクラスのインスタンスを生成
srvsock = new ServerSocket(port);
printServerMsg("server started on port " + port);
// サーバが起動している間は。。。
while(true) {
// クライアントからの接続要求を受けとり、新しいソケットを生成する
Socket sock = srvsock.accept();
// FacesClientクラスのインスタンス生成
FacesClient fc = new FacesClient(this, sock);
// 接続成功を伝える
printServerMsg(fc.getIPStr() + " connected to the server.");
fc.getClientInfo().setNnum(getWaitingCnum()); // クライアント番号設定
// クライアントスレッドを開始する
fc.start();
}
} catch(IOException ioe) {
// 接続が失敗したことを伝える
printServerMsg("connection error. closing serversocket...");
ioe.printStackTrace();
// サーバを停止する
stopServer();
}
}
private void stopServer() {
try {
// サーバソケットを閉じる
srvsock.close();
printServerMsg("serversocket closed");
if(jdbcflag == true)
pg.close();
} catch (IOException ioe){
ioe.printStackTrace();
}
}
/**
* mainメソッド
*
* @param args[] 接続待ちポート番号のみ
*/
public static void main(String args[]) {
int portNum = 0;
// 引数の数をチェック
if(args.length == 1) {
try {
portNum = Integer.parseInt(args[0]);
}
catch (NumberFormatException e){
e.printStackTrace();
portNum = 0;
}
if(portNum > 0){
// 引数を整数型(ポート番号)にしてコンストラクタ起動
FacesServer fsrv = new FacesServer(portNum);
}
else {
printServerMsg("invalid port number. stopped.");
}
} else {
// 引数の数が間違ってたらエラー表示
printServerMsg("invalid number of argument. stopped.");
}
}
}
faces/FacesXML.java 0100644 0000766 0000766 00000040722 07425146554 014652 0 ustar kitazawa kitazawa package jp.faces;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.*;
import java.util.*;
/**
* FACEs用XMLメッセージ解析クラス
*
* @author Jun Kitazawa
* @version 0.1.3
*/
public class FacesXML {
private Document document;
private GenDom objDom;
private ClientInfo ci;
private FacesClient fc;
private FacesServer srv;
private String DocumentStr;
private JDBC pg = null;
private HashMap fclist;
/**
* コンストラクタ(引数はクライアント情報管理オブジェクト)
*
* @param srv FacesServer(メインクラス)
* @param fc このインスタンスを使用しているクライアントのインスタンス
*/
public FacesXML(FacesServer srv, FacesClient fc){
objDom = new GenDom(srv);
this.srv = srv;
this.fc = fc;
this.ci = fc.getClientInfo();
this.pg = srv.getPG();
this.fclist = srv.getClients();
}
/**
* 受け取ったXMLドキュメント文字列をDOM化
*
* @param str DOM化するXMLドキュメント文字列
*/
public void readXML(String str){
DocumentStr = str;
document = objDom.makeDom(new InputSource(new StringReader(str)));
if(document != null){
document.normalize();
DocumentAnalysis();
}
try {
String teststr = new String(str.getBytes("EUCJIS"));
//System.out.println(teststr); // ノード名表示(デバッグ用文字列 本運用のときは外す)
} catch(Exception e){
e.printStackTrace();
}
}
/**
* 部屋もしくはロビーに入って,クライアント固有の番号を得る
*
* @param nmdMap QNエレメントのAttributeのNodeMap
*/
private void processQN(NamedNodeMap nmdMap){
String appname = "";
// スタートしたクライアントに固有の番号を与える
fc.sendToClient("");
//ユーザ&部屋登録
if(nmdMap != null){ // 属性が存在するなら
Node n_node;
int max = 0;
Node max_node;
if((max_node = nmdMap.getNamedItem("max")) != null){ // max属性が存在するなら
try {
max = Integer.parseInt(max_node.getNodeValue());
} catch(Exception e) {
e.printStackTrace();
}
}
if((n_node = nmdMap.getNamedItem("app")) != null){ // app属性が存在するなら
Node r_node;
// アプリケーション名をセット
appname = n_node.getNodeValue();
ci.setAppName(appname); // 自分のクライアントのアプリケーション名セット
ci.setRoomNum(0); // 自分のクライアントの部屋番セット(とりあえず0(ロビールームの番号)に設定)
if((r_node = nmdMap.getNamedItem("r")) != null){ // r属性が存在するなら
int r = 0;
try {
r = Integer.parseInt(r_node.getNodeValue());
} catch(Exception e) {
e.printStackTrace();
}
ci.setRoomNum(r); // 自分のクライアントの部屋番セット
addNewRoom(appname,r,max);
}
else { // r属性が存在しないなら
addNewRoom(appname,0,max);
}
}
else { // app属性が存在しないなら
// アプリケーション名を"0"にセット
appname = "0";
ci.setAppName(appname);
}
}
else { // 属性が存在しないなら
// アプリケーション名を"0"にセット
appname = "0";
ci.setAppName(appname);
}
// DBのユーザテーブル(puser)にユーザID(ci.getNnum()),ユーザ名(今のところ空),アプリケーション名(appname)をセット
if(!appname.equals("0")){
if(pg != null)
pg.puserSet(ci.getNnum(),"",appname, srv.appUserCount(appname));
}
// クライアントリストにクライアントを登録
if(fclist.get(appname) == null){ // 新しい名前のアプリケーションだったら(当然部屋番も新しい)
Vector v = new Vector();
v.add(fc);
fclist.put(appname,v);
}
else { // 新しい名前のアプリケーションでなければ
Vector v = (Vector)fclist.get(appname);
int index = v.indexOf(fc);
if(index == -1){ // 既に存在するクライアントでなければ
v.add(fc);
}
}
}
private boolean addNewRoom(String appname,int r, int max){
HashMap list = (HashMap)(srv.getRooms().get(appname));
if(list == null){ // 新しい名前のアプリケーションだったら(当然部屋番も新しい)
// 指定された番号の部屋を作る
RoomInfo newRoom = new RoomInfo(srv);
newRoom.setAppName(appname);
newRoom.setRoomNum(r, max);
list = new HashMap();
list.put(new Integer(newRoom.getRoomNum()),newRoom);
// ロビーが無ければロビーを作る
if(r != 0){
RoomInfo newRoom0 = new RoomInfo(srv);
newRoom0.setAppName(appname);
newRoom0.setRoomNum(0, max);
list.put(new Integer(newRoom.getRoomNum()),newRoom);
}
srv.getRooms().put(appname,list);
// DBのアプリケーションテーブル(app)にアプリケーション名をセット
if(pg != null)
pg.appSet(appname);
return true;
}
else { // 新しい名前のアプリケーションでなければ
if(srv.getRoomInfo(appname,r) == null){
// 指定された番号の部屋を作る
RoomInfo newRoom = new RoomInfo(srv);
newRoom.setAppName(appname);
newRoom.setRoomNum(r, max);
list.put(new Integer(newRoom.getRoomNum()),newRoom);
}
else {
// 新しい部屋番でなければその既存の部屋に接続する(のでなにもしない)
// ただし部屋が最大人数に達していたらエラーメッセージをクライアントに送り、
// デフォルトアプリケーション(アプリケーション名0)に接続する
RoomInfo ritmp = srv.getRoomInfo(appname, r);
int roomMaxP = 0;
if(ritmp != null)
roomMaxP = ritmp.getRoomMaxP();
if(roomMaxP != 0){
if(srv.roomUserCount(appname, r) >= roomMaxP){
// エラー送信,デフォルトアプリケーションに接続
fc.sendToClient("");
appname = "0";
ci.setAppName(appname);
}
}
}
return false;
}
}
/**
* サーバが保持している情報をリクエスト
*
* @param nmdMap QRエレメントのAttributeのNodeMap
*/
private void processQR(NamedNodeMap nmdMap){
// 属性が存在するならn属性で指定した名前のノードの内容をリクエスト
if(nmdMap != null){
String requestedNodeName;
Node n_node;
if((n_node = nmdMap.getNamedItem("n")) != null){
RoomInfo ritmp = srv.getRoomInfo(ci.getAppName(), ci.getRoomNum());
if(ritmp != null){
if(n_node.getNodeValue().equals("COUNT")){ // リクエストされたノードの名前がCOUNTだったら
fc.sendToClient(ritmp.outputLogCount());
}
else {
fc.sendToClient(ritmp.outputByNodeName(n_node));
}
}
}
else {
// 保持しているノード全部送る
RoomInfo ritmp = srv.getRoomInfo(ci.getAppName(), ci.getRoomNum());
if(ritmp != null)
fc.sendToClient(ritmp.outputAll());
}
}
// 属性が存在しないならサーバが保持しているすべての情報をリクエスト(クライアント側から)
else {
RoomInfo ritmp = srv.getRoomInfo(ci.getAppName(), ci.getRoomNum());
if(ritmp != null){
fc.sendToClient(ritmp.outputAll());
}
}
}
/**
* サーバが保持している情報をファイルにセーブ
*
* @param nmdMap QFエレメントのAttributeのNodeMap
*/
private void processQF(NamedNodeMap nmdMap){
// 属性が存在するならn属性で指定した名前のノードの内容をファイルにセーブ
RoomInfo ritmp = srv.getRoomInfo(ci.getAppName(), ci.getRoomNum());
if(nmdMap != null){
Node n_node;
if((n_node = nmdMap.getNamedItem("n")) != null){
if(ritmp != null)
fc.sendToClient(ritmp.saveByNodeName(n_node));
}
else {
// 保持しているノード全部送る
if(ritmp != null)
fc.sendToClient(ritmp.saveAll());
}
}
// 属性が存在しないならサーバが保持しているすべての情報をファイルにセーブ
else {
if(ritmp != null)
fc.sendToClient(ritmp.saveAll());
}
}
/**
* サーバが保持している情報を消去
*
* @param nmdMap QEエレメントのAttributeのNodeMap
*/
private void processQE(NamedNodeMap nmdMap){
// 属性が存在するならn属性で指定した名前のノードを消去
RoomInfo ritmp = srv.getRoomInfo(ci.getAppName() ,ci.getRoomNum());
if(nmdMap != null && ritmp != null){
Node n_node;
if((n_node = nmdMap.getNamedItem("n")) != null){
Node key_node;
if((key_node = nmdMap.getNamedItem("key")) != null){
if(n_node.getNodeValue().equals("all")){
ritmp.clearByKey(key_node);
}
else {
ritmp.clearByNodeNameAndKey(n_node, key_node);
}
}
else {
Node self_node = nmdMap.getNamedItem("self");
if(n_node.getNodeValue().equals("all")){
if(self_node != null){
ritmp.clearBySelf(self_node);
}
else {
ritmp.clearAll();
}
}
else {
if(self_node != null){
ritmp.clearByNodeNameAndSelf(n_node, self_node);
}
else {
ritmp.clearByNodeName(n_node);
}
}
}
}
else {
// 保持しているノードすべて消去
if(ritmp != null)
ritmp.clearAll();
}
}
// 属性が存在しないならサーバが保持しているすべての情報を消去
else {
if(ritmp != null)
ritmp.clearAll();
}
}
/**
* サーバにカウンタ名と待機カウントを送信
*
* @param nmdMap QSエレメントのAttributeのNodeMap
*/
private void processQS(NamedNodeMap nmdMap, int self){
// 属性が存在するなら
RoomInfo ritmp = srv.getRoomInfo(ci.getAppName() ,ci.getRoomNum());
if(nmdMap != null && ritmp != null){
String SNodeStr;
if((SNodeStr = ritmp.checkQSNode(nmdMap, self)) != null){
srv.sendToRoom(SNodeStr, ci.getAppName(), ci.getRoomNum());
}
}
}
/**
* ロビーの情報から空き部屋番号を返す。
*
* @param nmdMap QERエレメントのAttributeのNodeMap
*/
private void processQER(NamedNodeMap nmdMap){
// 属性が存在するなら
RoomInfo ritmp = srv.getRoomInfo(ci.getAppName() ,ci.getRoomNum());
if(nmdMap != null && ritmp != null){
String ErNodeStr;
if((ErNodeStr = ritmp.checkQERNode(nmdMap)) != null){
srv.sendToRoom(ErNodeStr, ci.getAppName(), ci.getRoomNum());
}
}
}
/**
* サーバ上の正確な時刻を送信
*
* @param nmdMap QTエレメントのAttributeのNodeMap
*/
private void processQT(NamedNodeMap nmdMap){
CalendarFormat cf = new CalendarFormat();
fc.sendToClient(cf.getDateTStrFormat());
}
/**
* n属性で指定されたクライアント番号のクライアントを消去
*
* @param nmdMap DエレメントのAttributeのNodeMap
*/
private void processD(NamedNodeMap nmdMap){
if(nmdMap != null){
String requestedClientID;
Node n_node;
if((n_node = nmdMap.getNamedItem("n")) != null){
requestedClientID = n_node.getNodeValue();
FacesClient fcc;
if((fcc = srv.getFacesClientFromID(Integer.parseInt(requestedClientID))) != null){
//srv.deleteClient(fcc);
RoomInfo ritmp = srv.getRoomInfo(ci.getAppName() ,0);
if(ritmp != null)
ritmp.deleteLogNode(Integer.parseInt(requestedClientID));
ritmp = srv.getRoomInfo(ci.getAppName(), ci.getRoomNum());
if(ritmp != null)
ritmp.deleteSelfSubNode(Integer.parseInt(requestedClientID)); // 要素self=selfnameのノード削除
}
}
}
}
/**
* (クライアントから送られてきたドキュメントの)トップノードがQN,QR,QF,QE,QS,Dのいずれかでないノードの処理
*
* @param node 素通し配信(もしくはサーバのメモリ上に残した上で配信)するノード
*/
private void processUserNode(Node node){
NamedNodeMap nmdMap;
Node fixed = node.cloneNode(true); // 送信用にsaveとkeyをあとで消す
if((nmdMap = node.getAttributes()) != null){ // 属性が存在するなら
Node saveattr = nmdMap.getNamedItem("save");
Node toattr = nmdMap.getNamedItem("to");
boolean allsave = false;
if(saveattr != null){
RoomInfo ritmp = null;
// save属性とto属性両方ある場合は、toで指定された部屋でsave
if(saveattr != null && toattr != null){
// to属性の値がallだったら全ての部屋番でsave
if(toattr.getNodeValue().equals("all")){
HashMap list = (HashMap)(srv.getRooms().get(ci.getAppName()));
Collection valueSet = list.values();
Iterator itr = valueSet.iterator();
allsave = true;
while(itr.hasNext()){
ritmp = (RoomInfo)itr.next();
if(saveattr.getNodeValue().equals("1")){
//情報を配列でない形で保持する場合(部屋単位)
// save
if(ritmp != null)
ritmp.checkNodeName(node);
}
else {
//情報を配列で保持する場合(部屋単位)
// ノード名がLOGの時の処理は,
// Dノードを受信したときに対処
if(ritmp != null)
ritmp.checkNodeListName(node);
}
}
}
// to属性の値が番号だったら番号で指定されたクライアントの属する部屋でsave
else {
int toid = 0;
try {
toid = Integer.parseInt(toattr.getNodeValue());
} catch(Exception e){
e.printStackTrace();
}
if(toid != 0){
FacesClient toClient = srv.getFacesClientFromID(toid);
if(toClient != null){
int toRoomNum = toClient.getClientInfo().getRoomNum();
ritmp = srv.getRoomInfo(ci.getAppName() , toRoomNum);
}
}
}
}
else {
ritmp = srv.getRoomInfo(ci.getAppName() ,ci.getRoomNum());
}
//情報を配列で無い形で保持する場合(部屋単位)
if(saveattr.getNodeValue().equals("1")){
// save
if(ritmp != null)
ritmp.checkNodeName(node);
}
else {
//情報を配列で保持する場合(部屋単位)
// ノード名がLOGの時の処理は,
// Dノードを受信したときに対処
if(ritmp != null)
ritmp.checkNodeListName(node);
Node subattr = nmdMap.getNamedItem("key");
// sendToRoom時にkeyを消す
if(subattr != null)
((Element)fixed).removeAttribute("key");
}
// sendToRoom時にsaveを消す
((Element)fixed).removeAttribute("save");
// sendToRoom時にselfを消す
NamedNodeMap nmdMap2 = fixed.getAttributes();
if(nmdMap2 != null){
if(nmdMap2.getNamedItem("self") != null){
((Element)fixed).removeAttribute("self");
}
}
}
// to属性が付いていたら,特定のIDをもつクライアントのみに送信
if(toattr != null){
int toid = 0;
// to属性の値がallだったら部屋番に関らず同じアプリの全員に送る
if(toattr.getNodeValue().equals("all")){
srv.sendToApp(RoomInfo.getNode(fixed), ci.getAppName());
return;
}
// to属性の値が番号なら
else {
try {
toid = Integer.parseInt(toattr.getNodeValue());
} catch(Exception e){
e.printStackTrace();
}
if(toid != 0){
((Element)fixed).removeAttribute("to");
FacesClient fcto = srv.getFacesClientFromID(toid);
if(fcto != null){
fcto.sendToClient(RoomInfo.getNode(fixed));
}
return;
}
}
}
}
// ブロードキャスト
srv.sendToRoom(RoomInfo.getNode(fixed), ci.getAppName(), ci.getRoomNum());
}
/**
* 受け取ったXMLドキュメント文字列をDOM化し、
* 要素、属性の種類に応じて処理する。
*
*/
private void DocumentAnalysis(){
Node node = document.getFirstChild();
NamedNodeMap nmdMap = node.getAttributes();
if(node.getNodeName().equals("QN")){ // 部屋もしくはロビーに入って,クライアント固有の番号を得る
processQN(nmdMap);
}
else if(node.getNodeName().equals("QR")){ // サーバが保持している情報をリクエスト
processQR(nmdMap);
}
else if(node.getNodeName().equals("QF")){ // サーバが保持している情報をファイルにセーブ
processQF(nmdMap);
}
else if(node.getNodeName().equals("QE")){ // サーバが保持している情報を消去
processQE(nmdMap);
}
else if(node.getNodeName().equals("QS")){ // サーバにカウンタ名と待機カウントを送信
processQS(nmdMap, ci.getNnum());
}
else if(node.getNodeName().equals("QT")){ // サーバ上の正確な時刻を送信
processQT(nmdMap);
}
else if(node.getNodeName().equals("QER")){ // ロビーの情報から空き部屋番号を返す。
processQER(nmdMap);
}
else if(node.getNodeName().equals("D")){ // n属性で指定されたクライアント番号のクライアントを消去
processD(nmdMap);
}
else { // クライアントから送られてきたドキュメントのトップノードがQN,QR,QF,QE,QS,Dのいずれかでなければ
processUserNode(node);
}
}
}
/**
*
* DOMオブジェクト生成
*
*/
class GenDom extends DefaultHandler {
private XmlErrMap errMap;
private boolean hm;
private FacesServer srv;
/**
* エラーメッセージマップ生成。
*
*/
public GenDom(FacesServer srv){
errMap = srv.getXmlErrMap();
}
/**
* DOMオブジェクト生成
*
* @param in 入力ソース
* @return Documentインスタンス
*/
public Document makeDom(InputSource in){
Document document = null;
try {
DocumentBuilder docBld = DocumentBuilderFactory.newInstance().newDocumentBuilder();
if(in != null){
document = docBld.parse(in);
document.normalize();
}
} catch(IOException ioe){
ioe.printStackTrace();
return null;
} catch(SAXParseException saxpe){
System.out.println("\nXML error in line" + saxpe.getLineNumber());
System.out.println(saxpe.getMessage());
if(errMap.getLoaded()){
System.out.println(errMap.getErrMessage(saxpe.getMessage()));
}
return null;
} catch(ParserConfigurationException pce){
pce.printStackTrace();
return null;
} catch(SAXException saxe){
System.out.println(saxe.getMessage());
return null;
}
return document;
}
}
faces/JDBC.java 0100644 0000766 0000766 00000011362 07425146554 013750 0 ustar kitazawa kitazawa package jp.faces;
import java.sql.*;
/**
* JDBCによるSQLデータベースへの接続とテーブル操作を扱う
*
* @author Jun Kitazawa
* @version 0.1.3
*/
public class JDBC {
private Connection Conn;
/**
* SQLデータベースサーバへ接続
* 現在接続先とデータベース名がハードコードされているが,ファイルから読み込むよう変更予定
*/
public JDBC(){
try {
// Load JDBC-ODBC Bridge Driver
Class.forName("org.postgresql.Driver");
String strConn = "jdbc:postgresql://192.168.254.10:5432/kitazawa";
// Connect to DBMS
Conn = DriverManager.getConnection( strConn, "kitazawa", "" );
} catch ( Exception e ) {
System.out.println( "Error: " + e);
e.printStackTrace();
}
}
/**
* SQL命令文字列(SELECT文)を実行
*
* @param sqlstr SQL命令文字列(SELECT文)
* @return ResultSetインスタンス
*/
public ResultSet sqlexec(String sqlstr) {
ResultSet rs;
try {
// Execute SELECT query.
Statement st = Conn.createStatement();
//java.sql.ResultSet rs = st.executeQuery("SELECT * from BookTable");
rs = st.executeQuery(sqlstr);
// Show result
/*
while ( rs.next() ) {
int nBookID = rs.getInt("BookID");
String strTitle = rs.getString("Title");
System.out.print("BookID: " + nBookID );
System.out.println(" Title: " + strTitle );
}
*/
//rs.close();
return rs;
} catch ( Exception e ) {
System.out.println( "Error: " + e);
e.printStackTrace();
return null;
}
}
/**
* ResultSet内の項目数を数える
*
* @param rs ResultSetインスタンス
* @return 項目数
*/
public int ResultCount(ResultSet rs){
int count = 0;
if(rs != null){
try {
while ( rs.next() ) {
count++;
}
rs.close();
} catch ( Exception e ) {
System.out.println( "Error: " + e);
e.printStackTrace();
}
}
return count;
}
/**
* SQL命令文字列(SELECT文)を実行
*
* @param sqlstr 結果を返さないSQL命令文字列(DELETE,INSERT,UPDATE文)
* @return 変更した項目数
*/
public int sqlupdate(String sqlstr) {
int row = -1;
try {
// Execute query.
Statement st = Conn.createStatement();
row = st.executeUpdate(sqlstr);
} catch ( Exception e ) {
System.out.println( "Error: " + e);
e.printStackTrace();
}
return row;
}
/**
* アプリケーション名をappテーブルにセット
*
* @param appname アプリケーション名
*/
public synchronized void appSet(String appname){
sqlupdate("DELETE FROM app WHERE appname = '" + appname +"'");
sqlupdate("INSERT INTO app VALUES('" + appname + "',0)");
}
/**
* ユーザをpuserテーブルにセットし、新しいユーザ数をappテーブルにセット
*
* @param id ユーザID
* @param username ユーザ名(現在未使用)
* @param appname アプリケーション名
* @param count 新しいユーザ数
*/
public synchronized void puserSet(int id, String username, String appname, int count){
sqlupdate("DELETE FROM puser WHERE userid = " + id);
sqlupdate("INSERT INTO puser VALUES(" + id + ",'" + username + "','" + appname + "')");
//int row = ResultCount(sqlexec("SELECT * from puser where appname = '" + appname + "'"));
//sqlupdate("UPDATE app SET usercount = " + row + " WHERE appname = '" + appname + "'");
if(count != -1){
sqlupdate("UPDATE app SET usercount = " + count + " WHERE appname = '" + appname + "'");
}
}
/**
* ユーザをpuserテーブルから削除し、新しいユーザ数をappテーブルにセット
*
* @param id ユーザID
* @param appname アプリケーション名
* @param count 新しいユーザ数
*/
public void puserDelete(int id, String appname, int count){
sqlupdate("DELETE FROM puser WHERE userid = " + id);
//int row = ResultCount(sqlexec("SELECT * from puser where appname = '" + appname + "'"));
//sqlupdate("UPDATE app SET usercount = " + row + " WHERE appname = '" + appname + "'");
if(count != -1){
sqlupdate("UPDATE app SET usercount = " + count + " WHERE appname = '" + appname + "'");
}
else {
}
}
/**
* アプリケーション名をappテーブルから削除
*
* @param appname アプリケーション名
*/
public void appDelete(String appname){
sqlupdate("DELETE FROM app WHERE appname = '" + appname +"'");
}
/**
* puserテーブルとappテーブルを全クリア
*/
public void clearTables(){
sqlupdate("DELETE FROM puser");
//sqlupdate("DELETE FROM app");
sqlupdate("UPDATE app SET usercount = 0");
}
/**
* データベース接続を閉じる
*/
public void close() {
try {
clearTables();
Conn.close();
} catch ( Exception e ) {
System.out.println( "Error: " + e);
e.printStackTrace();
}
}
}
faces/RoomInfo.java 0100644 0000766 0000766 00000046512 07425146554 015003 0 ustar kitazawa kitazawa package jp.faces;
import java.util.*;
import java.io.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import org.apache.crimson.tree.*;
/**
* 部屋情報管理
*
* @author Jun Kitazawa
* @version 0.1.3
*/
public class RoomInfo {
private HashMap nodeNameshm = new HashMap(); //リストで無い形で保持するノードの名前リスト
// saveをキーにしたHashMap(要素はkeyをキーにしたHashMap(要素はNode))
private HashMap nodeSaveMap = new HashMap();
private String AppName; // クライアントが所属しているアプリケーションの名前
private int roomNum = -1; // クライアントが所属している部屋番号
private int roomMaxP = 0; // 部屋に入れる人数の最大値(デフォルト値(0)なら無制限)
private SyncCounters syncCount;
private FacesServer srv;
/*
* 部屋クラスのコンストラクタ
* @param server サーバオブジェクト(部屋の人数を知るときに参照する)
*/
public RoomInfo(FacesServer server){
srv = server;
syncCount = new SyncCounters(srv); // カウンタセットのインスタンス
}
public SyncCounters getSyncCounters(){
return syncCount;
}
/**
* XML文字列をファイルにセーブ
*
* @param xmlstr XML文字列
* @param prefix ファイル名に付けるプレフィクス
* @return SERVERMSG要素のみのXMLドキュメント文字列
*
*/
private String FileSave(String xmlstr, String prefix){
String timestr = (new Long(System.currentTimeMillis())).toString();
String to_name = prefix + timestr + ".xml";
File to_file = new File(to_name);
if(to_file.exists()){
if(!to_file.canWrite()){
System.out.println("");
return "";
}
}
else {
String parent = to_file.getParent(); // デスティネーションディレクトリを取得
if(parent == null) parent = System.getProperty("user.dir"); // カレントディレクトリ
File dir = new File(parent); // ファイルに変換
if(!dir.exists()){
System.out.println("");
return "";
}
if(dir.isFile()){
System.out.println("");
return "";
}
if(!dir.canWrite()){
System.out.println("");
return "";
}
}
// ここまでくればOK。
FileOutputStream to = null; // デスティネーションへの書き込み用のストリーム
try {
byte[] buffer = xmlstr.getBytes();
to = new FileOutputStream(to_file); // 出力ストリームの作成
to.write(buffer);
}
catch(Exception e){
e.printStackTrace();
}
finally {
if(to != null) {
try {
to.close();
} catch (IOException ioe){
ioe.printStackTrace();
}
}
}
System.out.println("");
return "";
}
/**
* 保持しているノード配列の中の指定されたノード名のノードをXMLドキュメント文字列にしてファイルにセーブ
*
* @param nodename セーブしたいノード名
* @return SERVERMSG要素のみのXMLドキュメント文字列
*/
public String saveByNodeName(Node node){ // 文字列をファイルにセーブ
return FileSave(outputByNodeName(node), AppName + "_" + node.getNodeValue() + "_");
}
/**
* 保持しているノード配列の中のノード全てをXMLドキュメント文字列にしてファイルにセーブ
*
* @return SERVERMSG要素のみのXMLドキュメント文字列
*/
public String saveAll(){ // 文字列をファイルにセーブ
return FileSave(outputAll(), AppName + "_");
}
/**
* (ロビーに)セーブされているLogノードの数をCOUNTタグで返す
*
* @return COUNTタグ
*/
public String outputLogCount(){
return "";
}
/**
* 保持しているノードの中で、リクエストされたノード名のものを出力用XMLドキュメントに整形
* クライアントからリクエストがあったとき用
*
* @param savenode リクエストするノード名
* @return リクエストされたノード名のノードを文字列にしたもの
*/
public String outputByNodeName(Node savenode){
Document doc = new XmlDocument();
Node node = (Node)nodeNameshm.get(savenode.getNodeValue());
if(node != null){
Node listnode = doc.importNode(node,true);
// XML整形
NamedNodeMap nmdMap = listnode.getAttributes();
if(nmdMap != null){
if(nmdMap.getNamedItem("self") != null){
((Element)listnode).removeAttribute("self");
}
if(nmdMap.getNamedItem("to") != null){
((Element)listnode).removeAttribute("to");
}
}
doc.appendChild(listnode);
return getNode(doc.getDocumentElement());
}
HashMap nodeSubMap = (HashMap)nodeSaveMap.get(savenode.getNodeValue());
if(nodeSubMap != null){
// XML整形
//Document doc = new XmlDocument();
Element e = doc.createElement(savenode.getNodeValue());
doc.appendChild(e);
Collection valueSet = nodeSubMap.values();
Iterator itro = valueSet.iterator();
while(itro.hasNext()){
Node childnode = doc.importNode((Node)itro.next(),true);
((Element)childnode).removeAttribute("save");
((Element)childnode).removeAttribute("key");
NamedNodeMap nmdMap = childnode.getAttributes();
if(nmdMap != null){
if(nmdMap.getNamedItem("self") != null){
((Element)childnode).removeAttribute("self");
}
if(nmdMap.getNamedItem("to") != null){
((Element)childnode).removeAttribute("to");
}
}
e.appendChild(childnode);
}
return getNode(doc.getDocumentElement());
}
return "<" + savenode.getNodeValue() + "/>"; // 一致するノードがなかった
}
/**
* 保持しているノードをすべて消去
*/
public void clearAll(){
nodeNameshm.clear();
nodeSaveMap.clear();
}
/**
* 指定されたノード名のノードをすべて消去
*/
public void clearByNodeName(Node savenode){
if(nodeNameshm.remove(savenode.getNodeValue()) != null){
return;
}
if(nodeSaveMap.remove(savenode.getNodeValue()) != null){
return;
}
}
/**
* 指定されたノード名の指定されたキーをもつノードを消去
*/
public void clearByNodeNameAndKey(Node savenode, Node keynode){
HashMap nodeSubMap = (HashMap)nodeSaveMap.get(savenode.getNodeValue());
if(nodeSubMap != null){
nodeSubMap.remove(keynode.getNodeValue());
}
}
/**
* 指定されたノード名の指定されたselfnameをもつノードを消去
*/
public void clearByNodeNameAndSelf(Node savenode, Node selfnode){
String savenodestr = savenode.getNodeValue();
String selfnodestr = selfnode.getNodeValue();
clearByNodeNameAndSelfString(savenodestr, selfnodestr);
}
private void clearByNodeNameAndSelfString(String savenode, String selfnode){
Node node = (Node)nodeNameshm.get(savenode);
if(node != null){
NamedNodeMap nmdMap = node.getAttributes();
if(nmdMap != null){
Node tmpselfnode;
if((tmpselfnode = nmdMap.getNamedItem("self")) != null){
if(tmpselfnode.getNodeValue().equals(selfnode)){
nodeNameshm.remove(savenode);
}
}
}
}
HashMap nodeSubMap = (HashMap)nodeSaveMap.get(savenode);
if(nodeSubMap != null){
Collection valueSet = nodeSubMap.values();
Iterator itr = valueSet.iterator();
while(itr.hasNext()){
Node tmpnode = (Node)itr.next();
NamedNodeMap nmdMap = tmpnode.getAttributes();
if(nmdMap != null){
Node tmpselfnode;
if((tmpselfnode = nmdMap.getNamedItem("self")) != null){
if(tmpselfnode.getNodeValue().equals(selfnode)){
itr.remove();
}
}
}
}
}
}
/**
* 指定されたselfnameをもつノードをすべて消去
*/
public void clearBySelf(Node selfnode){
Set keySet = nodeSaveMap.keySet();
Iterator itr = keySet.iterator();
while(itr.hasNext()){
String savenodestr = (String)itr.next();
clearByNodeNameAndSelfString(savenodestr, selfnode.getNodeValue());
}
}
/**
* 指定されたkeyをもつノードをすべて消去
*/
public void clearByKey(Node keynode){
Collection valueSet = nodeSaveMap.values();
Iterator itr = valueSet.iterator();
while(itr.hasNext()){
((HashMap)itr.next()).remove(keynode.getNodeValue());
}
}
/**
* 保持しているノードをすべてXMLドキュメント文字列に整形
* クライアントからリクエストがあったとき用に
*
* @return XMLドキュメント文字列
*/
public String outputAll(){
Document doc = new XmlDocument();
Element rootElement = doc.createElement("R");
doc.appendChild(rootElement);
Collection valueSet = nodeNameshm.values();
Iterator itr = valueSet.iterator();
while(itr.hasNext()){
Node listnode = doc.importNode((Node)itr.next(), true);
// XML整形
rootElement.appendChild(listnode);
}
Set saveMapSet = nodeSaveMap.keySet();
itr = saveMapSet.iterator();
while(itr.hasNext()){
String savenodestr = (String)itr.next();
HashMap nodeSubMap = (HashMap)nodeSaveMap.get(savenodestr);
Element e = null;
try {
e = doc.createElement(savenodestr);
rootElement.appendChild(e);
}
catch(DOMException dome){
dome.printStackTrace();
}
valueSet = nodeSubMap.values();
Iterator itro = valueSet.iterator();
while(itro.hasNext()){
Node childnode = doc.importNode((Node)itro.next(),true);
((Element)childnode).removeAttribute("save");
((Element)childnode).removeAttribute("key");
NamedNodeMap nmdMap = childnode.getAttributes();
if(nmdMap != null){
if(nmdMap.getNamedItem("self") != null){
((Element)childnode).removeAttribute("self");
}
if(nmdMap.getNamedItem("to") != null){
((Element)childnode).removeAttribute("to");
}
}
if(e != null)
e.appendChild(childnode);
}
}
return getNode(doc.getDocumentElement());
}
/**
* QERエレメントをを解析し、空き部屋番号を返す
*
* @param nmdMap QERエレメントの要素
*/
public String checkQERNode(NamedNodeMap nmdMap){
int maxint;
Node max_node;
if((max_node = nmdMap.getNamedItem("max")) != null){ // n属性(カウンタ名)があれば
try {
maxint = Integer.parseInt(max_node.getNodeValue());
} catch(Exception e){
maxint = 5;
e.printStackTrace();
}
return "";
}
else {
return null;
}
}
/**
* QSエレメントを解析し、カウンタを生成もしくはインクリメントする。maxに達した場合カウンタを
* 削除しSノードを送信
* @param nmdMap QSエレメントの要素
* @return カウンタがmaxに達している場合Sノード文字列, そうでない場合はnull
*/
public String checkQSNode(NamedNodeMap nmdMap, int self){
//NamedNodeMap nmdMap = node.getAttributes(); // 属性を得る
String n; // カウンタ名
int maxint = 1; // 待機カウント
int rn; // max="Rx" flag="Rx"の場合のxの部分のが表す部屋番号
Node n_node;
Node max_node;
Node flag_node;
if((n_node = nmdMap.getNamedItem("n")) != null){ // n属性(カウンタ名)があれば
n=n_node.getNodeValue();
if((max_node = nmdMap.getNamedItem("max")) != null){ // max属性(待機カウント)があれば
try {
maxint = Integer.parseInt(max_node.getNodeValue());
} catch(Exception e){
String maxstr = max_node.getNodeValue();
if(maxstr.startsWith("R")){
try {
rn = Integer.parseInt(maxstr.substring(1));
maxint = srv.roomUserCount(AppName, rn);
}
catch(Exception ee){
maxint = 1;
}
}
else {
maxint = 1;
}
}
}
else { // max属性(待機カウント)がなければ
//maxint = 1;
// flag属性(待機カウント(部屋の全員にフラグを立てる))があれば
if((flag_node = nmdMap.getNamedItem("flag")) != null){
String flagstr = flag_node.getNodeValue();
if(flagstr.startsWith("R")){
try {
rn = Integer.parseInt(flagstr.substring(1));
if(!syncCount.evalRoom(AppName, rn, n, self)){
return "";
}
else {
return null;
}
}
catch(Exception ee){
maxint = 1;
}
}
else {
maxint = 1;
}
}
}
}
else { // n属性(カウンタ名)がなければ(カウンタはデフォルトカウンタ)
if((max_node = nmdMap.getNamedItem("max")) != null){ // max属性(待機カウント)があれば
n = "0";
try {
maxint = Integer.parseInt(max_node.getNodeValue());
} catch(Exception e){
maxint = 1;
}
}
else { // max属性(待機カウント)がなければ
n = "0";
maxint = 1;
}
}
// カウンタをセットする。もしカウンタがmaxに達していたらSノードを送信
if(!syncCount.setCounter(n,maxint)){
return "";
}
else if(maxint <= 1){
return "";
}
else {
return null;
}
}
/**
* 情報を配列で無い形で保持する場合
* saveを削除してリスト更新
*
* @param node ノードインスタンス
*/
public void checkNodeName(Node node){
((Element)node).removeAttribute("save");
nodeNameshm.put(node.getNodeName(),node);
}
/**
* 情報を配列で保持する場合
* すでにリストにあるかどうかチェックし、なければリストに付加、あれば更新
*
* @param node ノードインスタンス
*/
public void checkNodeListName(Node node){
NamedNodeMap nmdMap = node.getAttributes();
Node savenode = null;
Node subnode = null;
if(nmdMap != null){
savenode = nmdMap.getNamedItem("save");
subnode = nmdMap.getNamedItem("key");
}
HashMap nodelist = null;
if(savenode != null)
nodelist = (HashMap)nodeSaveMap.get(savenode.getNodeValue());
if(nodelist != null && subnode != null){
nodelist.put(subnode.getNodeValue(), node);
}
else {
HashMap nodeSubMap = new HashMap(); // keyをキーにしたHashMap(要素はNode)
if(subnode != null)
nodeSubMap.put(subnode.getNodeValue(), node);
if(savenode != null)
nodeSaveMap.put(savenode.getNodeValue(), nodeSubMap);
}
}
/**
* ロビーにのこしてある自分が書いたLOGノードを消去する
* リストにあるかどうかチェックし、あれば消去
*
* @param n クライアントID
*/
public void deleteLogNode(int n){
Collection valueSet = nodeSaveMap.values();
Iterator itr = valueSet.iterator();
while(itr.hasNext()){
HashMap nodeSubMap = (HashMap)itr.next();
// ノード名が一致した(リストにあった)ら
Node listnode = (Node)nodeSubMap.get(Integer.toString(n));
if(listnode != null){
if(listnode.getNodeName().equals("LOG")){
nodeSubMap.remove(Integer.toString(n));
}
}
}
}
/**
* セーブされているLogノードをカウントする
*
* @return LOGノードの数
*/
private int countLogNode(){
Collection valueSet = nodeSaveMap.values();
Iterator itr = valueSet.iterator();
int cnt = 0;
while(itr.hasNext()){
HashMap nodeSubMap = (HashMap)itr.next();
Collection valueSeto = nodeSubMap.values();
Iterator itro = valueSeto.iterator();
while(itro.hasNext()){
Node listnode = (Node)itro.next();
if(listnode != null){
if(listnode.getNodeName().equals("LOG")){
cnt++;
}
}
}
}
return cnt;
}
/**
* Logノードをしらべて空き部屋を探す
*
*
*/
private int getEmptyRoomNum(int max){
Collection valueSet = nodeSaveMap.values();
Iterator itr = valueSet.iterator();
int cnt = 0;
Node rnode;
int count[] = new int[256];
for(int i = 0; i < 256; i++){
count[i] = 0;
}
while(itr.hasNext()){
HashMap nodeSubMap = (HashMap)itr.next();
Collection valueSeto = nodeSubMap.values();
Iterator itro = valueSeto.iterator();
while(itro.hasNext()){
Node listnode = (Node)itro.next();
if(listnode != null){
if(listnode.getNodeName().equals("LOG")){
NamedNodeMap nmdMap = listnode.getAttributes();
if((rnode =nmdMap.getNamedItem("r")) != null){
try {
int rnum = Integer.parseInt(rnode.getNodeValue());
count[rnum]++;
} catch(Exception e){
e.printStackTrace();
}
}
}
}
}
}
for(int i = 1; i < 256; i++){
if(count[i] < max){
return i;
}
}
return -1;
}
/**
* ログアウトした部屋で要素self=selfnameのデータを消去する
* リストにあるかどうかチェックし、あれば消去
*
* @param n クライアントID
*/
public void deleteSelfSubNode(int n){
Collection valueSet = nodeSaveMap.values();
Iterator itr = valueSet.iterator();
while(itr.hasNext()){
HashMap nodeSubMap = (HashMap)itr.next();
// ノード名が一致した(リストにあった)ら
Collection valueSetSub = nodeSubMap.values();
Iterator itro = valueSetSub.iterator();
while(itro.hasNext()){
NamedNodeMap nmdMap = ((Node)itro.next()).getAttributes();
Node self_node;
if((self_node = nmdMap.getNamedItem("self")) != null){
if(self_node.getNodeValue().equals(Integer.toString(n))){
itro.remove();
}
}
}
}
valueSet = nodeNameshm.values();
itr = valueSet.iterator();
while(itr.hasNext()){
NamedNodeMap nmdMap = ((Node)itr.next()).getAttributes();
Node self_node;
if((self_node = nmdMap.getNamedItem("self")) != null){
if(self_node.getNodeValue().equals(Integer.toString(n))){
itr.remove();
}
}
}
}
/**
* ノードを文字列にする
*
* @param node 文字列にしたいノードインスタンス
* @return XML文字列
*/
public static String getNode(Node node){
String nstr = "";
if (node.getNodeType() == Node.TEXT_NODE) {
//System.out.print(node.getNodeValue());
nstr = nstr + node.getNodeValue();
}
else if (node.getNodeType() == Node.ELEMENT_NODE){
//System.out.print("<");
//System.out.print(node.getNodeName());
nstr = nstr + "<" + node.getNodeName();
NamedNodeMap nmdMap = node.getAttributes(); // 属性を得る
if(nmdMap != null){ // 属性が存在したら
for(int nSb = 0; nSb < nmdMap.getLength(); nSb++){ // 属性をすべてスキャン
String nn = nmdMap.item(nSb).getNodeName();
String nv = nmdMap.item(nSb).getNodeValue();
//System.out.print(" " + nn + "=\"" + nv + "\"");
nstr = nstr + " " + nn + "=\"" + nv + "\"";
}
}
if(!node.hasChildNodes()){
//System.out.print("/>");
nstr = nstr + "/>";
}
else {
//System.out.print(">");
nstr = nstr + ">";
for (Node childnode = node.getFirstChild();
childnode != null;
childnode = childnode.getNextSibling() ){
//getNode(childnode);
nstr = nstr + getNode(childnode);
}
//System.out.print("");
//System.out.print(node.getNodeName());
//System.out.print(">\n");
nstr = nstr + "";
nstr = nstr + node.getNodeName();
nstr = nstr + ">";
}
}
return nstr;
}
/**
* アプリケーション名をセットする
*
* @param app アプリケーション名
*/
public final void setAppName(String app){
AppName = app;
}
/**
* 部屋番号をセットする
* 部屋に入れる人数は無制限
* @param r 部屋番号
*/
public final void setRoomNum(int r){
roomNum = r;
}
/**
* 部屋に入れる最大人数をセットする
*
* @param r 部屋番号
* @param max 部屋に入れる人数の最大値 0なら無制限
*/
public final void setRoomNum(int r, int max){
roomNum = r;
roomMaxP = max;
}
/**
* アプリケーション名をゲットする
*
* @return アプリケーション名の文字列
*/
public final String getAppName(){
return AppName;
}
/**
* 部屋番号をゲットする
*
* @return アプリケーション名の文字列
*/
public final int getRoomNum(){
return roomNum;
}
/**
* 部屋に入れる最大人数をgetする
*
* @return 部屋に入れる最大人数
*/
public final int getRoomMaxP(){
return roomMaxP;
}
}
faces/SyncCounters.java 0100644 0000766 0000766 00000011543 07425146554 015706 0 ustar kitazawa kitazawa package jp.faces;
import java.util.*;
/**
* クライアント同士のタイミング同期のためのカウンタ集合を管理する
*
* @author Jun Kitazawa
* @version 0.1.3
* @see RoomInfo
*/
public class SyncCounters {
private List counters = new Vector();
private FacesServer srv;
public SyncCounters(FacesServer s){
srv = s;
}
/*
* 部屋の全員がQSを送ったかどうかチェック
*
* @param appname アプリケーション名
* @param roomnum 部屋番号
* @param counterName カウンタ名
* @param selfname クライアント固有の番号
*
* @return 全員がQSを送り済ならfalse それ以外はtrue
*
*/
public boolean evalRoom(String appname, int roomnum, String counterName, int selfname){
Iterator itr = counters.iterator();
System.out.println("evalRoom selfname " + selfname);
while(itr.hasNext()){
Counter cntr = (Counter)itr.next();
// すでにその名前のカウンタが存在するならカウンタ値を更新
if(cntr.getCounterName().equals(counterName)){
cntr.qsListAdd(selfname);
if(!cntr.qsAll(appname, roomnum)){
counters.remove(cntr); // 全員からQSを受けているのでのでカウンタ削除
// Sノード送信
return false;
}
else {
return true;
}
}
}
// その名前のカウンタが存在しないなら
if(srv.roomUserCount(appname, roomnum) > 1){ // 2人以上いるならカウンタ設定
Counter newCnt = new Counter(counterName, 0 , srv);
counters.add(newCnt);
newCnt.qsListAdd(selfname);
return true;
}
else { // 1人以下なら即座にSノード送信
return false;
}
}
/*
* 誰かがログアウトした時点で部屋の全員がQSを送ったかどうかチェック
*
* @param appname アプリケーション名
* @param roomnum 部屋番号
*
* @return Sノード送信するカウンタ名リスト
*
*/
public synchronized List evalRoomForDelete(String appname, int roomnum){
List cntlst = new Vector();
Iterator itr = counters.iterator();
while(itr.hasNext()){
try {
Counter cntr = (Counter)itr.next();
if(!cntr.qsAll(appname, roomnum)){
// このカウンタ名はSノード送信
cntlst.add(cntr.getCounterName());
counters.remove(cntr); // 全員からQSを受けているのでのでカウンタ削除
}
} catch(Exception e){
break;
}
}
return cntlst;
}
/**
* カウンタをインクリメント,同名のカウンタが存在していなければ新規に作る
*
* @param counterName カウンタ名
* @param maxCount 待機カウント
* @return カウンタが最大値に達したら false それ以外はtrue
*
*/
public boolean setCounter(String counterName, int maxCount){
Iterator itr = counters.iterator();
while(itr.hasNext()){
Counter cntr = (Counter)itr.next();
// すでにその名前のカウンタが存在するならカウンタ値を更新
if(cntr.getCounterName().equals(counterName)){
cntr.resetMaxCount(maxCount);
if(!cntr.incrementCount()){
counters.remove(cntr); // カウンタがmaxに達したのでカウンタ削除
// Sノード送信
return false;
}
else { // 1人以下なら即座にSノード送信
return true;
}
}
}
// その名前のカウンタが存在しないなら
if(maxCount > 1){ // 2人以上いるならカウンタ設定
counters.add(new Counter(counterName, maxCount, srv));
return true;
}
else {
// Sノード送信
return false;
}
}
}
class Counter {
private String counterName;
private int maxCount;
private int currentCount;
private FacesServer srv;
// Listで qs受けたクライアントのselfnameのリストを持つ
private List qsList = new Vector();
public Counter(String counterName, int maxCount, FacesServer srv){
this.counterName = counterName;
this.maxCount = maxCount;
this.srv = srv;
currentCount = 1;
}
public int getCurrentCount(){
return currentCount;
}
public String getCounterName(){
return counterName;
}
public void qsListAdd(int selfname){
// 既にqs受けたクライアントのselfnameのリストにselfnameがなければ付加
Integer selfnameInt = new Integer(selfname);
System.out.println("selfname " + selfname);
if(!qsList.contains(selfnameInt)){
System.out.println("qsList.add " + selfname);
qsList.add(new Integer(selfname));
}
}
public boolean qsAll(String appname, int roomnum){
boolean check = false;
// appname, roomnumの部屋のメンバー全員がqsListの中に含まれているかどうかチェック
List appfclist = (List)(srv.getClients().get(appname)); // アプリ名が一致して
Iterator itr = appfclist.iterator();
while(itr.hasNext()){
FacesClient fc = (FacesClient)itr.next();
if(roomnum == fc.getClientInfo().getRoomNum()){ // 部屋番号が一致して
Integer si = new Integer(fc.getClientInfo().getNnum());
if(!qsList.contains(si)){
return true; // qsListに含まれていない(ので全員のQSが揃ってない)
}
}
}
return false;
}
public boolean incrementCount(){
if(currentCount >= maxCount - 1){
return false;
}
else {
currentCount++;
return true;
}
}
public void resetMaxCount(int cnt){
maxCount = cnt;
}
}
faces/XmlErrMap.java 0100644 0000766 0000766 00000003170 07425146554 015113 0 ustar kitazawa kitazawa package jp.faces;
import java.util.*;
import java.io.*;
/**
* XML$B%(%i!<%a%C%;!<%8%^%C%W@8@.(B
*
* @author Jun Kitazawa
* @version 0.1.3
*/
public class XmlErrMap {
private String stFile = "Messages_en.properties";
private Properties prop;
private static boolean loaded = false;
/**
* $B%(%i!<%a%C%;!<%8%^%C%W$r@8@.(B
*/
public XmlErrMap(){
loaded = makeMsgMap();
}
/**
* $B%(%i!<%a%C%;!<%8%^%C%W$N@8@.$K@.8y$7$F$$$k$+$I$&$+$rJV$9(B
*
* @return $B%(%i!<%a%C%;!<%8%^%C%W$N@8@.$K@.8y$7$?$+$I$&$+$N??56CM(B
*/
public boolean getLoaded(){
return loaded;
}
/**
* $B%(%i!<%a%C%;!<%8$N%W%m%Q%F%#%U%!%$%k$+$i(BProperties$B%*%V%8%'%/%H@8@.(B
*
* @return Properties$B$,@5>o$K@8@.$G$-$?$+$I$&$+$N??56CM(B
*/
public boolean makeMsgMap() {
try {
if(!loaded){
prop = new Properties();
FileInputStream fin = new FileInputStream(stFile);
prop.load(fin);
fin.close();
loaded = true;
}
return true;
}
catch(Exception e){
//System.out.println("no XML error message map file");
return false;
}
}
/**
* SAXParseException$B$N%(%i!<%3!<%I$+$iBP1~$9$k%(%i!<%a%C%;!<%8$rJV$9(B
*
* @param errCode $B%(%i!<%3!<%I(B
* @return $B%(%i!<%a%C%;!<%8J8;zNs(B
*/
public String getErrMessage(String errCode){
String stLine, stCode;
int nPos;
if((nPos = errCode.indexOf("/")) > 0){
stCode = errCode.substring(nPos + 1).trim();
if((nPos = stCode.indexOf(" ")) > 0)
stCode = stCode.substring(0, nPos);
return (String)prop.getProperty(stCode);
}
else return "";
}
}
faces/jp/ 0040755 0000766 0000766 00000000000 07406047613 013007 5 ustar kitazawa kitazawa faces/jp/faces/ 0040755 0000766 0000766 00000000000 07407607405 014072 5 ustar kitazawa kitazawa faces/jp/faces/CalendarFormat.class 0100644 0000766 0000766 00000003455 07425146705 020010 0 ustar kitazawa kitazawa 朋詐 - u
) =
> ? ( @
> A
B C ( D ( E ( F ( G ( H ( I
J K L
= M
N
O P ( Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g cal Ljava/util/Calendar; year Ljava/lang/String; month day hour minute second weekstr ()V Code LineNumberTable getDateStrFormat ()Ljava/lang/String; getDateTStrFormat
SourceFile CalendarFormat.java 4 5 h i j * + k l m n o , - . - / - 0 - 1 - 2 - p q r java/lang/StringBuffer 0 s t n 9 3 - Sun Mon Tue Wed Thu Fri Sat [ / : ]