yamicha.com's Blog - Presented by yamicha.com
Blog yamicha.com's Blog - 2018/11 の記事
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30]

yamicha.com's Blog
 諸事情により、現在更新休止中。ご了承ください。もし今後ブログを再開することがあるとすれば、その際にはこのブログスクリプトではなく、新しく開発したものによるかもしれません。
 当ブログ管理者についてはこちらをご参照。
開発魔法(737)
社会問題(733)
お知らせ(11)
質問・バトン回答(15)
ゲスト出演(8)
経済・知的財産(150)
ゲーム開発(182)
[Ada] 勝手に補足
- Note
- 金配りの次の一手


- Endless Ultimate Diary
- 銃世界

漢字バトン
- うるる雑記帳
- 漢字接力棒

ツキアイゲノムバトン
- ブログ@うにうに画像倉庫
- あぶ内閣

縺イ縺セ縺、縺カ縺励ヰ繝医Φ
- 月夜のボヤキ
- 騎士サーラバトン
パスワードを使う
名無し (2012/02/27)


開発者解放裁判
yamicha.com (2010/03/14)
Winnyに関しては、私も「純白」とまでは考えておりませんし、使用し..

開発者解放裁判
通りすがり (2010/03/08)
winnyに関しては「ダウンロードソフト板」なんてところを拠点に開発..

新型インフルエンザの恐怖
いげ太 (2009/11/03)
> C#などの「int Some(int , int)」は、F#では「(int * int) ->..

