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 模式適合用在有線網卡,無線網卡部份還無法適用。

2008年10月23日 星期四

Live USB Debian 20g隨身碟筆電

製作自己的LiveUSB:
將Debian裝在隨身碟上,並將BIOS設定為USB開機
即可進入作業系統進行一般電腦操作。

下載live-helper套件並安裝:
http://packages.debian.org/sid/live-helper/all/download
dpkg -i live_helper_1.0~a31-1_all.deb
同時也必須安裝 live-helper 相依的 debootstrap

安裝完成後建立一工作目錄
mkdir liveusb
cd liveusb

使用lh_config設定參數,並以 lh_build 產生 image 檔 - binary.img
lh_config
-b usb-hdd
-d etch
-p xfce-desktop
--bootappend-live "local=zh_TW.UIF-8 keyb=us"
-m "http://ftp.tw.debian.org/debian"
&&
lh_build
(需要很長時間)

將usb隨身碟 umount
umount /dev/sda1

以 dd 將 binary.img 輸出到隨身碟上
dd if=binary.img of=/dev/sda bs=1M
注意要輸出到整個隨身碟(sda)而不是單一磁區(sda1)

2008年10月22日 星期三

Spring i18n 設定

Spring使用MessageSource介面做為i18n資訊的存取介面,
而且ApplicationContext即實作了MessageSource介面,
只需要在bean-config.xml裡加上MessageSource的bean即可。
ApplicationContext在啟動時會自動尋找bean-config.xml裡id為messageSource的bean
並將ApplicationContext所收到的MessageSource介面的呼叫都轉到這個bean來實作,

MessageSource bean的 id 一定要稱為 messageSource

一般使用 ResourceBundleMessageSource 做為 MessageSource bean
並指定 property basename 假設 basename 為 message
ResourceBundleMessageSource 會尋找 classpath 下的
message_zh_TW.properties , message_en_US.properties, message_xx_XX.properties ...
做為 i18n的資料來源。

如果是webapp的環境下,想將 i18n的資料放在 WEB-INF 下 (非classpath)
則應該改用 ReloadableResourceBundleMessageSource 做為 MessageSource bean
並指定 basename 為 WEB-INF/i18n/message

如果有中文亂碼的情型,
使用 utf-8 儲存資料來源檔 (message_xx_XX.properties)
且 messageSource bean 加上 property defaultEncoding value當然是 UTF-8 即可。

2008年10月6日 星期一

svn dump 備份

備份:
svnadmin dump REPOS_PATH > back_file.dmp
回存:
svnadmin create NEW_REPOS
svnadmin load NEW_REPOS_PATH < back_file.dmp

2008年10月3日 星期五

Spring Multipart

MutipartResolver要設定UTF-8為預設編碼,不然會造成中文亂碼的問題。


2008年9月22日 星期一

JavaEE HttpSession 用法

先建立一個儲存使用者資訊用的POJO物件,如:

使用WebApp的Servlet或Spring Controller,建立Login及Logout的動作,

Login:


Logout:

2008年9月19日 星期五

Hibernate 自定 generator

Hibernate的generator tag 是用來定義如何Hibernate物件的主鍵
如:


使用increment可以使主鍵每次自動加一。
然而class也可以是自己設計的 java CustGenerator class
要設計一個generator class 必須 implement兩個interface:
public class GreenBookGroupGenerator implements IdentifierGenerator, Configurable

IdentifierGenerator interface 提供 的方法
public Serializable generate(SessionImplementor session, Object obj) throws HibernateException
會在每次需要主鍵時被呼叫,obj即是要被指定id的Hibernate entity POJO
要return Serializable id回去。

Configurable interface 提供 的方法
public void configure(Type type, Properties props, Dialect dialect) throws MappingException
只會在SessionFactory建立時呼叫一次,如果generator有提供param會以 key-value pair把參數
放在Properties裡傳進來:

自從Hibernate 3.3 後複合主鍵才可以使用generator tag

2008年9月4日 星期四

hibernate 關連

在hbm.xml使用many-to-one進行多對一關連
當被關連的對象是複合主鍵時,不可在many-to-one tag使用column attribute
只要在many-to-one tag下建立多個子column tag並一一指定name=主鍵欄位名稱即可
如圖:

2008年8月21日 星期四

Eclipse UML2 工具

在預設的Site Ganymede下的Models and Model Development下的UML2*
選擇 UML2 Tools 、 UML2 Tools SDK 、UML2 End-User Features 、UML2 Extender SDK四項,
安裝即可。

使用時New -> Others -> UML 2.1 Diagrams 就可以建立UseCase 等UML圖,
建立時會產生一個.uml的model xml檔案,及另一個.umlxxx的圖形render定義檔,
使用model可以產生各種的render圖,但如果多個圖共用同一個model要小心資料共用的問題。

2008年8月20日 星期三

apache ftpserver-1.0-M2

apache ftpserver 可以加入自定的Ftplet來處理Ftp Event。
只要實作Ftplet interface 或 直接繼承DefaultFtplet。
再加入Ftplet到ftpserver,當Ftp command到來後就會自動呼叫對應的方法。

FtpServer ftpserver = new FtpServer();
ftpserver.setFtplets(getFtpletsMap());
ftpserver.start();

想使用DefaultFtplet來處理Ftp命令,可以override DefaultFtplet的onXXXStart方法。
卻找不到onListStart方法,來顯示檔案列表。
看了一下source code 發現DefaultFtplet的實作只是把beforeCommand根據,
request.getCommand()取得的命令來分支到其他方法,如下,

public FtpletResult beforeCommand(FtpSession session, FtpRequest request)
throws FtpException, IOException {
String command = request.getCommand().toUpperCase();

if ("DELE".equals(command)) {
return onDeleteStart(session, request);
} else if ("STOR".equals(command)) {
return onUploadStart(session, request);
} else if ("RETR".equals(command)) {
return onDownloadStart(session, request);
} else if ("RMD".equals(command)) {
return onRmdirStart(session, request);
} else if ("MKD".equals(command)) {
return onMkdirStart(session, request);
} else if ("APPE".equals(command)) {
return onAppendStart(session, request);
} else if ("STOU".equals(command)) {
return onUploadUniqueStart(session, request);
} else if ("RNTO".equals(command)) {
return onRenameStart(session, request);
} else {
// TODO should we call a catch all?
return null;
}
}

於是就可以自己重新override beforeCommand方法再增加LIST分支即可,
@Override
public FtpletResult beforeCommand(FtpSession session, FtpRequest request) throws FtpException, IOException {
String command = request.getCommand().toUpperCase();
if ("LIST".equals(command)) {
return this.onListStart(session, request);
} else {
return super.beforeCommand(session, request);
}
}

2008年8月11日 星期一

Spring 整合 Hibernate

classpath所需要的jar
===== postgresql ==========
pg74.216.jdbc3.jar
======= spring ===========
spring.jar
commons-logging.jar
======= hibernate =========
antlr-2.7.6.jar
asm.jar
c3p0-0.9.1.jar
cglib-2.1.3.jar
commons-collections-2.1.1.jar
dom4j-1.6.1.jar
ehcache-1.2.3.jar
hibernate3.jar
jta.jar
log4j-1.2.13.jar
=======================

