2009年1月23日 星期五

svnadmin dump 參數說明

在命令列下輸入
$svnadmin help dump 會出現以下訊息:

dump: 用法: svnadmin dump REPOS_PATH [-r LOWER[:UPPER]] [--incremental]

將檔案系統的內容, 以一種可攜式 '傾印檔' 格式輸出到標準輸出, 並將訊息
回報輸出到標準錯誤. 將 LOWER 與 UPPER 之間修訂版內容傾印出來. 如果沒
有指定修訂版的話, 傾印所有的修訂版樹. 如果只有指定 LOWER 的話, 只傾印
一個修訂版樹. 如果使用了 --incremental 選項, 那麼第一個傾印的修訂版會
是與前一個修訂版的差異, 而非平常的全文輸出.

有效選項:
-r [--revision] ARG : 指定修訂版編號 ARG (或 X:Y 範圍)
--incremental : 以差異增量進行傾印
--deltas : 於傾印檔輸出中使用檔案差異
-q [--quiet] : 不顯示進度 (僅錯誤) 至標準錯誤輸出


僅備份部分版本需使用 -r 參數,如:
repos檔案庫的最新版本號為100
svnadmin dump repos/ -r 90:100
即是完整備份90到最新的100的資料,但下次使用svnadmin load指令回來時
版本會從1開始算,也就是之前的版本90變成版本1

--incremental是進行差異備份,影響的是第一個版本的內容,如:
svnadmin dump repos/ -r 90:100 --incremental
一樣是備份 90-100 之間的資料,但版本90的資料卻不包含版本89之前的資料
也就是備份出來的資料必須建立在已經有版本89的檔案庫為基礎的檔案庫
如果 svnadmin load 時沒有版本 89的檔案庫為基礎,則會出現錯誤。

2009年1月19日 星期一

非 standalone jetty的啟動關閉方式

非 standalone jetty的啟動關閉方式:
cd %JETTY_HOME%
java -DSTOP.PORT=8079 -DSTOP.KEY=secret -jar start.jar

這將告訴Jetty在8079 Port偵聽Stop命令,並且Stop時要求提供Key:secret。對應的Stop命令:
java -DSTOP.PORT=8079 -DSTOP.KEY=secret -jar start.jar --stop

一個簡單的 shell script進行控制
#!/bin/bash
cd /usr/local/jetty-6.1.12.rc2
if [ "$1" == "start" ]; then
java -DSTOP.PORT=8079 -DSTOP.KEY=green -jar start.jar etc/jetty.xml etc/green-jaas.xml &
elif [ "$1" == "stop" ]; then
java -DSTOP.PORT=8079 -DSTOP.KEY=green -jar start.jar --stop
else
echo "useage: switch.sh [start|stop]."
fi

2009年1月14日 星期三

debian base安裝+icewm+基本套件

安裝好base system

xorg:
aptitude install xorg
x window:
aptitude install icewm
update-alternatives --config x-session-manager
update-alternatives --config x-window-manager
terminal:
aptitude install mlterm mlterm-tools
update-alternatives --config x-terminal-emulator
input:
aptitude install gcin
font:
sudo aptitude install ttf-wqy-zenhei
sudo aptitude install xfonts-wqy

修改startx啟動的X windows manager

update-alternatives --config x-session-manager
update-alternatives --config x-window-manager

2009年1月9日 星期五

Spring支援的log4j設定web.xml

在web.xml裡增加下列設定,即可整合log4j到webapp裡:

2009年1月3日 星期六

Debian好看的中文字型-文泉驛

文泉驛
sudo aptitude install ttf-wqy-zenhei
sudo aptitude install xfonts-wqy
文鼎
sudo aptitude install ttf-arphic-bkai00mp
sudo aptitude install ttf-arphic-uming

Debian安裝過程載入adsl pppoe設定

使用debian安裝光碟開機後,不直接按Enter進入安裝程序.
選擇Help選項,即可查尋及輸入特殊參數,
啟動載入 pppoe 模組的參數:
install modules=ppp-udeb
這樣一來在安裝過程,安裝程式會詢問adsl的帳號密碼
來進行網路設定.

