ハマリ(´ω`)

2007年02月16日

AJP連携時のTomcatのServerPortの設定

Apache−Tomcatの連係をしていて、Tomcat側のRequest.getServerPort() メソッドを使うとApacheが受けたポート番号が帰ってきます。

#AJPは、標準だと8009で受けているはずなのに。

これは、ApacheがAPJプロトコルの中でProxyPortとして80をTomcatに教えてあげているからです。

なるほど。

 

この動作は、Apacheが直接リクエストを受けてTomcatに転送している場合は、いい感じに動くのですが、いったんProxyを経由したりしていると、うまく動かない場合が出てきます。

例えば、Apache内部でVirtualHostを8001で立てて、そこにRedirectしてからTomcatと連携したりすると getServerPort() メソッドは8001を返してしまいます。

これに対しては、Tomcatのserver.xml のAJP Connector の設定でProxyPortを指定してあげることでうまいこと回避可能です。

例えばこんなん。
<Connector enableLookups="false" port="8009" protocol="AJP/1.3" redirectPort="8443" proxyPort="80" />

これなら、AJPで受けたリクエストのgetServerPort() は常に80 を返します。
やった!解決!

 

別のやり方として、HttpServletRequestWrapper を継承したクラスを作って、getServerPort の戻り値の偽装も考えたのですが、こっちのほうはうまくいきませんでした。

Tomcatが初期に作成するResponseオブジェクトは、内部変数でRequestオブジェクトを保持してしまっており、用意したRequestWrapperを使ってくれないのです。

#これは、たとえば response.sendRedirect( ) を相対パスで実行しようとすると問題になります。
#Tomcatは、Redirect先のパスを絶対パスに書き換えてからクライアントに戻すのですが、この相対パスから絶対パスへの変換の際に、上記の理由でオリジナルのRequestが持っている getServerPort が使われるので、RequestWrapperを使った偽装が適用されないわけです。

また、jsessionid の自動付加でも問題が起きそうです。

jsessionid を付けるか付けないかの判断でも、指定したURLを一旦絶対パスに置き換えてから、ServerName, ServerPort 等が一致することを確認しているからです。
#これもハマって、Tomcatのソースを追う羽目に・・・orz

 

なんかまぁ、いろんなハマりがあるなぁ。。。



t100life at 15:15|PermalinkComments(0)TrackBack(0)clip!

2007年02月07日

PCサイトを携帯サイトに変換する

Javaで作った今時のリッチなエディタ付きPCブログサイトで作った文字装飾入りまくりのブログ記事を携帯で表示したい。
とか突然言われたら、どうしたら良いだろうか・・・

携帯は要領制限があるせいで、ブログ記事の改ページはまぬがれない。
といって、単純にサイズでカットしてしまっては、タグが切れたり、開始タグと閉じタグがページをまたいだりしても泣きそう。
他にも、携帯だと使えないタグや属性を同種のタグに置き換えたりとかで、もうどうしたらいいねん。


で、探してみたらありました!PCサイトを携帯サイトに変換してくれるオープンソースのライブラリが!

http://phpspot.org/blog/archives/2006/12/pc.html



PHPですが・・・・orz

ぐあー!!Javaで誰か作ってないのかっ?!


あ、、あるいは、PHPのコードをJavaに変換するとかっ!!








・・・・自力でやるしかないのだろうか・・・(´Д⊂ヽ


t100life at 02:02|PermalinkComments(0)TrackBack(0)clip!

2007年01月30日

Apache内のCGI環境変数をTomcatに渡す。

Apache内のCGI環境変数をTomcatに渡す。


Apache+Tomcatの環境で開発してるんですが
全般的に rewrite.conf を使ってURLの書き換えを行っているため
Tomcatからは、ユーザーが入力したURLが見れなくなっていて
そのことが問題になるケースに遭遇してしまいました。

ということで、この時の解決方法を記録しときます。
知ってれば大したことじゃないんだとは思いますが、、、
自分は知らなくて、数日ハマったので・・・orz


ちなみに本件は、apache2.2 + Tomcat 5.5 + mod_proxy_ajp を使ってます。


対応としては、一旦 mod_rewriteを使って、環境変数(偽)を、本当の(?)環境変数として登録してから、mod_headersを使って、本物の環境変数の値をRequestHeader に書き出すというものです。

以下は、QUERY_STRINGの値をORG_QUERY_STRING としてTomcat に転送する例です。
(ヘッダーのキー名は適当です。)

RewriteEngine On

RewriteRule ^(/.*)$ $1 [env=ORG_QUERY_STRING:%{QUERY_STRING}]
RequestHeader append "x-meke-original-query_string" %{ORG_QUERY_STRING}e

 

mod_rewrite のリファレンスを見ると%{変数名}という記述で、各種情報にアクセス可能っぽく見えるのですが、このうちの幾つかはmod_rewrite でしか使えない定数だったりします。(ヒドス)
http://blog.dawgsdk.org/weblog/archives/411011


そのため、以下のように書いても値をとることができません。

RequestHeader append "x-meke-original-query_string" %{QUERY_STRING}e

ちなみに mod_rewrite は、どうやって処理しているのかというと、、、mod_rewrite.c の1955行目あたりをみると、、、

if (!strcmp(var, "QUERY_STRING")) {
    result = r->args;
}


直接リクエスト構造体(?)から、値を返してるっ!!Σ(゜д゜|||)

たいていのモジュールは、%{変数名} の値の解決を、apr_table_getという関数のみで行っています。
これは、Apache内部の環境変数を保存するテーブルにアクセスする関数なんですが、初期状態では、このテーブルに値が入ってないのでイマイチ使えません。。。

mod_rewrite は%{変数名}の解決で、上記のテーブル以外の内部の値も使えるように拡張されているため、非常に強力になっています。

そして、mod_rewriteのenvオプションを使えば、apr_table_setn 関数を使って上記の環境変数のテーブルへ登録を行えるので、この処理の後であれば他のモジュールからも値が利用可能になるというカラクリです。

 

ていうか、Apache内の変数の名称が、「環境変数」っていうのは、検索の際にややこしすぎ、、、、orz



t100life at 17:14|PermalinkComments(0)TrackBack(0)clip!

2007年01月28日

Solarisがインターネットに繋がるまで

Solarisでインターネットにつながるまで

社内のSolarisサーバーをインターネットにつなげるまでの手順をメモっとこ。
すぐ忘れちゃうので・・・(´ω`)

  • 名前解決の方法を指定
    名前解決にDNSを使うように設定するっぽいです。

    /etc/nsswitch.conf ファイルの hosts: の項目に、DNSを設定

    hosts: files dns
  • DNSサーバーのアドレスを指定
    /etc/resolve.conf ファイルにDNSサーバーのアドレスを指定(ファイルがない場合は新規作成)

    nameserver 192.168.0.1

    ※domainを指定すると、ホスト名の検索の際にドメイン名を省略できるんだとか。社内LANの場合に有効か?
  • デフォルトルーターの設定
    routeコマンドを使って設定してみる。

    #route add default 192.168.0.1

    で、再起動しても設定が有効になるように、以下のファイルも作成。

    /etc/defaultrouter にデフォルトルーターのIPアドレスを記述

    ※この部分は以下のサイトを参考にさせてもらいました。
    http://akionweb.com/archives/2005/04/solaris.shtml


