Google Chrome OSを入れてみた

,
[Download]
こちらのサイトからVMの仮想ディスクイメージをダウンロードします.
(DLにはユーザ登録が必要)
http://gdgt.com/google/chrome-os/download/

[Install]
VM PlayerやVM WorkStationで実行します.
vmdkからの展開となるので,少し厄介.
インストールには,下記ページを参照してください.
http://www.forest.impress.co.jp/docs/special/20091120_330552.html

[Screen shot]

・OSが立ち上がった直後のログイン画面.
ここのログインにはGmailのアカウントが必要となります.
また,ネットワークに接続されている必要があります.





・このページを見たところ.
右上にメニューがあります.




 ・メモリーの使用量
26Mbyteほどで動作しているみたいです.
ちなみにOSの最小動作メモリは32Mbyteとなっています.





・ダウンロードしたファイルも,ブラウザ上からアクセスします.




・バージョン情報




まだまだ,実用レベルには達していないと思いますが,今後の開発には注目していきたいです.
[追記]
proxy環境下ではログインすらできないのかな??

reacTIVisionを使ってみた2(volume controller)

,
こんなのを作ってみました。



二つのマーカーを使っていて、
ひとつはボリューム調節用コントローラとして
もうひとつは、写真を表示するためのXY座標を決定するために使用しています。

ボリューム調節用コントローラは時計回転すると(見にくいんですけど)マーカーの下に黒色のゲージがたまっていきます。
逆回転すると下がります。

そして、ボリューム調節用コントローラのボリューム値によって写真を拡大・縮小しています。

reacTIVisionを使ってみた

,
reacTIVision
は,タンジブルユーザインターフェースやフィンガートラッキングを実現するためのオープンソースなフレームワークです.




昨日,研究室の先輩に教えていただき,とりあえずサンプルプログラムをいじって,簡単なプログラムを書いてみた.

どういうことをしているかって言うと,壁の手前にプロジェクターとカメラを用意しています.

壁にマーカーを貼り付けることにより,マーカーの座標を取得し,その座標を基に,描画を行いプロジェクターから出力しています.

とりあえず,作ってみたのは,

二つのマーカーを使用した音楽再生プログラム.
一つのマーカーは音楽プレーヤを表していて,処理として「Play」と「Stop」を持ちます.

もうひとつのマーカーは音楽プレーヤをコントロールするためのマーカーです.
音楽プレーヤマーカーの近くに表示されているPlayとStopの近くにこのコントロールマーカーを持っていくことで,音楽を再生したり止めたりすることができます.

画像認識,処理などの知識なんて全くって言っていい程ないけど,reacTIVisionを使うと簡単にプログラムを書けます.

Google Guiceを使ってみた

,
Google Guice はオープンソースの Java™ 開発用DI (Dependency Injection: 依存性注入)フレームワークです.

DIとは依存性の注入のことで,同じインターフェースを持つ具象クラスを,設定によって入れ替え可能にする方法を指します.このことにより,プログラムの挙動を動的に変更することができます.

[download]
http://code.google.com/p/google-guice/downloads/list

[Main.java]
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;

public class Main {
 public static void main(String[] args) {
  Injector injector = Guice.createInjector(new AbstractModule() {
   @Override
   protected void configure() {
    bind( String.class ).toInstance( "まつたけ" );
    bind( int.class ).toInstance( 5000 );
   }
  });
  injector.getInstance(Item.class).view();
 }
}

[Item.java]
import com.google.inject.Inject;

public class Item {
 @Inject
 private String name;
 @Inject
 private int price;
 
 public void view() {
  System.out.println("商品名" + " : " + name);
  System.out.println("値段" + " : " + price);
 }
}

上記のプログラムでは,次の2行でItemクラスのフィールドに対して値を代入しています.
bind( String.class ).toInstance( "まつたけ" );
bind( int.class ).toInstance( 5000 );

ここでは,Itemクラスのフィールドの型が別なので,自動的にString型がnameへintがpriceに代入されています.

ここで,Itemクラスに商品番号を表すint idというフィールドがあった時,どちらを代入すればよいのかわからないため,例外が飛びます.
bind( int.class ).toInstance( 5000 ); // price?
bind( int.class ).toInstance( 1 );  // id?