2009年1月2日 星期五

建立USB隨身碟debian安裝碟

安裝套件:
dosfstools,syslinux,mtools,mbr
步驟:

1. 建立FAT16到USB的第一分割區上
#fdisk /dev/sdb (設定bootable,partition system id)
#mkdosfs /dev/sdb1

2. 安裝syslinux到USB
#syslinux /dev/sdb1 (會在sdb1上建立
ldlinux.sys)

3. mount USB 並 copy必需的檔案
#mount /dev/sdb1 /mnt
#cp
vmlinuz /mnt (kernel)
#cp
initrd.gz /mnt (initrd)

4. 建立 syslinux 設定檔
在 /mnt 新建 syslinux.cfg
內容包含下兩行:

DEFAULT vmlinuz auto url=debian.org.tw modules=ppp-udeb
APPEND initrd=initrd.gz

5. copy debian 安裝光碟映象檔
#cp debian-testing-i386-xfce-CD-1.iso /mnt

6. mount USB
#umount /dev/sdb1

7. 安裝mbr到USB的開機區
#install-mbr /dev/sdb

8. 重開機並設定BIOS使用USB開機

2008年12月25日 星期四

jetty 的 JAAS 啟動設定

不能再以 $JETTY_HOME/bin/jetty.sh start 啟動 jetty server
而是在 $JETTY_HOME 下,以 java -jar start.jar etc/jetty.xml etc/jetty-jaas.xml 來啟動 server
首先在 webapp 的 web.xml 下加入有關的security設定,主要是以下3個tag:
security-constraint 、login-config、security-role,
其中login-config下的realm-name會對應到 etc/jetty-jaas.xml下的UserRealm中的setName資料
JAAS又自動從java.security.auth.login.config環境變數指定到的檔案中去找到UserRealm中
LoginModuleName所設定的名字進而找到java.security.auth.login.config裡應該被運作的
LoginModule 。

web.xml(設定realm-name) =>
jetty-jaas.xml (設定realm與LoginModule對應,與指定LoginModule設定檔位置) =>
java.security.auth.login.config(指定LoginModule設定檔位置) =>
LoginModule設定檔(某LoginModuleName使用哪些LoginModule的實作類別及其條件參數)

2008年12月12日 星期五

DNS修改ip對應的小技巧

假設最優先DNS server 為 168.95.1.1
當有client要尋找某網址的ip時,例如要找:www.google.com.tw
168.95.1.1的運作方式是:

會先去問(root) . DNS -> .tw DNS -> .com.tw DNS -> .google.com.tw

但一但問到後168.95.1.1 DNS server會將www.google.com.tw的對應暫時放在memory裡
這樣下一次又有client問www.google.com.tw時就不用再跑一次,

不過如果www.google.com.tw改了ip位址,這樣一來所有和168.95.1.1詢問的client
都會問到錯的ip,這時可以將client的DNS server優先順序改一下,
讓client暫時以別台沒有暫存www.google.com.tw的DNS server去重新由root開始查找ip

如此即可暫時解決,而約1-2天後168.95.1.1的暫存記錄也會因timeout而消失,
這時到168.95.1.1查找的client也可以找到對的ip了。

2008年12月11日 星期四

滑鼠連點3下觸發mouse listener實作(AWT)

source.addMouseListener(new MouseAdapter() {
private int interval = 300; // ms
private int target = 3; // 連點3下
private int addup = 0; // 已連點了addup下
private Calendar calPriorTime = Calendar.getInstance();

@Override
public void mouseClicked(java.awt.event.MouseEvent e) {
Calendar calNow = Calendar.getInstance();
long curInterval = calNow.getTimeInMillis() - calPriorTime.getTimeInMillis();
if (curInterval > interval) {
// 點第一下(和上一次點的時間相差太久)
addup = 1;
} else {
// 連點(和上一次點的時間相差在interval內)
addup++;
}
if (addup >= target) {
addup = 0;
System.out.println("連點三下已被觸發。");
}
calPriorTime = calNow;
}
});

2008年12月5日 星期五

JUnit 4 簡介