範例資料表DDL
CREATE TABLE tbl_user
(
id serial NOT NULL,
name character varying(20),
age integer,
CONSTRAINT tbl_user_pkey PRIMARY KEY (id)
)

使用HibernateTools產生TblUser.java POJO物件 及 TblUser.hbm.xml mapping file

建立IUserDAO介面
package idv.muchu.test.spring;

public interface IUserDAO {
public void insert(TblUser user);
public void update(TblUser user);
public void delete(TblUser user);
public TblUser find(Integer id);
}

實作IUserDAO介面(使用HibernateTemplate簡化實作)

package idv.muchu.test.spring;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class UserDAO implements IUserDAO {
private HibernateTemplate hibernateTemplate = null;

public void setSessionFactory(SessionFactory sf) {
this.hibernateTemplate = new HibernateTemplate(sf);
}

public void delete(TblUser user) {
hibernateTemplate.delete(user);
}

public TblUser find(Integer id) {
return (TblUser) hibernateTemplate.get(TblUser.class, id);
}

public void insert(TblUser user) {
hibernateTemplate.save(user);
}

public void update(TblUser user) {
hibernateTemplate.update(user);
}
}

spring bean設定檔透過DataSource設定SessionFactory物件並"注入"到UserDAO物件


Demo程式
package idv.muchu.test.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class SpringHibernateDemo {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("dao-config.xml");
IUserDAO userDAO = (IUserDAO)context.getBean("userDAO");
TblUser user = new TblUser();
user.setAge(15);
user.setName("mars");
userDAO.insert(user); //新增
TblUser mark = userDAO.find(1); //查詢
System.out.println("mark's age:" + mark.getAge());
mark.setAge(30);
userDAO.update(mark); //修改
System.out.println("mark's age:" + mark.getAge());
userDAO.delete(mark); //刪除
}
}

2008年7月26日 星期六

hibernate LazyInitializationException

hibernate 3 預設有啟動LazyInitialization
在Session.
load(Class theClass,Serializable id)時
還不會將資料庫中的資料載入到物件中,一直要到物件屬性被改變時才會載入,
但修改物件時Session必須處於open狀態,否則會丟出LazyInitializationException
如果在Session關閉後才要使用物件則可以使用Hibernate.initialize(rec_obj);
來先行載入資料庫的資料到物件中
如:
Session session = HibernateUtil.getSessionFactory().openSession();
User user = (User) session.load(User.class, new Integer(1));
Hibernate.initialize(user);

session.close();

Hibernate的Session物件有兩個:
org.hibernate.Session 及 org.hibernate.classic.Session
classic版是為了相容於Hibernate 2.x的物件,已半棄用,建議新的開發要使用
org.hibernate.Session

使用Hql進行查詢時可以一次查詢多個資料表的物件,只要把資料TO物件extends/implements同一個class/interface即可,如:
Man implements Human ...
Woman implements Human ...
同時查找Man 及 Woman的資料:
Session.find("from Human ...");

透過ThreadLocal讓多個Thread各自管理自己的Session物件範例:
public class HibernateUtil {
public static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException {
Session s = session.get();
if(s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = session.get();
if(s != null) {
s.close();
}
session.set(null);
}
}

2008年7月22日 星期二

debian下使用zhcon

沒有做任何設定直接執行zhcon會造成畫面錯亂當機的情型
只要在/boot/grub/menu.list檔案的最下面的kernel字串後加上vga=791再重新開機就可以了

title Debian GNU/Linux, kernel 2.6.18-4-k7
root (hd0,0)
kernel /boot/vmlinuz-2.6.18-4-k7 root=/dev/hdd1 ro vga=791
initrd /boot/initrd.img-2.6.18-4-k7
savedefault

vga其他顯示模示代碼如下:
Screen 640x480 800x600 1024x768 1280x1024 1600x1200
Colors --------------------------- -------------------------------------------
256 | 769 771 773 775 796
32,768 | 784 787 790 793 797
65,536 | 785 788 791 794 798
16.8M | 786 789 792 795 799

2008年7月21日 星期一

virtualbox

下載:
http://www.virtualbox.org/wiki/Downloads

安裝:
#dpkg --install virtualbox_1.6.2-31466_Debian_etch_i386.deb

加入群組:
#usermod -G vboxusers -a muchu1983

設定Host key:
檔案 -> 偏好設定 -> 輸入

複製一份.vdi硬體檔:
VBoxManage clonevdi /mnt/hdb1/debian-vbox.vdi /mnt/hdb1/debian-vbox-v2.vdi
複製完成即可再建立一台新的虛擬機來使用新的硬碟檔

虛擬機之間的網路互通:
啟用虛擬機的新網卡eth1並設定為掛附到內部網路及給定相同的network name
再分別設定各別虛擬機的eth1 ip (例:192.168.1.100 & 192.168.1.200)
#ifconfig eth1 192.168.1.100

主端分享資料夾給客端電腦:
需先安裝客端額外功能 -
#sh /media/cdrom0/VboxLinuxAdditions.run
在主端vbox程式的 設定值 -> 分享資料夾 -> 加入新的分享資料夾
啟動客端電腦,mount 分享資料夾
#mount -t vboxsf share /mnt/share

2008年7月12日 星期六

java Thread wait() notify() notifyAll() 運作

.使用wait()、notify()、notifyAll()方法前,執行緒必需先獲得物
件鎖,也就是說,執行緒必需是處理物件的synchronized區段
中,該執行緒是處於Running狀態的。

.當執行緒在物件的synchronized區段中碰到了wait()方法,該執
行緒就必需釋放出該物件的Lock,並進入該物件的wait pool中
等待。

.執行的過程式可能會有多個執行緒因為碰到wait()方法而在wait
pool中等待。

..此時。如果某個使用該物件的執行緒碰到了notify()方法,那麼在
物件的wait pool中第一個碰到了wait()方法的執行緒就會被移到該
物件的lock pool中繼續等待取得物件鎖。

..而如果某個使用該物件的執行緒碰到了notifyAll()方法,那麼在物
件的wait pool中所有的執行緒就會被移到該物件的lock pool中,
而優先權最高的執行緒會先取得物件鎖。

2008年7月8日 星期二

Jaas Login module flag意義

      1) Required     - The LoginModule is required to succeed.
If it succeeds or fails, authentication still continues
to proceed down the LoginModule list.

此LoginModule一定要驗証成功整個Login程序才會通過,無論驗証成敗,均會繼續
進行下一個LoginModule驗証。

2) Requisite - The LoginModule is required to succeed.
If it succeeds, authentication continues down the
LoginModule list. If it fails,
control immediately returns to the application
(authentication does not proceed down the
LoginModule list).

此LoginModule一定要驗証成功整個Login程序才會通過,驗証成功,則繼續進行
下一個LoginModule驗証,若驗証失敗,則不繼續進行下一個LoginModule驗証,
驗証程式完成。
3) Sufficient - The LoginModule is not required to
succeed. If it does succeed, control immediately
returns to the application (authentication does not
proceed down the LoginModule list).
If it fails, authentication continues down the
LoginModule list.
此LoginModule不一定要驗証成功,若驗証成功,則繼續進行則不繼續進行下一個
LoginModule驗証,若驗証失敗,則繼續進行下一個LoginModule驗証,
4) Optional - The LoginModule is not required to
succeed. If it succeeds or fails,
authentication still continues to proceed down the
LoginModule list.
此LoginModule不一定要驗証成功,無論驗証成敗,均會進行下一個LoginModule驗証。