そのとうな場合には,下記のようにアノテーションで名前をつけることにより,解決できます.

[Main.java]
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;

public class Main {
 public static void main(String[] args) {
  Injector injector = Guice.createInjector(new AbstractModule() {
   @Override
   protected void configure() {
    bind( String.class ).annotatedWith(Names.named( "name" )).toInstance( "まつたけ" );
    bind( int.class ).annotatedWith(Names.named( "price" )).toInstance( 5000 );
    bind( int.class ).annotatedWith(Names.named( "id" )).toInstance( 1 );
   }
  });
  injector.getInstance(Item.class).view();
 }
}

[Item.java]
import com.google.inject.Inject;
import com.google.inject.name.Named;

public class Item {
 @Inject
 @Named("name")
 private String name;
 @Inject
 @Named("price")
 private int price;
 @Inject
 @Named("id")
 private int id;
 
 public void view() {
  System.out.println("商品名" + " : " + name);
  System.out.println("値段" + " : " + price);
  System.out.println("ID" + " " + id);
 }
}


参考:
Guice による依存性注入(IBM Developerworks)
http://www.ibm.com/developerworks/jp/java/library/j-guice.html

GoogleからリリースされたDIフレームワーク(gihyo.jp)
http://gihyo.jp/dev/serial/01/awdp/000101


GoogleのDIフレームワーク"Guice"を使ってみる(マイコミジャーナル)
http://journal.mycom.co.jp/articles/2007/03/14/googleguice/001.html

AutoHotKeyを使ってみた

,
AutoHotkeyはアプリケーション毎のホットキーの割り当てや,キーカスタマイズ,スクリプトによるOS/アプリケーションのコントロール等ができるツールです.

簡単に言うと,自由自在に操作できる高機能なスクリプト実行環境です.

詳しい使い方は,
AutoHotkeyを流行らせるページ
に書いてあるので,見て下さい.


いくつかスクリプトを書いたので,メモします
■Alt+Tabの動作変更
通常,Alt+TabでWindows標準のウィンドウ切り替えが起動しますが,インクリメンタルサーチで絞り込めるウィンドウ切り替えソフトウェア「CLTC」に変更します.
!Tab::Run "C:\MyPrograms\cltc\cltc.exe"



■起動orアクティブ
関数を定義し,プログラムが起動していなかったら起動し,起動している場合には,アクティブ(トップに表示すること)にします.
ここでは,Alt+aで便利な2画面ファイラー「あふ」を,Alt+cで,ユーザデスクトップ上で,コマンドプロンプトを起動します.その他にもいくつか割り当ててますが,省略します.
Launch(class, path)
{
IfWinNotExist ahk_class %class%
Run, %path%
else
WinActivate, ahk_class %class% 
return
}
Launch_Param(class, path, param)
{
IfWinNotExist ahk_class %class%
Run, %path%, %param%
else
WinActivate, ahk_class %class%
return
}
!a::Launch("TAfxForm", "C:\MyPrograms\afx11\AFX.EXE")
!c::Launch_Param("ConsoleWindowClass", "cmd.exe", "C:\Users\*****\desktop")



■F10でアクティブなウィンドウを半透明にする
こんな感じ


F10::
WinGet, t, Transparent, A
if %t%
WinSet, Transparent, Off, A
else
WinSet, Transparent, 160, A
return



■Ctrl+F10で上記を全てのウィンドウに
^F10::
WinGet, id, list, , , Program Manager
Loop, %id%
{
StringTrimRight, this_id, id%a_index%, 0
WinGet, t, Transparent, ahk_id %this_id%
if %t%
WinSet, Transparent, Off, ahk_id %this_id% 
else
WinSet, Transparent, 160, ahk_id %this_id% 
}
return




■F11でアクティブなウィンドウを最大化
F11::
WinGet, State, MinMax, A
if State != 0
WinRestore, A
else
WinMaximize, A
return



■Ctrl+F11でアクティブなウィンドウを最小化
^F11::
WinGet, State, MinMax, A
if State != 0
WinRestore, A
else
WinMinimize, A
return