時効に関する思考
yamicha.com (2009/08/31)
>いげ太さんコメントありがとうございます。手元にドキュメントが少..
Homepage
Blog Top
Normal View
List View
Search
Calendar
Comment List
Trackback List
Blog RSS
Send Trackback
Phone Mode
Administrator
yamicha.com
Blog
るううるる。
Source
法令データ提供システム
FindLaw
Development
Java2 Platform SE 6
Java EE 6 API
MySQL Developer Zone
PHP Reference
MSDN Library
Ada Reference Manual
Objective Caml
Python Documentation
Erlang
Prolog Documents
摂氏40.9
2007/08/17(Fri)23:28:08
 すさまじいまでの猛暑が続きますが、皆様いかがお過ごしでしょうか(この文章を冬に読み返すと非常に違和感があるに違いありませんが)。
 8月16日、日本の2箇所で40.9度を記録したとの記事が出ていました。記事中ではその事実にしか触れられていませんでしたが、日本公式最高気温は山形の40.8度と記憶していますので、まさか最高記録更新かと調べてみたところ、やはり2007年8月16日の40.9度は日本公式最高気温となったようです。
 山形の40.8度はフェーン現象によるもので、これは高低差によって熱された乾いた風が発生する現象ですので、これはいわゆる「さわやかな暑さ」であったとされています。それに比べ、昨今の夏の異常な暑さは温暖化によるものとみられ、フェーン現象のような特殊な現象によるものではないため、日本のジメジメ気候とマッチした大変不快なものとなっています。子どもの車中起きざりなどは論外としても、熱中症などには十分注意が必要です。
 さて、これまでの40.8度が40.9度に0.1度だけ更新されたわけですが、大したことではないと言うなかれ、40.8度の記録は1933年に観測されたものです。しかも70年間破られなかったところを見る限り、極めて偶発的なフェーン現象によるものでしょう。こうして作られた例外的な記録が、温暖化とみられる現象によって破られたのは非常に問題です。山形の場合と違い、今後毎年同等の暑さになる可能性があるのです。
 これの何が恐ろしいかといいますと、世界規模では水没や食糧不足がまず挙げられるのでしょうが、日本ではまず「疫病」です。熱帯地方の蚊が日本で生息可能になることが極めて強く危惧されます。熱帯地方特有の病気の中には蚊が媒介するものもあり、これが日本に住み着いた場合、日本で同様の疫病が発生することは避けられません。日本人の多くはこうした感染症に免疫を持たず、重篤な被害をもたらす恐れがあります。
 また、温暖化は生態系を破壊する恐れがあります。暑さに弱い動植物が絶滅する恐れがある他、これまでは日本の気候になじめなかった外来種が幅を利かせ、固有種が追いやられて絶滅することも考えられます。さらに、その固有種を捕食、あるいは共生関係にある動植物も同時に絶滅する危険があり、農作物に被害をもたらしたり病気を媒介する害虫の大量発生も危惧されます。
 温暖化対策の成果は芳しくないようで、今後何らかの転換期が訪れたとしても、それまで温暖化が進むことは避けられません。今後の温暖化の進み具合によっては、新病の治療あるいは予防方法の確立、外来種の水際阻止など様々な対策が必要になると考えられますが、果たして現状の日本政府はどこまでこれに対応できるのでしょうか。

 参院の与野党逆転に伴い、表面でも水面下でも様々な駆け引きがなされているようです。これのおかげで無賃残業合法化や教育バウチャー導入の危機は去りましたので、非常に良いことではあるのですが、マスコミにはかなりとんちんかんな言動も多く見られます。しかし、その中でも読売新聞の理論の巧妙さには舌を巻きました。
 8月16日付の社説なのですが、国政の危機を避けるため、また政策理念を現実の施策として生かすために民主党は大連立を行うべきという内容です。一見まじめな主張に見えますが、実はここがポイントです。
 これまでの読売社説を読んだことのある方ならご存知でしょうが、読売新聞の社説の中には非常に突飛な理論によって無理やり民主党批判を行ったものが多く存在します。批判のための批判とはまさにこのことでしょう。無論、時として民主党が批判されるのが正当なものもありますが、こと読売新聞に関しては理不尽な批判が非常に多いのです。おそらく民主党不支持者の中にも、こうした主張に首をかしげている人は多いでしょう。そういう新聞社が民主党のために進言するようなことがあるでしょうか。
 実際に民主党が大連立を組んだらどうなるでしょうか。自社や自自の例を見るまでもなく、安倍内閣への批判と怒りの受け皿となったはずの民主党の裏切りは多くの支持者を失望させ、その瞬間に民主党は崩壊します。つまり、民主党に大連立を組んでもらいさえすれば、民主党を自滅させることができるのです。読売新聞だけでなく、自民党も水面下でそれを狙っているかもしれません。そうなれば民主党が取るべき道は1つ、大連立案を徹底的に跳ねつけ、与党案と競合する優れた対案によっておつりをつけて返すしかありません。
 もう1つおまけに、読売新聞の上記社説より面白い部分を引用しておきます。

 05年11月に成立した現在のメルケル政権も、第1党CDU・CSUと、第2党SPDとの大連立政権だ。
 メルケル政権は、日本の消費税に当たる付加価値税の16%から19%への引き上げを実現し、増収分の3分の2を財政再建に、3分の1を雇用保険料の引き下げに充てた。また、所得税の最高税率を42%から45%へと引き上げたが、これはSPDの主張を受け入れたものである。
 これにより、財政再建に一定のメドがつき、08年から法人税率の引き下げを実施することになっている。

 なるほど、付加価値税(消費税)を16%から19%に増税し、法人税引き下げですか。それはそれは素晴らしい政策だことで。あまりに素晴らしいので日本では願い下げですね。ちなみに日本の所得税最高税率は40%です。税源移譲によって所得税最高税率は37%から40%になりましたが、住民税は13%から10%に引き下げられています。消費税を上げるのは、法人税及び所得税高税率部分減税を除く減税などによって負担相殺の措置があることを前提として、景気回復後に検討するのも良いでしょう。しかし、法人税を下げるために消費税を上げるようなことが大連立で決定されれば、民主党は確実に死にます。

 とんでもない記事を見かけました。この問題自体は「役所による出生届の扱いに差が生じている」というまじめなものですが、内容がすさまじいです。
 富山県の立山町で「稀星」(きらら)という名前で出生届が出された際、職員は「星はららとは読まない」として届出者である父親に再考を促しました。ところが、富山市で同じ名前を提出したところ「特異でない限り意向を尊重する」として受理されたというのです。
 役所間で出生届の扱いに差があるのは問題です。しかし、それ以前に「稀星」(きらら)とは何たる「DQNネーム」なのでしょうか。富山市曰く「特異でない限り意向を尊重する」とのことですが、これのどの辺りが特異でないのか説明願いたいものです。もし役所間の差をなくすのであれば、再考を促す方を基準にすべきでしょう。
 なお、以前に子どもを「悪魔」と命名した問題がありましたが、裁判では「悪魔と名づけるのは命名権の濫用で違法だが、一旦登録された場合は抹消できない」という判決が出されています(その後高裁に即時抗告されるも、親が違う名前を届け出る)。すなわち、明らかに命名権の範囲を逸脱した奇異な名前は違法とされる可能性があり、最近ちらほら見かけるような珍奇な名前は必ずしも合法とは限りません(しかし、同種の裁判を見かけないことからして、珍奇な名前を受理するかを役所の裁量に任せる形で「黙認」しているのが現実のようです)。
 余談ながら、平易な名前の人は珍奇な名前の人に比べて頭が良い傾向にあるそうです。平易な名前を付ける親権者はまともであり、仮に親権者がまともでない名前をつけようとしたのだとしても、周囲の反対によって思いとどまったのであれば、周囲に歯止めが存在することになり、親も踏みとどまるだけの良識を持っていることになります。すなわち、子どもは良い環境に恵まれているといえます。逆に珍奇な名前をつけられる環境では、親がそのような非常識な名前をつけようとする上、周囲にも歯止めが存在しないわけですから、子どもの周辺環境は悪いといえます。後にはいじめられるリスクも高くなり、不幸な子ども時代を過ごす恐れがあります。こうしたことを考えれば、平易な名前の人の方が頭が良くなる傾向が出るのは当然です。

 なぜ平易でありふれた名前は良く使われるのか。それはその名前が優れているからです。なぜそのような名前は時代を超えて存在するのか。時代を選ばず、安定して優れているからです。なぜ良いソフトウェアやライブラリは頻繁に使われるのか。それらが優れているからです。
 以下のコードは同じ動作を行うものですが、どちらが優れているでしょうか。