2008年7月6日 星期日

XFce4快捷鍵記錄檔位置

XFce4 的預設快捷鍵位置在
/usr/share/themes/Default/xfwm4/keythemerc

2008年6月30日 星期一

xfce新增圖示主題

先到http://www.xfce-look.org/下載想要的圖示
例如XXX.tar.gz
移到~/icons/並解壓縮開來 (如果沒有icons資料夾就自行mkdir)
~/icons/XXX/
即可在 Xfce設定管理程式 -> 使用者介面 -> 圖示主題 下
看到剛新增的圖示主題

2008年6月20日 星期五

JCR研究:jackrabbit

一。使用 svn checkout出jackrabbit的src code
svn co http://svn.apache.org/repos/asf/jackrabbit/trunk jackrabbit
二。進到checkout出來的根目錄,使用 maven 進行build
mvn install
三。完成建置後 maven 會在家目錄產生jackrabbit的jars:
${home}\.maven\repository\org.apache.jackrabbit\jars\jackrabbit-*-SNAPSHOT.jar

四。在classpath引入必要的jars
jcr的有:
jcr-1.0.jar
jackrabbit的有:
jackrabbit-api-1.5-SNAPSHOT.jar
jackrabbit-core-1.5-SNAPSHOT.jar
jackrabbit-jcr-commons-1.5-SNAPSHOT.jar
jackrabbit-spi-1.5-SNAPSHOT.jar
jackrabbit-spi-commons-1.5-SNAPSHOT.jar
jackrabbit-text-extractors-1.5-SNAPSHOT.jar
slf4j的有:
slf4j-api-1.3.0.jar
slf4j-simple-1.5.2.jar
其他:
commons-collections-3.1.jar
concurrent-1.3.4.jar
derby-10.2.1.6.jar
commons-io-1.4.jar
lucene-core-2.2.0.jar
PDFBox-0.7.3.jar
poi-3.0.2-FINAL-20080204.jar
tm-extractors-0.4.jar
poi-scratchpad-3.0.2-FINAL-20080204.jar
poi-contrib-3.0.2-FINAL-20080204.jar

五。第一個登入程式FirstHop
public static void main(String[] args) throws Exception {
// local repository
// System.setProperty("org.apache.jackrabbit.repository.home", "D:/jackrabbit-repos");
// Repository repository = new TransientRepository();
// http rmi repository
Repository repository = new URLRemoteRepository("http://192.168.1.57:-1/jackrabbit-webapp-1.5-SNAPSHOT/rmi");
// rmi repository
// Repository repository = new RMIRemoteRepository("//localhost/jackrabbit.repository");
Session session = repository.login(new SimpleCredentials("transtep", "".toCharArray()));
try {
String user = session.getUserID();
String name = repository.getDescriptor(Repository.REP_NAME_DESC);
System.out.println("Logged in as " + user + " to a " + name + " repository.");
Workspace workspace = session.getWorkspace();
Node rootNode = session.getRootNode();
// // 儲存資料
workspace.getNamespaceRegistry().registerNamespace("xsignage", "http://www.transtep.com/xsignage/1.0");
Node imageNode = rootNode.addNode("xsignage:image");
imageNode.setProperty("xsignage:type", "圖片");
imageNode.setProperty("xsignage:read", true);
imageNode.setProperty("xsignage:write", true);
Node jpegImage = imageNode.addNode("xsignage:jpeg");
jpegImage.setProperty("xsignage:yuffie", new FileInputStream(new File("./尤菲.jpg")));
session.save();
// 取出資料
Node imageNode2 = rootNode.getNode("xsignage:image");
System.out.println("type: " + imageNode2.getProperty("xsignage:type").getString());
System.out.println("read: " + imageNode2.getProperty("xsignage:read").getString());
System.out.println("write: " + imageNode2.getProperty("xsignage:write").getString());
Node jpegImage2 = imageNode2.getNode("xsignage:jpeg");
InputStream ins = jpegImage2.getProperty("xsignage:yuffie").getStream();
FileOutputStream pos = new FileOutputStream("./yuffie.jpg");
int read = -1;
while ((read = ins.read()) != -1) {
pos.write(read);
}
} finally {
session.logout();
}
}

2008年6月19日 星期四

從servlet上下載檔案的寫法

public void execute(HttpServletRequest req, HttpServletResponse res) {
PrintWriter out = null;
// 取得輸入參數
String did = req.getParameter("did");
String filename = req.getParameter("filename");
if (did == null) {// 無did
out.print("公文文號(did)為空值");
return;
} else if (filename == null) {// 無filename
out.print("檔案名稱(filename)為空值");
return;
}
// Dao
DocAttDao docAttDao = DocAttDao.getInstance();
TblDocattId id = new TblDocattId(Integer.parseInt(did), filename);
TblDocatt tblDocAtt = new TblDocatt(id);
tblDocAtt = (TblDocatt) docAttDao.get(tblDocAtt);
try {
res.setHeader("Pragma", ""); // HTTP 1.0
res.setHeader("Cache-Control", ""); // HTTP 1.1
if (tblDocAtt != null) {
String fileurl = tblDocAtt.getUrl();
String agent = req.getHeader("User-Agent");
if (agent.indexOf("MSIE") > -1) {
// encoding filename for IE
filename = URLEncoder.encode(filename, "utf-8");
} else {
filename = new BCodec().encode(filename);
}
// 下載檔案
res.setContentType("application/octet-stream;charset=utf-8");
res.setHeader("Content-Disposition", "attachment; filename = " + filename);
// 打開指定文件的stream
File file = new File(fileurl);
FileInputStream bis = new FileInputStream(file);
OutputStream bos = res.getOutputStream();
byte[] buff = new byte[1024];
int readCount = 0;
readCount = bis.read(buff);
while (readCount != -1) {
bos.write(buff, 0, readCount);
readCount = bis.read(buff);
}
if (bis != null)
bis.close();
if (bos != null)
bos.close();
} else {
res.getWriter().print("無此檔案");
}
} catch (Exception e) {
e.printStackTrace();
}

}

maven安裝

1.下載maven
2.解壓縮
3.新增M2_HOME環境變數到解壓縮目錄
4.新增M2_HOME\bin 路徑到Path環境變數
5.在console下運行svn --version檢查是否安裝成功

2008年6月18日 星期三

DTO DAO 物件

[轉載]http://www.javaworld.com.tw/jute/post/view?bid=44&id=85388&tpg=1&ppg=1&sty=3&age=0
DTO:Data Transfer Object
DAO:Data Access Object

由名稱來猜,DTO 就是類似用來作資料傳輸的 Java 類別,個人看過的寫法是寫成有 getter/setter 的 JavaBean
透過 DTO 可以很方便地將資料跨 tier 傳遞,且完整封裝

比如:

Servlet 產生 DTO 物件,將 Client 端輸入的資料透過 setter 寫進 DTO,呼叫企業邏輯處理元件時將 DTO 物件當成參數向後端傳遞