■Win+カーソルでウィンドウの移動
Ctrlも一緒に押すと移動量が少なくなります
WinMoveStep(XD,YD,PARAM) {
WinGet,win_id,ID,A
WinGetPos,x,y,,,ahk_id %win_id%
Step := 128
if(PARAM = 1)
Step := 24
x := x + (XD * Step)
y := y + (YD * Step)
WinMove,ahk_id %win_id%,,%x%,%y%
return
}
#Left::WinMoveStep(-1,0,0)
#Right::WinMoveStep(1,0,0)
#Up::WinMoveStep(0,-1,0)
#Down::WinMoveStep(0,1,0)
#^Left::WinMoveStep(-1,0,1)
#^Right::WinMoveStep(1,0,1)
#^Up::WinMoveStep(0,-1,1)
#^Down::WinMoveStep(0,1,1)



■Win+Shift+カーソルでウィンドウサイズを変更
Ctrlも一緒に押すと移動量が少なくなります
WinSizeStep(XD,YD,PARAM) {
WinGet,win_id,ID,A
WinGetPos,,,w,h,ahk_id %win_id%
Step := 128
if(PARAM = 1)
Step := 24
w := w + (XD * Step)
h := h + (YD * Step)
WinMove,ahk_id %win_id%,,,,%w%,%h%
return
}
+#Left::WinSizeStep(-1,0,0)
+#Right::WinSizeStep(1,0,0)
+#Up::WinSizeStep(0,-1,0)
+#Down::WinSizeStep(0,1,0)
+#^Left::WinSizeStep(-1,0,1)
+#^Right::WinSizeStep(1,0,1)
+#^Up::WinSizeStep(0,-1,1)
+#^Down::WinSizeStep(0,1,1)



■Shift+SpaceでIME ON-OFF切り替え
+Space::Send, {vkF3sc029}



■単独のWinキーのみでスタートメニューを表示しない
※誤動作防止のため
RWin::return
RWin & RWin::return
LWin::return
LWin & LWin::return



■コマンドプロンプト
コマンドプロンプト上でもクリップボードの内容を貼り付けるのに,Ctrl+vを使えるようにする.また,終了はCtrl+w,全て選択はCtrl+a等

#IfWinActive ahk_class ConsoleWindowClass
^v::Send,!{Space}ep     ; ^V ペースト
^w::Send,!{Space}c      ; ^W 終了
^f::Send,!{Space}ef     ; ^F 検索
^a::Send,!{Space}es     ; ^A 全て選択
^k::Send,!{Space}ek     ; ^K 選択
#IfWinActive





AutoHotkeyを流行らせるページに行くと便利なサンプルプログラムがあります.
中でもホイールリダイレクトは便利!

Linuxコマンド

,
-----------------------------
find
-----------------------------
⇒ /foo/bar 以下の全ファイル一覧を表示
find /foo/bar -type f
⇒ /foo/bar 以下の全ディレクトリ一覧を表示
find /foo/bar -type d
⇒ 特定のファイル名を検索
find . -name "*.conf"
⇒ 4日以内にアクセスされたファイル
find . -atime -4
⇒ 4日以内に修正されたファイル
find . -mtime -4
⇒ 10分以内に修正されたhtmlファイルを検索
find . -mmin -10 -exec grep *.html {} \;
⇒ /var/以下で"成功"という文字列を持つhtmlファイルを検索する
find /var/ -name \*.html -print0 | xargs -0 grep 成功 /dev/null

-----------------------------
iptables
-----------------------------
⇒ 状態の確認
iptables -L
⇒ ポリシーの設定
iptables -P INPUT ACCEPT
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
⇒ ルールの削除
iptables -F
⇒ icmp(ping)からの入力を許可
iptables -A INPUT -p icmp -j ACCEPT
⇒ 自端末からの入力を許可
iptables -A INPUT -i lo -j ACCEPT
⇒ Web,SSHからの入力を許可
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
⇒ 他の接続はすべて破棄(ポリシーの再設定)
iptables -P INPUT DROP
⇒ ルールをセーブする
/etc/init.d/iptables save
⇒ 再起動
networking restart


-----------------------------
netstat ネットワーク関連の統計情報を表示する
-----------------------------
⇒ 全てのサービスを表示(-t:tcp,-u:udp)
netstat -a