// Code.A
void main(){
	printf("Hello");
}

// Code.B
void main(){
	char *str = new char[6];
	str[0] = 'H';
	str[1] = 'e';
	str[2] = 'l';
	str[3] = 'l';
	str[4] = 'o';
	str[5] = '\0';

	for(int i = 0; i < str[i] != '\0'; i++){
		putchar(str[i]);
	}

	delete [] str;
}
 名づけも同じようなものでしょう。
 そんなこんなで、やはり優れたソフトウェアということか、ちまたで多く使われているTomcat。6.0からはCometをサポートしているそうです。普通のServletでもCometと同等の技術を使うことはできますが、Tomcat 6.0のCometを使うとリソースを節約でき、同時接続数などの制限もゆるいとのこと。ここはひとつ、使ってみるとしましょうか。
 まず重要な点として、CometサポートはTomcat独自の実装によって行われています。すなわち、「javax.servlet.*」などといった標準パッケージにAPIが含まれているのではなく、「org.apache...」といった独自のパッケージにAPIが含まれています。当然、これを処理するコンテナ側の実装も独自のものでしょう。一言で表現すれば「移植性がない」ということです。このComet技術を使ったServletをWAR化し、glassfish辺りにそのまま投げ込んだとしても、動作することは期待できません。glassfishなどのJava EEサーバーは内部でTomcatを使っているため、この辺りは微妙なのですが、期待薄でしょう。
 それではとにかく実装を考えるとしましょう。実装方法に関しては、本家ドキュメントのAdvanced I/Oの項目を流し読みしておけば、使い方程度は簡単に理解できるようになっています。このページの記述及びサンプルコードから得られる情報を以下にまとめます。

・Cometを用いるServletは通常通りHttpServletを継承するが、これとは別にCometProcessorをインプリメントする
・CometProcessorはvoid event(CometEvent)メソッドのみを持つ
・CometProcessorを実装したクラスでは、doPostなどのServletクラスのオーバーライドは不要
・CometEventからはHttpServletRequestやHttpServletResponseを得られる
・event()がコールされるのは基本的に接続開始時、データ受信時、エラー時、終了時などに限られ、通常の通信を行うためにはHttpServletResponseなり何なりを保管しておかなければならない
・CometEventをclose()すれば、いつでも接続を終了できる

 後は実装を行いつつ考えるとしましょう。まがりなりにもServletですので、以下のような構成になります。