而後端的企業邏輯處理元件就可以透過 DTO 的 getter 取出所需要的資料,並進行運算
若後端運算完畢之後必須要將處理結果傳回 Client 端,也是透過 DTO 的 setter 設定新的值,並回傳給 Servlet

這整個過程當中都只需要 DTO 物件一個參數,像坐捷運一樣從前端一路傳到後端
不需要串一堆參數傳來傳去的,若後端須新增參數時也只需要更改 DTO 及用到相關 getter/setter 的程式碼即可,大部分程式都不需要變動


至於 DAO,是跟資料庫存取有關的類別
我看過的做法是將所有操作資料庫的動作都萃取集中起來寫成特定的公用類別
程式中若需要存取資料庫時一律透過 DAO 處理

這樣的好處是,當資料庫更換時,僅需抽換 DAO 即可,其他程式可以繼續使用,可以將應用程式與資料庫的耦合度降低

linux 下使用藍芽傳輸

1.安裝kdebluetooth套件
2.確定相關服務已啟動
sudo /etc/init.d/dbus start
sudo /etc/init.d/bluetooth start
3.啟動kbluetoothd
4.使用kbtobexclient程式傳送資料到手機上

ps.手機 -> pc 尚未試成功

2008年6月13日 星期五

java 的 enum

透過java列舉型別可以很容易的表達一些常數性質的資料
public enum ROLE {
CHANNEL, PLAYLIST, TERMINAL, CONTENT;
};
而使用列舉型別的values()方法可以取出所有的列舉常數陣列
public static void main(String[] args) {
for(ROLE role : ROLE.values()){
System.out.println(role);
}
}
同時列舉型別也可以自定所屬的成員和方法,更可以override toString()方法來自定常數的表示
public enum ROLE {
CHANNEL, PLAYLIST, TERMINAL, CONTENT;
private Integer id;
private String name;

public void setId(Integer id) {
this.id = id;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return name + "(" + id + ")";
}
};

使用列舉型自定的方法:
public static void main(String[] args) {
for(ROLE role : ROLE.values()){
role.setId(4);
role.setName("頻道四號");
System.out.println(role);
}
}

2008年6月2日 星期一

使用URL post XML給server端的servlet

URL urlobj = new URL(servletUrl);
HttpURLConnection urlconn = (HttpURLConnection) urlobj.openConnection();
urlconn.setRequestProperty("Content-Type", "text/xml; charset=UTF-8"); //<--注意編碼設定
urlconn.setDoOutput(true);
urlconn.setDoInput(true);
urlconn.setRequestMethod("POST");
PrintWriter urlpw = new PrintWriter(new OutputStreamWriter(new DataOutputStream(urlconn.getOutputStream()),"UTF-8")); //<--注意編碼設定
JAXBAgent jaxbAgent = new JAXBAgent();
urlpw.print(jaxbAgent.marshal(reqObj));
urlpw.flush();
urlpw.close();
BufferedReader urlbr = new BufferedReader(new InputStreamReader(new DataInputStream(urlconn.getInputStream()),"UTF-8")); //<--注意編碼設定
StringBuffer strbuf = new StringBuffer();
String line = null;
while (null != (line = urlbr.readLine())) {
strbuf.append(line);
}
Object resObj = jaxbAgent.unmarshal(pkgName, strbuf.toString());


//server端的Servlet也要使用
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
//來設定編碼,才不會有中文字亂碼的問題。

2008年5月27日 星期二

ZipException

java.util.zip.ZipException: error in opening zip file
當在java執行時遇到以上的ZipException時,即代表:
有可能在ClassPath下的某一個jar或zip檔是有損壞的,
可能要重新下載lib來進行除錯。

2008年5月23日 星期五

JUnit TestSuite

JUnit只要class有提供public static Test suite()方法即可進行測試
可以建立一個含有suite()的class把所有TestCase歸類在一起,如:
public static Test suite(){
TestSuite suite = new TestSuite("Test the Channel Manage part!");
suite.addTestSuite(TestMediaFactory.class);
suite.addTestSuite(TestSqlDataSource.class);
return suite;
}

也可以建立另一個含有suite()的TestAll class把所有含有suite()的class歸類在一起,如:
public static Test suite(){
TestSuite suite = new TestSuite("Test All media_publish project!");
suite.addTest(TestChannelManageAll.suite());
return suite;
}

2008年5月18日 星期日

Ajith Abraham 教授

第一次聽英文演講(有點晚)
不意外的…完全聽不懂。
主講者:
Ajith Abraham 教授
在挪威教書、議題是-智能計算的最佳化
主要在討論有關模糊理論、類神經網絡、演化計算等人工智慧方面的
著有400篇論文、參與多個期刊及國際會議
感覺是一位在這方面非常權威的人士。
非常值得效仿的人。

網站:
http://www.softcomputing.net/

2008年5月11日 星期日

pietty 亞洲語系修正

使用pietty遠端連線時,如果執行含有UI的程式,
會產生畫面位移的問題(如下圖)
只要修改pietty的亞洲語系修正設定即可
必須將 :
選項 -> 亞洲語系修正 -> Unicode 亞洲寬符號字元
的勾選取消.

2008年5月8日 星期四

[轉載]安裝nvidia官方版驅動

用這個方式裝每次都順利成功:所以不記下來不行

下載適合的nvidia顯示卡驅動程式

離開x
使用rcconf把gdm關掉再重新開機

安裝需要的套件
# aptitude install make gcc

查一下自己應該裝的linux-headers版本
# uname -r
2.6.18-4-686
# aptitude install linux-headers-2.6.18-4

還有其他編譯時必要的套件
# aptitude install pkg-config xserver-xorg-dev

注意事項:
假使您安裝過nvidia-glx請下
# aptitude --purge remove nvidia-glx
並確認移除
/etc/init.d/nvidia-glx
/etc/init.d/nvidia-kernel

到下載的目錄下執行
# sh NVIDIA-Linux-x86-1.0-9639-pkg1.run

重新進入x
$startx
有看到nvidia logo就代表成功

MPlayer字幕設定

1打開Preferences設定頁

2Font Tab下的Font要選擇truetype的字型:如/usr/share/fonts/truetype/arphic/bsmi00lp.ttf

3Font Tab下的Encoding要選擇UTF8,這是指上面的字型檔的編碼,linux下的當然是utf8

4同時,Font Tab下的Text scale是用來調整字幕的大小

5Subtitles & OSD Tab下的encoding要選Big5這是指字幕檔的編碼,從windows的硬碟過來的字幕檔一般都用Big5編碼

2008年5月6日 星期二

JSP 不要快取設定

在JSP產生XML並使用XSL把XML轉換成HTML的情境下,
會造成快取暫留的問題,例如:
A登入 -> A的使用畫面 -> A登出 -> B登入 -> A的使用畫面
這問題的原因不太清楚,但治標的方法是,在JSP加上:

resp.setHeader("Pragma", "no-cache"); // HTTP 1.0
resp.setHeader("Cache-Control", "no-cache"); // HTTP 1.1

來要求browser不要進行快取即可

2008年5月4日 星期日

群組group