-----------------------------
arp システムのARPキャッシュを操作する
-----------------------------
⇒ 指定したホストに対しての情報を表示する
arp -a [ホスト名]
⇒ 指定したホストに対しての情報を削除する
arp -d [ホスト名]

-----------------------------
route ルーティング・テーブルを表示・設定する
-----------------------------
⇒ ルーティングを追加する 消す場合はaddをdelete
route add -net [192.168.1.0] netmask 255.255.255.0 eth0
⇒ デフォルト・ゲートウェエイを指定する
route add default gw [192.168.0.1]


-----------------------------
at
-----------------------------
⇒ 15時20分にjob.sh内のコマンドを実行します
at -f job.sh 15:20
⇒ 実行されていないジョブを表示する
at -l
⇒ ジョブを削除
at -d [ジョブ番号]


-----------------------------
other
-----------------------------
⇒ バージョンの確認
lsb_release -a
⇒ Apacheデーモン起動
/etc/rc.d/init.d/httpd start
⇒ ログファイルの最後の5行をずっと監視する
tail -n 5 -f [ファイル名]
⇒ 現在の日付と時刻を表示する
date
⇒ 時刻を合わせる
ntpdate ntp.nict.jp
⇒ 実行するコマンドにのみ環境変数を一時的に設定
env 変数名=設定する値 コマンド
⇒ 現在ログインしているユーザーを表示する
who

Ubuntu Serverでネットワークに接続できない

,
Ubuntu Server9.04をVM Ware上にインストールしましたが,初期状態でネットワークに接続できません(IPが正しく割り振られません)でした.
少し詰まったのでメモ

ネットワークカードを正常に認識していなかったようです.

1.ネットワークデバイス名を調べる
# lshw -C network

logical name をメモ
私の環境ではeth0でした.

2.ネットワークデバイスの設定
# vi /etc/network/interfaces
---------------------------
auto lo
iface lo inet loopback
# 以下を追記
auto eth0
iface eth0 inet dhcp
---------------------------


3.ネットワークの再起動
# /etc/init.d/networking restart


以上により,正常にIPが割り振られネットワークに接続できます.

JBox2Dのプログラムサンプル

,
2D物理シュミレーションエンジンBox2DのJavaバージョンであるJBox2Dを使用してみました.
JBox2D:http://www.jbox2d.org/


以下のプログラムは,ある閉じた空間(2D)内に複数のボールを用意し,物理演算を行ってボールが跳ねる様子を見ることができます.
また,自由に新しいボールや壁を追加することができます.


[PhysicalWorld.java]

import org.jbox2d.collision.AABB;
import org.jbox2d.collision.CircleDef;
import org.jbox2d.collision.PolygonDef;
import org.jbox2d.collision.Shape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.World;
import org.jbox2d.dynamics.joints.MouseJoint;
import org.jbox2d.dynamics.joints.MouseJointDef;
import org.jbox2d.collision.*;

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;

import java.util.*;

public class PhysicalWorld extends JFrame {
public static void main(String[] args) {
new PhysicalWorld();
}

public PhysicalWorld() {
// タイトルを設定
setTitle("MyFrame");
// 閉じるボタンを押した際,プログラムを終了
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 起動時のロケーション設定
// setLocation(0, 0);

// メインパネルを作成してフレームに追加
MainPanel panel = new MainPanel();
Container contentPane = getContentPane();
contentPane.add(panel);
setVisible(true);
// パネルサイズに合わせてフレームサイズを自動設定
pack();
}
}