(*)既存のファイルを変更するもの

/tomcat_directory
 /webapps
  /examples
   /WEB-INF
    /classes
     /com
      /yamicha
       /comet
        Comet.java
        MessageThread.java
        Log.java
    web.xml(*)
   writer.htm
 /conf
  server.xml(*)
 コード自体は「簡易メッセージセンター」の実装なのですが、実際の動作は極めて不安定かつ不定であり、全く実用には耐えません。コードはこれで動かないこともないはずなのですが、なぜ正常に動作しないのかは一切不明です。
// Comet.java
package com.yamicha.comet;

import org.apache.catalina.*;
import java.io.*;
import java.util.List;
import java.util.ArrayList;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.resource.*;
import static org.apache.catalina.CometEvent.EventType.*;

public class Comet extends HttpServlet implements CometProcessor{
	private List<HttpServletResponse> connects;
	private MessageThread mt;

	public void init() throws ServletException{
		connects = new ArrayList<HttpServletResponse>();
		mt = new MessageThread(connects);
		mt.start();
	}
	public void destroy(){
		connects.clear();
		mt.stopThread();
	}
	synchronized public void event(CometEvent e) 
		throws IOException , ServletException{
		e.setTimeout(0);

		HttpServletRequest request = e.getHttpServletRequest();
		HttpServletResponse response = e.getHttpServletResponse();
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");

		switch(e.getEventType()){
		case BEGIN:
			PrintWriter out = response.getWriter();
			if("write".equals(request.getParameter("mode"))){
				mt.addMessage(new Log(
					request.getParameter("name") , 
					request.getParameter("message")));
				response.setContentType(
					"text/plain;charset=UTF-8");
				out.println("データを登録しました。");
				out.flush();
				out.close();
				e.close();
			}else{
				response.setContentType(
					"text/plain;charset=UTF-8");
				synchronized(mt){
					mt.writeMessages(response);
					connects.add(response);
				}
			}
			break;
		case READ:
			break;
		case END:
			synchronized(mt){
				connects.remove(response);
			}
			e.close();
			break;
		case ERROR:
			e.close();
			break;
		}
	}
}

// MessageThread.java
package com.yamicha.comet;

import java.util.List;
import java.util.ArrayList;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class MessageThread extends Thread{
	private List<Log> logs;
	private List<HttpServletResponse> connects;
	private boolean loop;
	private boolean update;

	public MessageThread(List<HttpServletResponse> c){
		connects = c;
		loop = false;
		update = false;
		logs = new ArrayList<Log>();
	}

	public List<Log> getLogs(){
		return logs;
	}
	public void addMessage(Log log){
		synchronized(this){
			logs.add(0 , log);
			update = true;
			notify();
		}
	}
	public void clearMessage(){
		synchronized(this){
			logs.clear();
		}
	}

	public void run(){
		loop = true;

		synchronized(this){
			while(loop){
				update = false;

				try{
					wait();
				}catch(InterruptedException e){
				}

				if(!update || !loop)
					continue;

				for(HttpServletResponse response : connects){
					try{
						PrintWriter out = 
							response.getWriter();
						out.println(logs.get(0).
							getFormatMessage());
						out.flush();
					}catch(IOException e){
					}
				}
			}
		}
	}
	public void writeMessages(HttpServletResponse response){
		synchronized(this){
			try{
				PrintWriter out = response.getWriter();
				for(Log log : logs){
					out.println(
						log.getFormatMessage());
				}
				out.flush();
			}catch(IOException e){
			}
		}
	}
	public void stopThread(){
		loop = false;
		synchronized(this){
			notify();
		}
	}
}

// Log.java
package com.yamicha.comet;

import java.util.List;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Date;
import java.util.Calendar;

public class Log{
	private String name;
	private String message;
	private Date date;

	public Log(){
		date = new Date();
	}
	public Log(String n , String m){
		this();
		name = n;
		message = m;
	}
	public Log(String n , String m , Date d){
		this(n , m);
		date = d;
	}

	public String getName(){
		return name;
	}
	public String getMessage(){
		return message;
	}
	public Date getDate(){
		return date;
	}