Linux下的群組管理非常重要,有些裝置的使用必須要使用者屬於特定的群組。
例如:
cdrom和cdrw需要使用者有cdrom的群組權限,否則無法進行燒錄
音效卡需要使用者有audio的群組權限,否則電腦不會有聲音,就算driver有裝好也一樣
使用usermod指令可以為user設定其所屬的群組
#usermod -G Group[,Group,..] user
但這樣做的話,假如也要把user當前所屬群組重新key一次
不然沒有在-G列表上的群組會把user踢掉
如 user 的當前群組為 G1、G2
#usermod -G G1,G3 user
則user的當前群組變為G1、G3並被從G2踢出
可以改用
#usermod -G G1,G3 -a user
則user不會被G2踢出,但會加入G3
也就是user的當前群組變為G1、G2、G3

2008年4月20日 星期日

ie4linux 新版安裝修正

轉載自:http://twntwn.info/blog/ajer001/archives/1390
現在我們已經進入 IEs4Linux 安裝檔的目錄了,我安裝的版本是 2.99.0,這個版本有一些問題,我們得修改兩個檔案才能繼續安裝。首先我們要修改的是 /lib/messages.txt 檔,我們用文字編輯器開啟它
gedit ./lib/messages.txt
然後將第 19 行從
tw . zhTW TW
改成
zh tw zhTW TW
並存檔。

接著修改 /lib/functions.sh 檔,一樣的我們用文字編輯器開啟它
gedit ./lib/functions.sh
然後將第 98 行從
pid=$(wget -q -b -t 1 -T 5 -U "$useragent" -o /dev/null $URL $WGETFLAGS -O "$file" | sed -e 's/[^0-9]//g')
改成
pid=$(LANG=C wget -q -b -t 1 -T 5 -U "$useragent" -o /dev/null $URL $WGETFLAGS -O "$file" | sed -e 's/[^0-9]//g')
並存檔。

修改完畢,我們可以繼續安裝了。只要下這道指令就行囉~
./ies4linux
祝各位順利!

2008年4月16日 星期三

Hibernate 物件周期

轉載自:http://caterpillar.onlyfun.net/Gossip/HibernateGossip/EntityObjectLifeCycle.html

Hibernate中的實體物件可以分為四種狀態:Transient、 Persistent、DetachedRemoved
  • Transient
當您直接使用new創建出物件,例如在之前的例子中, User類別所衍生出之物件,在還沒有使用save()之前都是Transient物件,這些物件還沒有與資料庫發生任何的關係,不對應於資料庫中的任一筆資料。

  • Persistent
當物件與資料庫中的資料有對應關係,並且與Session 實例有關聯而Session 實例尚未關閉(close),則它是在Persistent狀態,具體而言,如果您將Transient狀態的物件使用Session的save()方法 加以儲存,或是使用Hibernate從資料庫載入資料並封裝為物件(例如使用get()、load()等查詢物件的相關方法),則該物件為Persistent狀態。

Persistent狀態的物件對應於資料庫中的一筆資料,物件的id值與資料的主鍵值相同,並且Session實例尚未失效,在這期間您對物件的任何狀 態變動,在Session實例關閉(close)或Transaction實例執行commit()之後,資料庫中對應的資料也會跟著更新。

如果您將Session實例關閉(close),則Persistent狀態的物件會成為Detached狀態。

如果您使用Session的實例delete()方法刪除資料,Persistent狀態的物件由於失去了對應的資料,則它會成為Transient狀 態。
  • Detached
Detached狀態的物件,其id與資料庫的主鍵值對 應,但脫離Session實例 的管理,例如在使用load()方法查詢到資料並封裝為物件之後,將Session實例關閉,則物件由Persistent狀態變為Detached狀 態,Detached狀態的物件之任何屬性變動,不會對資料庫中的資料造成任何的影響。

Detached狀態的物件可以使用update()方法使之與資料庫中的對應資料再度發生關聯,此時Detached狀態的物件會變為 Persistent狀態。

Detached物件,若不再被任何名稱參考,則在適當的時候將被垃圾收集所回收。

  • Removed
如果您使用Session的實例delete()或remove()方法刪除資料,Persistent狀態的物件由於失去了對應的資料,則它會成為Removed狀 態,一個成為Removed狀態的物件不應該被繼續重用,您應該釋放任何參考至它的名稱,讓該物件在適當的時候被垃圾回收。

簡單的說,Transient與Detached狀態的物件未受Hibernate持久層管理員管理,對這兩個狀態的物件作任何屬性變動,不會對資料庫中 的資料有任何的影響,而Persistent狀態的物件受Hibernate持久層管理,對物件的屬性變動,在Session實例關閉(close)或 Transaction實例執行commit()之後,資料庫中對應的資料也會跟著更新。

Transient與Detached狀態的物件是非管 理狀態,而Persistent狀態的物件是管 理狀態, 又稱為Persistent Object,其與一個Persistence Context 關聯。

在物件為Persistent時,如果物件的屬性發生變化,並且尚未提交之前,物件所攜帶的資料稱之為Dirty Data,Hibernate會在Persistence Context維護物件的最近讀取版本,並在資料提交時檢查兩個版本的屬性是否有變化,如果有的話,則將資料庫中的資料進行更 新


flag 設計

使用 flag 來進行判斷程式的狀態時
flag 應該是 1、2、4、…、2^n
且不可以使用 0
因為:
1.當x要加入flag時,用的運算是x or 該flag,而 0 or 任何數 都不會有作用。
2.當x要移除flag時,用的運算是x and 該flag的補數,0的補數是1111…111,進行and也不會有作用
3.當x要判斷flag是否存在時,用的運算是x and該flag是否會等於該flag,而0 and任何數均為 0也無法判斷。

2008年4月11日 星期五

debian 網路修復

debian linux 下常用的網路修復指令
重啟網路卡:
#ifconfig eth0 down && ifconfig eth0 up
重啟網路服務
#/etc/init.d/networking restart
重新由dhcp取得ip
#dhclient
重新ADSL連線
#pppoeconf

2008年4月10日 星期四

subversion

安裝與設定:
在debian上使用svn只要安裝subversion套件
並建立svn group
把所有想要使用svn的帳號(user)均加入到svn group下
使用svnadmin create 指令在想要的路徑下建立svn的repository檔案庫
並以chgrp把檔案庫的擁有者群組設為svn
之後即可在遠端使用svn+ssh://user@host/path_to_repository來使用檔案庫

備份的方法:
另外加裝subversion-tools套件
並使用svn-hot-backup some_repos/ backup_path/
即可備份檔案庫

2008年4月3日 星期四

jetty WebAppDeployer

jetty 的WebAppDeployer可以指定一個特定的目錄,
做為佈署webapp的位置,
webapp 可以是一整個含有jsp、servlet、web.xml的資料夾,
也可以是一個.war的包裝檔,
jetty啟動時會去指定的 scan 一但,找到war file或webapp,
就會將他註冊到server的ContextHandlerCollection下,
jetty.xml的設定如下
<Configure class="org.mortbay.jetty.Server" id="server">
<!-- Deployer 設定 -->
<Call name="addLifeCycle">
<Arg>
<New class="org.mortbay.jetty.deployer.WebAppDeployer">
<Set name="contexts"><Ref id="contexts"/></Set>
<Set name="webAppDir">./deployer</Set>
<Set name="parentLoaderPriority">false</Set>
<Set name="extract">true</Set>
<Set name="allowDuplicates">false</Set>
</New>
</Arg>
</Call>
</Configure>