こんだけ書く間に、BackSpaceキーで前のページに戻る事故で、2回も記事が消えた…
これだからWebアプリは嫌いだーーヽ(`Д´)ノうわぁぁぁぁん



t100life at 22:00|PermalinkComments(0)TrackBack(0)clip!

2007年01月23日

IFrame内のサイトにログインできない。

ハマり中のメモです。解決してません。

そもそもの発端は、世の中に山ほどソーシャルブックマークサイトがあって、そのうちの何個かにはアカウントを作ってるんだけれども、個別にブックマークを登録するのが面倒なので、マルチポストするスクリプトを作ってみよう。

と、思ったことでした。

動作方法としては、こんな感じを考えてました。

  1. スクリプトレットを使って、マルチポストするページにアクセス。
  2. その際に、元のページのURLやタイトルを#の後ろに貼り付けておく。
  3. マルチポストのページ内で、JavaScriptで#以降の値を取り出して解析。
  4. ページ内には、IFrameを複数個配置しておき、JavaScriptで解析した値から、各ソーシャルブックマークの登録の為のURLを組み立てて、IFrameのソースにセット。
  5. そしたら、IFrame内にバババ!!っと各サイトが開いて、あとはタグいれて登録をポチポチオスだけ!!

のはずが、5が動かない…(;´д⊂)

バババ!!っとページは開くんですが、どれも各サイトのログイン画面…

そして、何回ログインしてもログインできないっ・・・
ページと異なるドメインのサイトをIFrameに開いたら、クッキーが作れないとか、そんな制約があるのかなー・・・

誰か教えて〜〜ヽ(;´Д`)ノ

 