	public void setName(String n){
		name = n;
	}
	public void setMessage(String m){
		message = m;
	}
	public void setDate(Date d){
		date = d;
	}

	public String getFormatMessage(){
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(date.getTime());

		String dmsg = String.valueOf(c.get(Calendar.MONTH) + 1) + 
			"/" + c.get(Calendar.DATE) + " " +
			c.get(Calendar.HOUR_OF_DAY) + ":" + 
			c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND);

		String msg = name + " : " + message + 
			"(" + dmsg + ")";
		return msg;
	}
}
 なぜevent()メソッドにsynchronizedをかけているかといいますと、event()が呼ばれた時点ではCometEvent及びそこから取得したHttpServletResponse、PrintWriterなどはマルチスレッドに対して安全ではないとのこと。実際、他のクライアントに向けているとみられる出力がなされる現象にもたびたび遭遇していますので、ロックを行わなければ本来出力されるべきでない相手に対して出力が行われてしまうことがあるようです。しかし、synchronizedを指定することである程度回避できるようには見受けられますが、やはり発生してしまいます。これではとても実用できません。
 後はwriter.htmでメッセージの書き込みフォームを提供し、web.xmlに記述するだけです。ポートは8090であるものとします。
// writer.htm
<html>
<head>
<title>Comet Writer</title>
</head>

<form method="POST" 
action="http://localhost:8090/examples/servlet/Comet">
<input type="hidden" name="mode" value="write">
名前<input type="text" name="name" 
size="20" value="default"><br>
発言<input type="text" name="message" 
size="60" value="default"><br>
<input type="submit" value="送信">
</form>
</body>
</html>

// web.xml(編集) - 次のようにクラスとマッピングを追加
<servlet>
	<servlet-name>Comet</servlet-name>
	<servlet-class>com.yamicha.comet.Comet</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>Comet</servlet-name>
	<url-pattern>/servlet/Comet/*</url-pattern>
</servlet-mapping>
 これで一応は完成です。コンパイルの際にはorg.apache.catalinaのパッケージがなければエラーとなりますので、クラスパスに「tomcat_directory\lib\catalina.jar」を含めるようにしましょう。必要に応じてTomcatを再起動すれば、これでServletの実行が可能になります。
 ところが、実際にURLにアクセスすると405エラーが発生してしまうのです。writer.htmのフォームを使用することはおろか、普通にアクセスしても弾かれてしまいます。POSTやGETメソッドには対応していないとか。
 これを有効にするためには、server.xmlを編集しなければなりません。
/* server.xml(編集)
<Service name="Catalina">
このノード内に以下のタグを記述する
*/

<Connector port="8090" 
	protocol="org.apache.coyote.http11.Http11NioProtocol" 
	connectionTimeout="20000" 
	redirectPort="8443" />
 もともとのポート8080を残しておくために8090を新しいポートとして割り当てていますが、実際のところ上記プロトコル(org.apache.coyote.http11.Http11NioProtocol)でもdoPostやdoGetを使った従来のServletを処理できるようですので、ポート8080のprotocolアトリビュートを直接書き換えてしまっても良いかもしれません。ただし、トラブルが発生しても責任は負いかねます。
 これでようやくプログラムを動作させることができるようになりました。ただ、servlet/Cometにアクセスした際、通常のCometならwriter.htmから適当なデータを送るたびにデータが更新されていくはずなのですが、それが実際に動作したり、かといえば突然動作しなくなったり、途中で勝手に読み込み完了してしまったり、かなり意味不明な動作をします。Tomcatのバグか、私が何か書き間違えているのか、もしくは他に何らかの原因があるのかは分かりません。
 これでは実用には遠いですが、Comet自体は面白いのではないでしょうか。そのうち似たようなAPIがServlet標準APIに導入される可能性もありますし、検証の価値はありそうです。しかし、どうせならアノテーションを使ったAPIにした方が使いやすかったのでは。@CometMethodをメソッドにつけてみたり、@CometResponseListでHttpServletResponseのリストを管理できるようにしてみたり。仮に標準APIが作られたら、実際にそのようなモデルになるかもしれません。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]
<- 前の記事を参照 次の記事を参照 ->

- Blog by yamicha.com -