其中的./deployer是Deployer在啟動時會去scan的佈署目錄
而contexts則是server.setHandlers(new Handler[]{contexts , new DefaultHandler()})中的
ContextHandlerCollection物件。HandlerList也是ContextHandlerCollection其中一個子類別

2008年4月2日 星期三

linux上的防火牆 iptables

iptables 的簡圖 (from 鳥哥)
iptables防火牆的概念是:
當封包送來時,iptables會根據事先定義好的table,
一條一條規則逐一比對,如果符合其中一條,
就允許進入主機,否則就進行下一條規則的比對,
一但所有規則都不符合,則會進行預設動作,
預設動作也稱為Policy,一般有下列幾種:
接受 (ACCEPT) 、
丟棄 (DROP) 、
轉送 (FORWARD)









iptables 的簡圖 (from 鳥哥),
iptables的規則都記錄在tables裡,
常用的有兩個表格,filter及nat。

filter主要是設定有關進出本機的封包:
由 filter.INPUT 規則鍊限制進入本機的封包;
由 filter.OUTPUT 規則鍊限制送出本機的封包。

nat主要是設定要進出本機後端的主機的封包
當本機要做為防火牆主機時才有用到
nat.PREROUTING 規則鍊處理 路由前的封包
nat.POSTROUTING 規則鍊處理路由後的封包

iptables 指令用法:

iptables -L -n 顯示filter規則鍊下的所有規則
iptables -L -n -t nat 顯示nat規則鍊下的所有規則

iptables -P INPUT DROP 設定fliter.INPUT 規則鍊的預設動作為 DROP (丟棄)
iptables -t nat -P INPUT ACCEPT 設定nat.INPUT 規則鍊的預設動作為 ACCEPT (接受)

iptables -A INPUT -i lo -j ACCEPT filter.INPUT加入規則,所有來自lo的封包均接受

iptables -A INPUT -i eth0 -s 192.168.0.9 -j DROP eth0收到的所有來自192.168.0.9的封包均丟棄

iptables -I OUTPUT -d 140.126.21.0/24 -j DROP本機所有要送往140.126.21.*網域的封包均丟棄

2008年3月30日 星期日

javac 參數

javac -d somedir/ some.java是指定class的輸出目錄
javac -cp .:dir:anotherdir some.java 指定classpath
javac *.java 一次編譯所有java檔

2008年3月27日 星期四

java 的 DateFormat

//解析輸入日期 (轉換 MM/dd/yyyy 成 yyyy-MM-dd)
DateFormat formatIn = new SimpleDateFormat("MM/dd/yyyy");
DateFormat formatOut = new SimpleDateFormat("yyyy-MM-dd");
Date datefrom = formatIn.parse(from);
Date dateend = formatIn.parse(end);
formatedfrom = formatOut.format(datefrom);
formatedend = formatOut.format(dateend);

2008年3月24日 星期一

html input 空字串問題

html中的from使用的input元素
<input name="in" type="text">
如果沒有輸入任何值的話,submit後
由jsp的out.getParameter("in")取到的值,
將會是"" <-空字串,而不是null。
寫jsp時,需特別注意。

2008年3月17日 星期一

使tomcat完全支援中文

只要在/var/lib/tomcat5.5/conf/server.xml
下的Connector tag加上一個屬性,URIEncoding="UTF8"
即可,
例如:
<Connector port="8180" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8"/>

JSPWiki經由這個設定,即可使用中文做為文件名稱而不會顯示成亂碼。

2008年3月14日 星期五

jsp輸出xml

假如想要以jsp輸出xml到browser,如:
1 <%
2 out.println("<?xml version=\"1.0\"?>");
3 out.println("<test>");
4 out.println("abcd");
5 out.println("</test>");
6 %>
這樣還不夠,只會顯示abcd
還必須加上
7 <%@page contentType="application/xml" %>
讓browser知道這是一個xml而不是jsp

JspWiki設定

jspwiki的安裝在tomcat下的webapp完成後
就需要進行一些設定
主要的是WEB-INF/jspwiki.properties用來設定資料存放位置
及WEB-INF/jspwiki.policy用來設定用戶權限

2008年3月13日 星期四

log4j

在java程式裡如果log4j的設定檔log4j.properties
沒有放在程式的ClassPath下
則log4j會產生Warring

要指定log4j的設定檔位置 (假設放在java執行目錄下的conf/log4j.properties)
只要在程式開始處加入
PropertyConfigurator.configure("conf/log4j.properties");
即可。

2008年3月7日 星期五

hwclock

如果#hwclock -w 出現以下錯誤
select() to /dev/rtc to wait for clock tick timed out
可以試試看使用 --directisa參數
#hwclock -w --directisa來進行寫入時間到BIOS的動作

同樣的,要看看BIOS上的時間為何,只要下
#hwclock -r --directisa即可

JSPWiki in Debian 安裝記實

首先:
到http://www.jspwiki.org/下載JSPWiki
我的版本是JSPWiki-2.6.1-bin.zip
再來以aptitude安裝tomcat5.5套件
ps.非tomcat5而是tomcat5.5

修改tomcat5.5啟動配置檔
sudo vim /etc/default/tomcat5.5
設定
JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun
TOMCATS_SECURITY=no

然後:
解壓縮JSPWiki-2.6.1-bin.zip
7z x JSPWiki-2.6.1-bin.zip
就會產生JSPWiki/資料夾

建立/home/muchu1983/public_html/wikidata/的資料夾
並將JSPWiki/JSPWiki-corepages.zip copy到wikidata/資料夾下
解壓縮JSPWiki-corepages.zip
7z x JSPWiki-corepages.zip
更改wikidata/的權限
sudo chown tomcat55 wikidata -R
sudo chgrp nogroup wikidata -R

也將JSPWiki/JSPWiki.war copy到tomcat webapps下
sudo cp JSPWiki/JSPWiki.war /var/lib/tomcat5.5/webapps/
過一下子tomcat會自動將JSPWiki.war解壓,產生webapps/JSPWiki/資料夾
編輯webapps/JSPWiki/WEB-INF/jspwiki.properties檔案
更改以下幾行
jspwiki.pageProvider =VersioningFileProvider
jspwiki.fileSystemProvider.pageDir =/home/muchu1983/public_html/wikidata
jspwiki.basicAttachmentProvider.storageDir =/home/muchu1983/public_html/wikidata
儲存

以browser連到http://localhost:8180/JSPWiki/Install.jsp
直接按下Configure按鈕進行設定,
之後會亂數產生admin帳號的預設密碼,copy密碼
再連到http://localhost:8180/JSPWiki/就可以admin登入

2008年3月6日 星期四

jetty的request/response

jetty自己實做了request及response物件
來進行jsp/servlet的運作,
但jetty的handle方法是將request/response
以標準的HttpServletRequest/HttpServletResponse傳進來
所以如果要使用jetty新增或加強的功能就要做降轉(down cast)的動作:
Request base_request = request instanceof Request?(Request)request:HttpConnection.getCurrentConnection().getRequest();
Response base_request = response instanceof Response?(Response)request:HttpConnection.getCurrentConnection().getResponse();