↓失敗したHTMLのコード

<html>
<head>
<title>マルチポストのページ</title>
</head>
<body>


<DIV>
はてな
<iframe id="hatenaFrame" width="100%">
</iframe>
</DIV>

<DIV>
ライブドア
<iframe id="livedoorFrame" width="100%">
</iframe>
</DIV>

<script>
//  alert(location.hash);
 
  var paramStr = location.hash;
  paramStr = paramStr.substr(1, paramStr.length);
  paramStr = paramStr.replace(/&/g, '","');
  paramStr = paramStr.replace(/=/g,'":"');
  paramStr = 'var param = {"' + paramStr + '"}';

//  alert(paramStr);
  eval(paramStr);

  if(paramStr.length == 0){
  }else{

//  alert(param.href);
//  alert(param.title);

  var targethref = param.href;
  var targettitle = param.title;

  var hatenaUrl = 'http://b.hatena.ne.jp/add?mode=confirm&title='+targettitle+'&url='+targethref;
  document.getElementById('hatenaFrame').src = hatenaUrl;

  var livedoorUrl = 'http://clip.livedoor.com/clip/add?link='+targethref+'&title='+targettitle;
  document.getElementById('livedoorFrame').src = livedoorUrl;
  }
</script>


</body>
</html>



t100life at 22:25|PermalinkComments(0)TrackBack(0)clip!

2007年01月19日

JavaのMainスレッドが終わってもプログラムが終わらない場合があるよ。

JavaのMainスレッド(JavaVMから起動される最初のスレッド)が終わってしまったら、プログラムが終わるんじゃないか?というネタがあったので検証してみました。

意外と、終わらないのですね。これが。

public class ThreadTest {
 
  public static final void main(String args[]) throws Exception{
  
    Thread t = new Thread(new Runnable(){
     public void run(){
      for(int i = 0; i < 10; i++){
       System.out.println("表示するよ。" + i);
        synchronized(this){
         try {
          wait(1000);
         } catch (InterruptedException e) {
          e.printStackTrace();
         }
        }
       }
      }
     });
  
    //↓この行を有効にすると、メインが終わるとプログラムも終わってまう。
    //t.setDaemon(true);
    t.start();
  
    System.out.println("メイン終わるよ。");
   }
 }

コードが見づらくてすんません・・・

Mainスレッドが終わっても、他に動いてるスレッドがあったらプログラムの終了を待機してくれるっぽい。

ただ、スレッドの setDeamon に true をセットすると、上記の待機処理の対象外にすることが出来ます。

 

それにしても、プログラム内でスレッドをWait させるために、Synchronized(This)してる箇所が、よく考えると分かってない気が。

「スレッドのモニターを取得する」っていうのが、分かるようなわからんような。

いや、あれかな。
スレッド間での、インスタンスの参照権がモニターかな??

でもインスタンスの参照って、シンクロナイズドブロックの外でも自由にアクセスできるよねぇ。

ということは、一方でSynchronizedでブロックしてても、他方でSynchronizedされてないブロックがあったら値が破壊される気も。

これも検証してみなくては、、、

 

(つづく)



t100life at 12:42|PermalinkComments(0)TrackBack(0)clip!

2007年01月17日

Windowsのショートカットがシンボリックリンク的に使えた

今更なんですが、Meadow3を入れてEmacsの練習をしているとファイルを開くだとか、保存だとかでWindowsのディレクトリ構成が参っちゃうわけです。

長いし、間にスペース入ってるし。