class MainPanel extends JPanel implements Runnable {
// パネルサイズ
private static int width = 600;
private static int height = 400;
// 1m = 10px
private static final int WORLD_SCALE = 10;
private World mWorld;

// 壁格納用リスト
private java.util.List groundBodyList = new ArrayList();
// ボール格納用リスト
private java.util.List ballBodyList = new ArrayList();

// マウスジョイント
private MouseJointDef mouseJointDef;
private MouseJoint mouseJoint;

// アニメーション用スレッド
private Thread thread;
Body ballBody;

public MainPanel() {
initMainPanel();
initWorld();
initGround();
initBall();
// スレッドを起動
thread = new Thread(this);
thread.start();
}

private void initMainPanel() {
// パネルの推奨サイズを設定
// pack()するときに必要
setPreferredSize(new Dimension(width, height));
setBackground(Color.BLACK);
// マウスリスナを登録
this.addMouseListener(new MyListener());
this.addMouseMotionListener(new MyListener());
}

private void initWorld() {
Vec2 minV = new Vec2(-100,-100);
Vec2 maxV = new Vec2(100,100);
AABB aabb = new AABB(minV,maxV);
mWorld = new World(aabb, new Vec2(0.0f,9.8f),true);
}

private void initGround() {
// 上壁
createGroundBody(0.0f, 0.0f, (width * 0.9f) / WORLD_SCALE, 0.0f);
// 下壁
createGroundBody(0.0f, (height * 0.9f) / WORLD_SCALE, (width * 0.9f) / WORLD_SCALE, (height * 0.9f) / WORLD_SCALE);
// 左壁
createGroundBody(0.0f, 0.0f, 0.0f, (height * 0.9f) / WORLD_SCALE);
// 右壁
createGroundBody((width * 0.9f) / WORLD_SCALE, 0.0f, (width * 0.9f) / WORLD_SCALE, (height * 0.9f) / WORLD_SCALE);
}

private void initBall() {
// ボールの作成
for(int i = 15; i < 30; i++){
createBallBody((float)i, 10.0f);
}

// ジョイント用ボールの作成
BodyDef ballBodyDef = new BodyDef();
ballBodyDef.position.set(15.0f, 5.0f);
CircleDef ballShapeDef = new CircleDef();
ballShapeDef.radius = 1.0f;
ballShapeDef.density = 1.0f;
ballShapeDef.restitution = 0.7f;

ballBody = mWorld.createBody(ballBodyDef);
ballBody.createShape(ballShapeDef);
ballBody.setMassFromShapes();
ballBodyList.add(ballBody);

mouseJointDef = new MouseJointDef();
mouseJointDef.body1 = mWorld.getGroundBody();
mouseJointDef.body2 = ballBody;
mouseJointDef.target =  ballBody.getWorldCenter();
mouseJointDef.maxForce = 1000;
}

private void createGroundBody(float sx, float sy, float ex, float ey){
BodyDef groundBodyDef = new BodyDef();
groundBodyDef.position.set((sx + ex)/2.0f, (sy + ey)/2.0f);
PolygonDef groundShapeDef = new PolygonDef();
int angle = (int)(Math.atan((double)(ey - sy) / (double)(ex - sx)) * 180 / Math.PI);
float dis = (float)Math.sqrt(Math.pow((sx-ex), 2) + Math.pow((sy-ey), 2)) / 2.0f;
groundShapeDef.setAsBox(dis, 0.1f, new Vec2(0,0),(float)(Math.PI * angle / 180.0));
Body groundBody = mWorld.createBody(groundBodyDef);
groundBody.createShape(groundShapeDef);
groundBodyList.add(groundBody);
}

private void createBallBody(float x, float y){
BodyDef ballBodyDef = new BodyDef();
ballBodyDef.position.set(x, y);
CircleDef ballShapeDef = new CircleDef();
ballShapeDef.radius = 1.0f;
ballShapeDef.density = 1.0f;
ballShapeDef.restitution = 0.7f;
Body ballBody = mWorld.createBody(ballBodyDef);
ballBody.createShape(ballShapeDef);
ballBody.setMassFromShapes();
ballBodyList.add(ballBody);
}

public void paintComponent(Graphics g) {
super.paintComponent(g);

g.setColor(Color.GREEN);

for(Body groundBody : groundBodyList){
Shape shape = groundBody.getShapeList();
Vec2[] vPts = ((PolygonShape)shape).getVertices();

int minX = (int)Math.min(Math.min(vPts[0].x, vPts[1].x), Math.min(vPts[2].x, vPts[3].x));
int minY = (int)Math.min(Math.min(vPts[0].y, vPts[1].y), Math.min(vPts[2].y, vPts[3].y));
int maxX = (int)Math.min(Math.max(vPts[0].x, vPts[1].x), Math.max(vPts[2].x, vPts[3].x));
int maxY = (int)Math.min(Math.max(vPts[0].y, vPts[1].y), Math.max(vPts[2].y, vPts[3].y));

minX = (int)(groundBody.getWorldCenter().x + minX) * WORLD_SCALE;
minY = (int)(groundBody.getWorldCenter().y + minY) * WORLD_SCALE;
maxX = (int)(groundBody.getWorldCenter().x + maxX) * WORLD_SCALE;
maxY = (int)(groundBody.getWorldCenter().y + maxY) * WORLD_SCALE;

if(vPts[0].y <= vPts[1].y){
g.drawLine(minX, minY, maxX, maxY);
} else {
g.drawLine(minX, maxY, maxX, minY);
}
}

g.setColor(Color.RED);
int r = 2;
Vec2 pos;

for(Body ballBody : ballBodyList){
pos = ballBody.getWorldCenter();
g.fillOval((int)((pos.x-r/2) * WORLD_SCALE), (int)((pos.y-r/2) * WORLD_SCALE), r*WORLD_SCALE, r*WORLD_SCALE);
}
}

// メインループ
public void run() {
// プログラムが終了するまでフレーム処理を繰り返す
while (true) {
mWorld.step(1/20f, 8);

// ボールを再描画
repaint();

// 20ミリ秒だけ休止
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public class MyListener extends MouseAdapter {
Point startP,endP;

// ボタンプレス時
public void mousePressed(java.awt.event.MouseEvent e){
if((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0){         // 左クリック
// ジョイントの作成
mouseJoint = (MouseJoint)mWorld.createJoint(mouseJointDef);
mouseJoint.m_localAnchor = ballBody.getLocalCenter();
} else if((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0){   // 右クリック
// クリックポイントの作成
startP = e.getPoint();
}
}   

// ボタンリリース時
public void mouseReleased(java.awt.event.MouseEvent e){
if((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0){
// ジョイントの削除
mWorld.destroyJoint(mouseJoint);
mouseJoint = null;
} else if((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0){
// リリース場所の格納
endP = e.getPoint();
if(Math.abs(startP.x - endP.x) < 3 && Math.abs(startP.y - endP.y) < 3){   // プレス時とリリース時にあまり差が無い場合
// 新しいボールを作成
createBallBody(startP.x / WORLD_SCALE, startP.y / WORLD_SCALE);
} else {
// プレス場所からリリース場所まで壁を作成する
createGroundBody(startP.x / WORLD_SCALE, startP.y / WORLD_SCALE, endP.x / WORLD_SCALE, endP.y / WORLD_SCALE);
}
}
}

// マウスドラッグ時
public void mouseDragged(java.awt.event.MouseEvent e){
if((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0){
if(mouseJoint != null){
// ボールの移動
int x = e.getPoint().x / WORLD_SCALE;
int y = e.getPoint().y / WORLD_SCALE;
mouseJoint.setTarget(new Vec2(x, y));
}
}
}
}
} 

[Java]インタフェースのフック

,
Javaでインタフェースのフックを行います.


サンプルプログラムは,GUIに表示されたボタンを押した場合のフックについて記述してあります.

[実行クラス Main.java]
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import javax.swing.*;

public class Main extends JFrame{

public Main(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(200, 200, 200, 200);
setVisible(true);
JPanel p = new JPanel();

InvocationHandler handler = new MyInvocationHandler(new MyListener());
ActionListener action = (ActionListener) Proxy.newProxyInstance(MyListener.class.getClassLoader(), new Class[]{ActionListener.class}, handler);

JButton btn = new JButton("push");
btn.addActionListener(action);
btn.setActionCommand("btn");

p.add(btn);
add(p);
}

public static void main(String[] args) {
new Main();
}
}



[イベントリスナー MyListener,java]
import java.awt.event.*;

public class MyListener implements ActionListener{
public void actionPerformed(ActionEvent e){
if(e.getActionCommand().equals("btn")){
System.out.println("push");
}
}
}




[インボケーションハンドラー MyInvocationHandler.java]
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

private ActionListener action;

public MyInvocationHandler(ActionListener action) {
this.action = action;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
System.out.println("前処理");
result = method.invoke(action, args);
System.out.println("後処理");
return result;
}
}



GUIで表示されたボタンを押した際の処理結果は下記の様になります.
前処理
push
後処理

[Java]リフレクションによるメソッドの取得

,
リフレクションを用いて,特定クラスのメソッドを解析します.
サンプルプログラムでは親クラスから継承しているメソッドは取り除いています.

[調べるクラス Function.java]
import java.util.*;

public class Function {
public static int service(List list, int a ,byte e) throws Exception{
return 1;
}

public void service2(){
}
}


[メソッド情報を保持するクラス MethodInfo.java]
import java.util.List;
import java.util.ArrayList;

public class MethodInfo {
private String    name;   // メソッド名
private String    modifier;  // 修飾子
private List  paramTypes;  // メソッドの引数型の配列
private String    returnType;  // 返り値の型

public MethodInfo(){};

public MethodInfo(String   _name,
String   _modifer,
List _paramTypes,
String   _returnType){
name         = _name;
modifier     = _modifer;
paramTypes   = _paramTypes;
returnType   = _returnType;
}

public void setName(String _name){
name = _name;
}

public void setModifier(String _modifer){
modifier = _modifer;
}

public void setParamTypes(List _paramTypes){
paramTypes = _paramTypes;
}

public void setReturnType(String _returnType){
returnType = _returnType;
}

public String getName(){
return name;
}

public String getModifier(){
return modifier;
}

public List getParamTypes(){
return paramTypes;
}

public String getReturnType(){
return returnType;
}

public String toString(){
String str =  "Modifier : " + modifier + "\n";
str += "Name : " + name + "\n";
str += "Params : " + paramTypes.toString() + "\n";
str += "Retrun : " + returnType;
return str;
}
}


[解析実行クラス MethodAnalyzer.java]
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

public class MethodAnalyzer {
private String className;
public MethodAnalyzer(String _className){
className = _className;
}

/**
* クラスのメソッド一覧を取得する
* @param cls
* @return 
*/
private List getMethodList(Class cls){
List list = new ArrayList();
Method[] methods = cls.getMethods();
for(Method method : methods){
list.add(method);
}
return list;
}

/**
* 親クラスのメソッド一覧を取得する
* @param clas
* @return
*/
private List getParentMethodList(Class cls){
return getMethodList(cls.getSuperclass());
}

/**
* 第1引数から第2引数に存在するMethodを削除する
* @param list1
* @param list2
*/
private void removeMatchList(List list1, List list2){
for(Method method : list2){
if(list1.indexOf(method) != -1){
list1.remove(method);
}
}
}

/**
* リフレクションを用いて,クラスを解析する.
* @return MethodInfo[]
*/
public MethodInfo[] analyze(){
// メソッド情報を保持
MethodInfo[] methodInfos = null;
try{
// 親クラスには存在せず,自クラスのみに存在するメソッドを抽出
Class cls = Class.forName(className);
List methodList = getMethodList(cls);
removeMatchList(methodList, getParentMethodList(cls));

// メソッド情報配列の領域確保
methodInfos = new MethodInfo[methodList.size()];

for(int i = 0 ; i < methodList.size(); i++){
// メソッド情報配列の初期化
methodInfos[i] = new MethodInfo();

// 修飾子を取得&格納
methodInfos[i].setModifier(Modifier.toString(methodList.get(i).getModifiers()));

// 戻り値の型を取得&格納
methodInfos[i].setReturnType(methodList.get(i).getReturnType().getName());

// メソッド名を取得&格納
methodInfos[i].setName(methodList.get(i).getName());

// 引数の型を取得&格納
Class[] params = methodList.get(i).getParameterTypes();
List paramTypes = new ArrayList();
for(Class c : params){
paramTypes.add(c.getName());
}
methodInfos[i].setParamTypes(paramTypes); 
}
} catch (ClassNotFoundException cnfe){
cnfe.printStackTrace();
}
return methodInfos;
}

// 使用例
public static void main(String[] args) {
MethodAnalyzer ma = new MethodAnalyzer("Function");
MethodInfo[] mis = ma.analyze();

for(MethodInfo mi : mis){
System.out.println(mi.toString() + "\n");
} 
}
}



[実行結果]
Modifier : public
Name : service2
Params : []
Retrun : void

Modifier : public static
Name : service
Params : [java.util.List, int, byte]
Retrun : int