例如:如果handler要阻止request繼續往下一個hadler傳輸,則可以handle方法加上
Request base_request = (httprequest instanceof Request) ? (Request)httprequest:HttpConnection.getCurrentConnection().getRequest();
base_request.setHandled(true);

WEB-INF\classes

寫jsp的webapp時
如果所寫的jsp有用到自定的class或是servlet
要放在webroot/WEB-INF/classes資料夾內
並且要依據class的package放好
則jetty會自動的把WEB-INF\classes設為classpath

2008年3月5日 星期三

tomcat in Debian

在debian上安裝好tomcate5套件後
使用http://localhost:8180/進行連線
有別於以往大多數平台上是以8080 port來連線

2008年3月2日 星期日

getPackage()

this.getClass().getPackage()
這個方法會呼叫到class的所屬ClassLoader之getPackage(String name)
而如果ClassLoader是特殊客製的,必須要記得在實作defineClass()這個方法時,
適時的呼叫definePackage(pkgname,null,null,null,.....);這個方法
ClassLoader本身有維護一個HashMap
definePackae()會以對應的pkgname產生一個Packae物件實例,存入這一個HashMap
如此一來客製的ClassLoader的getPackage(String name)方法才會正確運作,
否則只會傳回null。

debian下的pdf reader

以aptitude找尋
套件名稱叫acroread

如果從官方網頁上下載xxx.deb下來的話

dpkg -i xxx.deb
來安裝。

2008年3月1日 星期六

Linux 的網路校時

台灣的ntp server列表
##########ntpserver#############
time.stdtime.gov.tw
clock.stdtime.gov.tw
tick.stdtime.gov.tw
tock.stdtime.gov.tw
watch.stdtime.gov.tw
##########ntpserver#############
先安裝ntpdate這一支程式
#ntpdate [ntpserver]
再寫入bios
#hwclock -w
即可完成校時

2008年2月29日 星期五

MPlayer縮放問題

在debian下使用MPlayer時如果顯示全螢幕
會有畫面邊框變大,但實際畫面還是很小的問題。
可以在~/.mplayer/config這個檔案下加入以下這一行:
zoom=true
即可正常縮放

2008年2月27日 星期三

classloader

java的classloader繼承自ClassLoader類別
classloader都會有一個parent的classloader
如果在new的時後沒有指定parent ()以super(parentClassloader)
會自動得以new該classloader的類別的所屬的Classloader做為parent
例:
AppClassLoader -> load -> ParentClass -> new ChildClassLoader()
假如ChildClassLoader的建構子沒有super(someOtherClassloader);
則ChildClassLoader的parent就是AppClassLoader(load ParentClass的classloader)

classloader在loadclass之前會先使用parent來loadclass
都找不到才會自己load
loadclass步驟會先使用findclass(),有找到再使用defineclass()