でも出来ればファイルは全部、マイドキュメントに固めておきたい。
#バックアップの時とか楽だし。

マイドキュメントのフォルダを移動するという方法もあるんですが、これもこれで、完全に移動できるわけではないので、何かと不便なんですよねぇ。
#ソフトによっては、移動前のディレクトリを相変わらず見たりするし。

と思ってたら、エクスプローラーでショートカットを作ると、シンボリックリンクみたいに使えることが判明。

例えば、C:\Document And Settings\t100\My Documents とかいう泣きそうなフォルダへのショートカットを、t100 という名前でC:\の直下に作っておくと、Meadowの補完でも c:\t100 でマイドキュメントにアクセスできます。

便利!!

上記の補完はDOSでも使えました。

ちなみに Windows Vista では、プロファイル関係のフォルダは C:\Users\[userId] 以下にパスが変わるんですが、Document And Settings は、シンボリックリンクとして残るんだとか。

Windows Vistaにはシンボリックリンクがいっぱい
CreateSymbolicLink とかいうAPIも増えるらしい・・・

 



t100life at 16:36|PermalinkComments(0)TrackBack(0)clip!

2007年01月16日

javaScript OOP講座はここを嫁!

http://d.hatena.ne.jp/amachang/20060316/1142508449

素晴らしい解説。

ていうか、prototype.js 普通に眺めても全然分からなかったわけですが...orz



これ勉強会の資料かー。やるなー。


t100life at 01:13|PermalinkComments(1)TrackBack(0)clip!

2007年01月15日

MacOS X 10.4 だとcronは使わないらしい

インスコしたPostgreSQLがストップ出来なくて困ってる訳です、、、
pg_ctl stop しても、failed で失敗するわけですが、、、むおお・・・


ということで、停止出来ないんだったら初期起動しないように止めてやれっ

と思って調べたら、どこで起動してるかわからねぇぇぇ!
/etc/rc にも何も書いてないし、crontab にも何のエントリも無いっ
(まぁcronは初期起動とは関係ないけど)


で、調べてみたらMacの初期起動の仕組みって全然違うことが発覚。
ついでに、cronも10.4 から使わなくなったんだとか。

まぢかっ!

調べた感じでは以下でした。
#というか、MacOS X ターミナルコマンド ポケットリファレンスのままです。詳しくは本を参照してください。


Mac OS X では、サービスを起動する仕組みは、SystemStarter と launchd の2種類が提供されている。
rc スクリプトもあるけど、基本は上記2つ。
(launchdはTigerで追加されたんだとか)

ちなみに、cron 相当の機能は、launchd 経由でperiodic コマンドでスケジューリングして使うそうな。
詳しいことは、またの機会に確認じゃな、、、

SystemStarter が起動するスクリプトは、/System/Library/StartupItems と、/Library/StartupItems の下に。
launchd が起動するスクリプトは、/System/Library/LaunchDeamons と、/Library/LaunchDeamons の下に。

どちらも、/System/Library の下のがシステム標準で、/Libraryの下のがローカルホスト共通で使い分けだそうです。


ということで、調べてみると・・・

あった!ありました!/Library/LaunchDeamons の下に、org.magic3.postgrex.plist がっ!!


そういう仕組みか〜。ということは、launchd で止めたらいいわけやねー。
回りくどいしくみやなー。ビックリさせおってからに・・・
ポチっとな〜

> sudo launchctl stop org.postgresql.postmaster

・・・・・


postmaster 止まらないYO!!ヽ(`Д´)ノウワァァァン


(つづく)



t100life at 23:51|PermalinkComments(0)TrackBack(0)clip!

2007年01月11日

DarwinPorts をProxy 環境下で使う

調べたらサクっと出てきますた。
http://forums.macosxhints.com/archive/index.php/t-50478.html

  1. 環境変数 http_proxy にプロキシサーバーの情報をセット
  2. で、普段どおり Ports を実行

ということみたいです。

> http_proxy="http://10.1.1.15:8080/";
> export http_proxy;

と実行後に、Ports実行で大成功!ヽ(´―`)ノ

> ports install ~~

いやっぴょい♪



t100life at 12:10|PermalinkComments(0)TrackBack(0)clip!