JUnit 4是JUnit框架有史以來的最大改進,其主要目標便是利用Java 5的Annotation特性簡化測試用例的編寫。讓我們看看如何使用JUnit 4來進行Unit測試。

我們先看一個簡單的Math類:
package com.javaeedev.junit4;
public class Math {

public int abs(int value) {
return value>=0 ? value : (-value);
}

public int div(int a, int b) {
return a / b;
}

/**
* BUG: if b less than 0!
*/
public float exp(int a, int b) {
float r = 1;
for(int i=0; i
r = r * a;
return r;
}
}

注意exp()方法是有Bug的,如果傳入參數2, -1,則期待的返回值應為0.5F,但實際返回值為1.0F。

傳統的JUnit的TestCase:
public class MathTest extends TestCase {

public void setUp() { super.setUp(); }
public void tearDown() { super.tearDown(); }

public void testAbs() { assertTrue(true); }
public void testDiv() {...}
public void testExp() {...}

}

JUnit依賴反射來執行每個以test開頭的方法。然而,在最新的JUnit 4中,由於有了Annotation的支持,我們的測試方法不需要再以testXxx標識了,而是寫上一個@Test標註即可。例如:
@Test public void doAbs() {...}

甚 至MathTest類也不必繼承自TestCase。你也許會想到,不繼承自TestCase就無法調用assertXxx方法了,正因為如此,所有的 assertXxx方法全部以靜態方法被放入了Assert類,使用Assert.assertXxx()調用。如果使用
import static org.junit.Assert.*;

則原有的代碼不必改動。

setUp()和tearDown()方法也依賴@Before和@After標記,這樣做的最大的好處是在繼承體系內不必擔心忘記了在setUp ()方法中調用父類的super.setUp()方法,JUnit框架會自動處理父類的@Before和@After標記的方法。

並且,JUnit框架對@Before和@After的調用順序類似於類的構造方法和析構方法,即@Before按照父類到子類的順序調用,@After則相反,這樣保證了資源的正確獲取和釋放。

當然,不再強迫必須使用setUp和tearDown作為方法名,可以使用更有意義的方法名,例如:initDatabase()和closeDatabase(),只要它們被標註了@Before和@After即可。

來看看使用Annotation的MathTest:
package com.javaeedev.junit4;

import static org.junit.Assert.*;

import org.junit.*;

public class MathTest {

public MathTest() {
System.out.println("new MathTest instance.");
}

@Before
public void setUp() throws Exception {
System.out.println("call @Before before a test method");
}

@After
public void tearDown() throws Exception {
System.out.println("call @After after a test method");
}

@Test
public void doAbs() {
Math math = new Math();
assertEquals(200, math.abs(200));
assertEquals(100, math.abs(-100));
assertEquals(0, math.abs(0));
}

@Test
public void doDiv() {
Math math = new Math();
assertEquals(5, math.div(100, 20));
assertEquals(4, math.div(100, 21));
}

@Test(expected=ArithmeticException.class)
public void doDiv0() {
new Math().div(127, 0);
}

@Test(timeout=1)
public void doLongTimeTask() {
double d = 0;
for(int i=1; i<10000000; i )
d =i;
}

@Test
public void testExp() {
Math math = new Math();
assertEquals(32f, math.exp(2, 5), 0.001f);
assertEquals(1f, math.exp(2, 0), 0.001f);
assertEquals(0.5f, math.exp(2, (-1)), 0.001f);
}

}

對測試異常,JUnit 4可以用expected=Exception.class來期待一個預期的異常,而不必編寫
try {
...
fail("No exception");
}
catch(Exception e) {
// OK!
}

來看看doDiv0測試,我們期待一個除數為0的ArithmeticException,因此編寫如下測試方法:
@Test(expected=ArithmeticException.class)
public void doDiv0() {
new Math().div(127, 0);
}

對於非常耗時的測試,@Test還有一個timeout來標識該方法最長執行時間,超過此時間即表示該測試方法失敗:
@Test(timeout=1)
public void doLongTimeTask() {
double d = 0;
for(int i=1; i<10000000; i )
d =i;
}

以上方法若執行時間超過1ms則測試失敗,由於依賴CPU的執行速度,在不同的機器上測試結果也不同。

JUnit 4另一個較大的變化是引入了@BeforeClass和@AfterClass,它們在一個Test類的所有測試方法執行前後各執行一次。這是為了能在 @BeforeClass中初始化一些昂貴的資源,例如數據庫連接,然後執行所有的測試方法,最後在@AfterClass中釋放資源。

正如你能想到的,由於@BeforeClass和@AfterClass僅執行一次,因此它們只能標記靜態方法,在所有測試方法中共享的資源也必須是靜態引用:
private static Object dbConnection;

@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("call @BeforeClass and init database connection");
dbConnection = new Object();
}