/********java.lang.ClassLoader()方法**********/
protected synchronized Class loadClass
(String name, boolean resolve)
throws ClassNotFoundException{

// First check if the class is already loaded
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then invoke
// findClass to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
/********java.lang.ClassLoader()方法**********/

假如自訂的ClassLoader沒有繼承getResourceAsStream()
取得resource會取不到,得到null

2008年2月23日 星期六

sudo 應用

sudo工具平常的用法:
sudo command
但是這樣只能執行一筆指令
可以搭配su指令來使用,也就是:
sudo su -
這樣可以切換為root,看來和直接執行su沒有不同
重點是.....
使用sudo su來切換,使用的密碼是原帳戶的密碼,
可以保護root密碼不外洩。

最後面的 - 符號其實是su的參數,等同於su -l或su --login
意思是,切換身份後同時也配合新身份改變執行環境配置 (例如$PATH)
就有如以新身份重新登入一樣。
加上這個參數可以避免掉一些環境不同步的問題。

2008年2月19日 星期二

vnc

vnc軟體有許多個分支
無論安裝了哪一個vnc軟體
debian圴會自動把
vncserver 鍊結到所安裝的vnc軟體的server程式
vncviewer 鍊結到所安裝的vnc軟體的client程式

以tightvnc/debian為例:
要安裝tightvncserver、tightvncviewer,
如果要增加以browser java applet來連線的話
要多裝tightvnc-java套件,並在vncserver啟動時指定-httpport參數。

而且vncserver啟動時會執行$HOME/.vnc/xstartup這一個shell script

以xfce為桌面(wm)的主機上
原本的xstartup設定無法以vncviewer成功啟動xfce
必須修改為以下3行
#######xstartup#######
#!/bin/sh
unset SESSION_MANAGER
startxfce4 &
########################
並且要記得chmod a+x xstartup

2008年2月17日 星期日

browser 的 java plugin

在debian下的iceweasel/mozilla 瀏覽器
如果要看applet的話,
除了安裝sun-java5-jdk之外
還要加裝sun-java5-plugin

2008年2月16日 星期六

debian 的 update-alternatives

sudo update-alternatives可以進行/etc/alternatives下
之鍊結目標的修改
例如同時裝了多個jvm在一台主機上時
執行java其實會執行/etc/alternatives/java (soft link)
透過對/etc/alternatives/java的修改可以改變執行的jvm
例:
sudo update-alternatives --list command 列出command有哪幾個鍊結可選擇
sudo update-alternatives --config command 改變command的鍊結
sudo update-alternatives --all 一次設定全部的command

2008年2月15日 星期五

JAXB and JDK

JAXB使用上遇到的問題 後續~~~

在jdk1.6上使用jaxb2.1的lib會有問題。
建議為jdk1.5 + jaxb2.1

eclipse的jvm不能指定jre的資料夾
要指定jdk的資料夾,否則,無法在eclipse下進行javac的功能
如:ant compile

2008年2月13日 星期三

hibernate tools過瀘

eclipse hibernate tools plugin的Code Gernation如果沒有設定
會取出.cfg.xml指定的資料庫下的所有table
可以透過hibernate.reveng.xml這個設定檔來進行過瀘
eclipse hibernate tools plugin也有提供產生hibernate.reveng.xml的精靈

2008年2月11日 星期一

XDNA-5.2

快速開發XDNA-5.2專案筆記 假如build.xml初始化為5200 有f的選項也許可以省略
http://xsquare.transtep.com/~david/eclipse
build.xml 5119 > 5200 f
[root]ant clean-all sample init f
reconfigure build path f
remove server/service/xdna_default_modules-5.1 f
use conf/*.sample replace conf/* (client/initial/* too) f
client/conf/system.ini CONST_HTTP > HTTP
server/conf/system.ini XDNA_DB use h2 ; duty use postgreSQL
client/initial/UPGRADE_SERVER_DB_SCRIPT.SQL create table dutyrecord
create .xsd
use XJC turn .xsd to .java (common/src)
create hibernate.cfg.xml (for duty database)
run server once to create database
use hibernate tools turn table to .java (server/src)
[問題] license 過期 不可在 root 下 ant sample f
write service module
write definition.xml
write client MVC
write package.properties
[root]compile dist (server/service/Demo.default)
run server/client

ps. [root]ant init 可產生 server/service/xdna_default_modules-5.2

2008年2月9日 星期六

linux 下聽廣播

http://jason.onweb.idv.tw/radio.asp
下的廣播鍊結均為mms://類型的鍊結
可以簡單的以mplayer來進行播放

如:
mplayer mms://url_of_radio &

即可

2008年2月2日 星期六

eclipse - xml schema editor 安裝

在eclipse 3.3之後eclipse分為五種package
java 、 jee 、 c/c++ 、 rcp/plugin 、 classic
可供下載,這些package之間不同是預設所提供的 plugin不同
其中以 classic 的最精簡;而 jee 的最完整。
eclipse官方下載頁有他們之間的比較圖

classic版和3.2.x的eclipse一樣沒有提供一個好用的 xml schema editor
該editor是屬於wst特性下的,所以可以勾選...

help -> software updates -> find and install -> search for new features to install ->
-> XXX discovery site -> web and j2ee development -> web standard tools

並點選右方的select required 來一併選擇與wst特性相依的特性 即可安裝

2008年2月1日 星期五

linux 下的 youtube 下載器

http://www.arrakis.es/~rggi3/youtube-dl/
youtube-dl 是一支python程式
先chmod a+x
再放到/usr/local/bin下
用法 youtube-dl [option] url_of_video
安靜地在背景下載:
youtube-dl -q url_of_video &

另外
ctrl-z 可暫停目前job並放到背景下
bg %1 可在背景下啟動暫停的程式 1為jobs所定的編號
fg %1 可把肩景程式移到前景來

2008年1月29日 星期二

JSP 多餘的斷行 錯誤

一個初學者較常犯但不容易檢查出的錯誤可能是「多餘的斷行」,例如:
  • errorDemo.jsp
 <%@page contentType="charset=Big5"
errorPage="errorHandler.jsp"%>
<%
throw new Exception("這是一個假裝的錯誤,純綷丟出例外");
%>
//←(斷行)

這個JSP程式乍看之下沒有錯誤,程式只是丟出一個例外而已,但注意到它最底下空了一行,在轉換為Servlet之後,這一行會實際轉換為 out.write('\r');,而在這行之前,由於直接丟出了一個例外,換句話說,out.write('\r');這行永遠不會被執行到,這個邏輯 錯誤,編譯器是可以檢查的出的,因而錯誤頁面會回報"unreachable statement",改正這個錯誤的方式,是將JSP頁面中多餘的斷行刪掉。

debian 重灌步驟

1.安裝及設置sudo
2./etc/apt/source.list 加入contrib non-free
3./etc/apt/source.list 加入 debian-multimedia 及 gcin 官方載點
4.安裝k7版linux-image
5.安裝nvidia官方driver
6.下載alsa driver 並 ./configure;make;sudo make install
7.sudo alsaconf
8.安裝bzip2 、 unrar
9.移動noseeing.gtab 到 /usr/share/gcin/table
10.安裝flashplugin-nonfree
11.安裝w32codecs 、 mplayer
12.安裝openssh-server 、 no-ip
13.下載安裝光碟iso檔 並設定fstab自動掛載到/media/cdrom0
14.安裝 jdk 、 eclipse
15.安裝gaim
16.copy stardict的字典到/usr/share/stardict/dic下並解開
17.設定gaim stardict 自動啟動

以上有點按又有點不按順序~^^

2008年1月28日 星期一

Jetty 6 handler 階層

1.root 是server

server -> HandlerCollection -> ContextHandlerCollection (pathmap) -> ContextHandler
而如果ContextHandler是屬於WebAppContext的話。其下包含了一連串的handler
WebAppContext -> SessionHandler -> SecurityHandler -> ServletHandler

原文:

  1. The Server delegates the request to the its configured handler, which is normally an instance of HandlerCollection.
    Server分派request給屬於server的handler,這常常是一個HandlerCollection的實例。

  2. The HandlerCollection acts like Jetty 5, and calls each of it's contained handlers in turn. Typically it is configured with
    a ContextHandlerCollection, a DefaultHandler and a RequestLogHandler. This allows a request to be handled by a context or the default handler, and then be passed to the request log handler.
    HandlerCollection會依序呼叫其下的每一個Handler,慣例上,其下會有ContextHandlerCollection,DefaultHandler,RequestHandler.

  3. The ContextHandlerCollection
    maintains a map of context path to lists of ContextHandlers. For a given request, each the URI is used to find matching context paths, and each is called in turn until the request is handled.
    ContextHandlerCollection維護一個path的map,根據request的URI mapping到其下對應的ContextHandler

  4. If the ContextHandler accepts a request (it may reject it due to virtual hosts), it will delegate the request to a nested handler and for the duration of that call it will set:
    • the request context path
    • the current thread context classloader
    • the resource base
    • the error handler
    • context attributes and init parameters.
  5. Typically the ContextHandler will be an instance of WebAppContext and will thus contain a nested chain of SessionHandler, SecurityHandler and ServletHandler. The request is delegated to the first handler in this chain, a SessionHandler
  6. The SessionHandler will examine the request for any session ID to be activated and will activate the mechanism for creating new sessions before delegating the request to the SecurityHandler.
  7. The SecurityHandler will check any constraints and authentication before delegating the request to the ServletHandler
  8. The ServletHandler implements the dispatch to Filters and Servlets to handle the request according to the servlet specification.
簡單範例程式
public static void main(String[] args) {
Server service = new Server();
// connector
Connector selconnector = new SelectChannelConnector();
selconnector.setPort(80);
service.setConnectors(new Connector[] { selconnector });
// thread pool
BoundedThreadPool pool = new BoundedThreadPool();
pool.setMinThreads(10);
pool.setMaxThreads(100);
service.setThreadPool(pool);
// handler collection
HandlerList handlerlist = new HandlerList();
service.setHandlers(new Handler[] { handlerlist, new DefaultHandler(), new RequestLogHandler() });
// static resource handler
ContextHandler resContext = new ContextHandler(handlerlist, "/html");
ResourceHandler reshandler = new ResourceHandler();
reshandler.setResourceBase("./html/");
resContext.setHandler(reshandler);
// dynamic resource handler
WebAppContext webappcontext = new WebAppContext(handlerlist, "./webapp/", "/webapp");

try {
service.join();
service.start();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}

debian kernel 1G以上ram支援

debaian預設安裝linux-image-`uname -r`-486
僅支援1G的ram,free -mt 可以看到只有約800mb

如要支援1G以上的ram,不需另外compile kernel
只要安裝專用的linux-image

linux-image-`uname -r`-k7
-> (amd處理器專用image)

linux-image-`uname -r`-686
-> (Intel處理器專用image)

kde 自動啟動設置

在~/.kde/AutoStart 資料夾下加入連結即可

cd ~/.kde/AutoStart
ln -s /usr/bin/gaim gaim

2008年1月21日 星期一

pietty 亂碼問題

遠端使用pietty 執行aptitude時的亂碼問題。
1.將pietty的編碼改為UTF-8
2.將pietty的字型改為fixedsys

SCTP

由於碩士學分班的報告需要,第一次接觸到了SCTP這一個協定。
http://dtim.mis.hfu.edu.tw/2006/paper/PAPER_A/140A.pdf
SCTP 主要的貢獻是對多重聯外線路的支持,一個端點可以由多於一個IP組成