@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("call @AfterClass to release database connection");
dbConnection = null;
}

最後執行測試用例,可以看到結果:

各個方法執行順序如下:

call @BeforeClass and init database connection

new MathTest instance.
call @Before before a test method
call @After after a test method

new MathTest instance.
call @Before before a test method
call @After after a test method

...

call @AfterClass to release database connection

可以看到,@BeforeClass是在實例化MathTest之前調用的,因此不能在構造方法中初始化共享資源。

最後需要注意的是由於Java 5的自動Box/Unbox特性,在調用assertEquals()時要特別注意,如果你傳入:

assertEquals(100F, 100);

則按照自動Box變為:

assertEquals(new Float(100F), new Integer(100));

測試失敗,因為Float類和Integer類不是同一類型。

因此要特別注意float和double的測試。事實上對float和double應使用

assertEquals(float, float, float delta);
assertEquals(double, double, double delta);

delta指定了兩個作比較的浮點數的相差範圍,在此範圍內的兩個浮點數將認為相等。可以傳入一個很小的數例如0.0001F。

JUnit 4非常適合使用Java 5的開發人員,但是無法在Java 1.4中獲得這些好處,並且,也不與以前的版本兼容。因此,如果你正在使用Java 5,就可以考慮使用JUnit 4來編寫測試。

spring aop 架構概觀

2008年11月26日 星期三

Spring資料庫Unit測試

進行資料庫測試,卻又不把資料寫入資料庫的方法就是使用 Transaction 交易機置,
在進行Unit測試時,開始一個 Transaction 並將之後Unit測試的資料庫操作都在 Transaction 中進行
,等到測試完畢再將 Transaction 給 rollback,如此一來即不會在資料庫中留下測試資料。

Spring提供了一個AbstractTransactionalSpringContextTests測試類別,該類別已經實作了
JUnit 的 TestCase,所以直接繼承他就可以開始寫測試程式,另外必須 override 他的:

//提供 spring bean 設定檔的位置
protected String[] getConfigLocations()

// 取代原本的 SetUp
protected void onSetUpInTransaction() throws Exception

// 取代原本的 TearDown
protected void onTearDownInTransaction() throws Exception

除此之外,由於AbstractTransactionalSpringContextTests會使用宣告式的交易,也就是說,
在 spring bean 設定檔裡必須提供一個bean
id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
並注入 SessionFactory (如:org.springframework.orm.hibernate3.LocalSessionFactoryBean)
property name="sessionFactory"

2008年11月23日 星期日

svn 使用merge 進行undo

假設當前 repository 版本為 50
假設之前 commit 了一個錯誤的資料進 repository ,版本為 48。
而現在才發現錯誤想進行 undo
意思就是 47->48 之間的 diff 是我不想要的部分
如果說47->48的diff是新增xxx反過來說 48->47的diff就是刪除xxx
因此,目前的workcopy就是要去merge 48->47的diff,就可以達到 undo的效果
svn merge -r 48:47 workcopy/
目前只是undo了workcopy還要進行commit
svn ci workcopy/ -m "undo"

2008年11月12日 星期三

vbox guest 與 host 分享資料夾

安裝完guest電腦後,啟動guest電腦。

選擇 "裝置" > "安裝客端額外功能"

vbox 會要求從網路下載 VBoxGuestAdditions_1.6.6.iso 檔案,
並存放在 ~/.VirtualBox 下。

下載完成後將此 iso 檔掛載到 guest 電腦的光碟機上,並 mount 到 /media/cdrom0。
在 cdrom0 中找到 VBoxLinuxAdditions.run 這一個 script

先確定guest電腦有安裝好 gcc 套件,再執行 VBoxLinuxAdditions.run。

安裝完成 VBoxLinuxAdditions.run 後先關閉 guest 電腦。

在 vbox 設定值 > 分享資料夾 右上角加入新的分享資料夾,例:
資料夾路徑:/home/muchu1983/vboxsf
名稱:vboxsf

重新啟動guest 電腦。

在guest電腦建立~/vboxsf 目錄,例:mkdir /home/vbox/vboxsf

編輯guest電腦的/etc/fstab,加上一行:
vboxsf /home/vbox/vboxsf vboxsf uid=vbox,rw,auto 0 0

重新開機或執行mount -a,如此,guest和host電腦就可以
透過各自的~/vboxsf 共享資料夾分享資料。

2008年11月11日 星期二

bash下輸出命令到serial/parallel port

serial port
echo -e "\x9e123" > /etc/ttyS0
parallel port
echo -e "\x9e123" > /etc/lp0

-e 是 enable backslash escape 也就是 "\"
而字串中的 "\x" 是指16進位。
java 對 serial/parallel 支援的 api 為

RXTX:
RXTXcomm.jar 及一些 native lib
http://www.rxtx.org/

JCA:
http://java.sun.com/products/javacomm/index.jsp

2008年11月6日 星期四

2008年11月5日 星期三

Debian backports

參考:http://wiki.debian.org/Backports
Debian下分為 stable testing unstable 三個主要版本,stable 最穩定但套件也最老舊。
backports 是一個Debian套件更新站,上面放著只有testing和unstable的套件,
但經由stable的環境重新compile而成。所以可以在stable環境中正常執行,
透過使用 backports 可以讓 stable 版本的 Debian 用到 testing 和 unstable 下才有的套件。

必須先安裝:debian-backports-keyring 套件,用來通過 backports 上的驗証。
在 /etc/apt/sources.list 加上
deb http://www.backports.org/debian/ etch-backports main contrib non-free
開啟aptitude並update即可安裝backports上的套件
aptitude -t etch-backports install "package"

Linux 下的 VirtualBox bridge 模式

安裝 VirtualBox:
先設定好backports
安裝 virtualbox-ose、virtualbox-ose-source 兩個套件
編譯並載入vboxdrv模組:
# cd /usr/src
# tar xvjf virtualbox-ose.tar.bz2
# cd modules/virtualbox-ose
# make
# make install
# modprobe vboxdrv
# lsmod | grep vbox
vboxdrv 55344 0
VirtualBox 有兩種模式 NAT 以及 Bridge 。
Bridge 設定方式如下。
停止eth0
#ifconfig eth0 down
修改/etc/network/interfaces檔案,註解掉eth0相關設定。
並加上br0設定。
# allow-hotplug eth0
# iface eth0 inet dhcp
auto br0
iface br0 inet dhcp
bridge_ports eth0
bridge_fd 2.5
要先安裝 bridge-utils uml-utilities 兩個套件
sudo apt-get install bridge-utils uml-utilities
設定方式
tunctl -t tap0 -u
brctl addbr br0
ifconfig eth0 0.0.0.0 promisc
brctl addif br0 eth0
dhclient br0
brctl addif br0 tap0
ifconfig tap0 up
chmod 666 /dev/net/tun
上面可以寫成shell script 存檔,記得用 root 身份執行這些指令,
完成後 ifconfig 會多 br0 , tap0 。
而在 VirtualBox 網路設定為 “Host Interface” 而 Interface Name 為 tap0。
而 guest os 就可以互連 host os 。
若要關掉 bridge 模式
brctl delif br0 eth0
brctl delif br0 tap0
brctl delbr br0
ifconfig tap0 down
ifconfig br0 down
ifconfig eth0 down
ifconfig eth0 up
不過 bridge 模式適合用在有線網卡,無線網卡部份還無法適用。