2009年10月29日 星期四

ivy 新增 maven repository 以外的 repository

先在 build.xml 所在目錄下加入 ivysettings.xml 覆寫掉 ivy.jar 裡預設的 ivysettings.xml
僅修改 main-chain 部分內容如下:
<?xml version="1.0" encoding="utf-8"?>
<ivysettings>
<settings defaultResolver="default"/>
<include url="${ivy.default.settings.dir}/ivysettings-public.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-shared.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-local.xml"/>
<include url="ivysettings-main-chain.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-default-chain.xml"/>
</ivysettings>
${ivy.default.settings.dir}的位置就是 ivy.jar 裡的 org.apache.ivy.core.settings package
修改後改為指到 build.xml 所在目錄下的 ivysettings-main-chain.xml
新增 ivysettings-main-chain.xml 其內容如下:
<?xml version="1.0" encoding="utf-8"?>
<ivysettings>
<resolvers>
<url name="com.springsource.repository.bundles.release">
<ivy pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
<artifact pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>
<url name="com.springsource.repository.bundles.external">
<ivy pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
<artifact pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>
<chain name="main" dual="true">
<resolver ref="shared"/>
<resolver ref="public"/>
<resolver ref="com.springsource.repository.bundles.release"/>
<resolver ref="com.springsource.repository.bundles.external"/>
</chain>
</resolvers>
</ivysettings>

這裡新增的public和shared resolver 是原本ivy.jar就預設定義的,而新增的兩個 url resolver是 spring 的 SpringSource Enterprise Bundle Repository

安裝 ivy - 類似 maven 的 java 函式庫管理工具

下載 ivy 後將 ivy-x.x.x.jar 放到 ant 的 lib 目錄下…如:
/usr/share/ant/lib/ivy-2.1.0.jar
即可在 ant 的 build.xml 裡使用 ivy 的 tag
並且編寫 ivy.xml 定義所用到的函式庫,放在 build.xml 檔案的同目錄下。

2009年10月27日 星期二

META-INF/MANIFEST.MF 的最後一行注意事項

要多加一行空白行(多按一次Enter),否則最後一行的參數將無法被 jar 讀到。
如:
========= MANIFEST.MF 開始 ==========
Manifest-Version: 1.0
Bundle-Name: Service listener example
Bundle-Description: A bundle that displays messages at startup and when service events occur
Bundle-Vendor: Apache Felix
Bundle-Version: 1.0.0
Bundle-Activator: tw.bennu.tutorial.example.Activator
Import-Package: org.osgi.framework (<===最後一行參數)

========= MANIFEST.MF 結束 ==========

2009年10月23日 星期五

以 mutt 結合 msmtp 透過遠端 MTA 幫忙發信

mutt 是 linux 下常見預設安裝好的文字模式 mail client
但是,本身預設不但不包含 pop3、smtp 功能,甚至連郵件編輯器也是委拖其他軟體
同樣的我們可以安裝 msmtp ,並讓 mutt 委拖 smtp 功能給 msmtp 就可以寄信了。
安裝 msmtp
sudo aptitude install msmtp

在家目錄下建立 ~/.msmtprc 內容:
# Example for a user configuration file
# Set default values for all following accounts.
defaults
tls on #Gmail TLS有打開
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile ~/.msmtp.log

# A freemail service
account gmail
host smtp.gmail.com
from yourid@gmail.com
auth on #Gmail SMTP要認證
user yourid #gmail 帳號
password secret #gmail 密碼,明碼,記得chmod 600本檔案
account default : gmail

在家目錄下建立 ~/.muttrc 內容
set sendmail="/usr/bin/msmtp"
set from=yourid@yourdomain.com #gmail SMTP會覆寫

2009年10月22日 星期四

ssh disable 掉 password 登入

注意!進行此動作前需先確定可以透過 ssh-key 登入,
否則…主機最好別放太遠.....

編輯 /etc/ssh/ssh_config 檔
sudo vim /etc/ssh/ssh_config
設定以下三行為 no
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
重新 reload ssh 服務
sudo /etc/init.d/ssh reload

測試,先將私錀改名
mv ~/.ssh/id_rsa ~/.ssh/id_rsa.backup
以 ssh 登入如果出現以下訊息表示ok (不再要求輸入密碼):
“Permission denied (publickey).”
成功後再把私錀改回來
mv ~/.ssh/id_rsa.backup ~/.ssh/id_rsa

以 ssh-key 代替密碼登入遠端機器

muchu@glory:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/muchu/.ssh/id_rsa): /home/muchu/id_rsa
Enter passphrase (empty for no passphrase): #直接按 enter
Enter same passphrase again: #直接按 enter
Your identification has been saved in /home/muchu/id_rsa.
Your public key has been saved in /home/muchu/id_rsa.pub.
The key fingerprint is:
21:02:7e:b1:7d:11:85:26:e7:4b:16:ae:39:d5:79:ed muchu@glory
The key's randomart image is:
+--[ RSA 2048]----+
| . . o+. |
| . . +. =. |
| . + o*oo . . |
| . . o*.o . . |
| *S. . . |
| + . E |
| . |
| |
| |
+-----------------+
muchu@glory:~$ ls /home/muchu | grep id_rsa
id_rsa id_rsa.pub

id_rsa 是私錀,id_rsa.pub 是公錀。
將 "公錀的內容" 附加在 "對方" 主機的 ~/.ssh/authorized_keys 下。
並將私錀以 id_rsa 的名稱放在 ~/.ssh/ 下。就可以不用密碼 ssh 登入 "對方" 主機。

在 debian 系統,放公錀到對方主機的動作可以透過以下命令完成,先將公錀放在 ~/.ssh/ 下
ssh-copy-id muchu@www

2009年10月19日 星期一

trac 重新同步 svn

如果在 trac 已經指定了某個 svn repository 的環境下,
重新建立 svn repository 導致 repositoy 版本變動,如:
將 rev 101 僅 dump 出第 101 版本,並放棄第 1~100 版。
重新建立 reposiotry load 101 版為新 repository 的第 1 版。
這時連到原本指定 repository 的 trac 時會看到以下的錯誤訊息:

Can't synchronize with the repository

執行以下命令重新進行 trac 與 svn 的同步即可解決:

trac-admin </path/to/projenv> resync

2009年10月12日 星期一

trac 備份及還原

備份
trac-admin /usr/local/trac/wiki hotcopy ~/backup/wiki
還原
cp 回去即可

apache2 + svn + trac 設置

一、apache2 + svn
#安裝 svn apache2 及 apache2-svn 模組
apt-get install apache2 subversion libapache2-svn
#建立 svn 目錄
mkdir -p /usr/local/svn
#建立 repos svn倉庫
svnadmin /usr/local/svn/repos
#改變 repos 存取權限
chown -R www-data /usr/local/svn/repos
#設定 apache dav_svn 模組
vim /etc/apache2/mods-available/dav_svn.conf
#修改為
<Location /svn>
DAV svn
SVNPath /usr/local/svn/repos
AuthType Basic
AuthName "Subversion repos"
AuthUserFile /etc/apache2/dav_svn.passwd
AuthzSVNAccessFile /etc/apache2/dav_svn.authz
#<LimitExcept GET PROPFIND OPTIONS REPORT>
Require valid-user
#</LimitExcept>
</Location>
#建立 dav_svn.authz 設定帳號讀寫權限
vim /etc/apache2/dav_svn.authz
#修改為 :設定 "/" = /repos 下的資料除了 muchu 帳號可以讀寫,其他帳號均不可讀寫。
[/]
* =
muchu = rw
#建立 dav_svn.passwd 設定帳號密碼 (如果檔案已存在就不需要 -c)
/usr/bin/htpasswd -c /etc/apache2/dav_svn.passwd muchu
#重新啟動 apache2
/etc/init.d/apache2 restart
#以 http co svn
svn co http://www.bennu.tw/svn

二、trac
#安裝 trac 及 mod_python 模組
apt-get install trac libapache2-mod-python
#建立 trac 根目錄
mkdir -p /usr/local/trac
#初始化 trac
trac-admin /usr/local/trac/wiki initenv
#Project Name 指定為
wiki
#Path to Repository 指定為
/usr/local/svn/repos
#設定 trac.ini
vim /usr/local/trac/wiki/conf/trac.ini
#修改 default_charset 編碼
default_charset = utf-8
#修改存取權限
chown www-data.www-data -R /usr/local/trac/wiki
# standalone 執行測試
sudo -u www-data tracd --port 8000 /usr/local/trac/wiki
存取 http://127.0.0.1:8000/ 檢查是否正常運作
#建立 apache2 Virtual Host
vim /etc/apache2/sites-available/trac
#修改為:
<VirtualHost *:80>
ServerName trac.bennu.tw
ServerAdmin muchu@trac.bennu.tw

DocumentRoot /usr/local/trac

ErrorLog /var/log/apache2/trac-error.log
CustomLog /var/log/apache2/trac-access.log combined

SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonOption TracEnv "/usr/local/trac/wiki"
PythonOption TracUriRoot "/trac/wiki"
<LocationMatch "/trac/[^/]+/login">
AuthType Basic
AuthName "trac"
AuthUserFile /etc/apache2/dav_svn.passwd
Require valid-user
</LocationMatch>
</VirtualHost>
#啟動 trac Virtual Site
sudo a2ensite trac
#重啟 apache2
/etc/init.d/apache2 restart
#新增 trac.bennu.tw domain
trac CNAME www.bennu.tw.
#存取 http://trac.bennu.tw/trac/wiki
並可以 svn 使用的 muchu 帳號登入

2009年10月2日 星期五

python 的第三方模組安裝 (windows)

直接將第三方的模組:如 eazygui.py 放到 C:\Python26\Lib\site-packages 下即可。

2009年10月1日 星期四

python 學習資料小集

Python 教學文件
http://www.python.tw/ebook/Guido%20van%20Rossum/tut.html
Python 學習手冊
http://www.oreilly.com.tw/product2_c.php?id=a240
易記學
http://ez2learn.com/index.php/python-tutorials
pydoing
http://pydoing.blogspot.com/
官方 module index
http://docs.python.org/modindex.html

2009年8月28日 星期五

java JVM 增大記憶體配置參數 -X 與 -XX

java OOM 分為兩種:

java.lang.OutOfMemoryError: PermGen space
表示 stack 空間不夠,可能是 static 變數太多,或 class 太多。

java.lang.OutOfMemoryError: Java heap space
表示 heap 空間不夠,可能是建立的物件太多,或是處理資料檔案太大。

-Xms<size> : 初始的記憶體大小 (heap)
-Xmx<size> : 最大的記憶體大小 (heap)
-XX:MaxNewSize=<size> : 初始的記憶體大小 (stack)
-XX:MaxPermSize=<size> :最大的記憶體大小 (stack)
-Xincgc = 讓gc在背景持續執行

例:
java -Xms512M -Xmx1024M -XX:MaxNewSize=256m -XX:MaxPermSize=256m -Xincgc -version

2009年8月21日 星期五

spring 的 annotation @Value 介紹

通常在 bean.xml 裡我們常以 value 注入單純的資料,如 int,string、
也會注入 properties 檔裡的變數資料,如:
x-setting.properties -
com.transtep.xdna.doc.projplan.docDirLocation=tpma_doc

x-bean.xml -
<property name="docDirLocation">
<value>${com.transtep.xdna.doc.projplan.docDirLocation}</value>
</property>

但spring 3.0 使用 annotation 的時候,x-bean.xml 有些 bean 就不需要再宣告了,如 @Controller
而是自動讓 spring 去 scan 某 package 找到的,如此一來就無法注入 value
在 spring 3.0.M3 時加入了 @Value 這一個方便的 annotation 讓我們可以重拾 value 注入。
用法:

@Value("${com.transtep.xdna.doc.projplan.docDirLocation}")
private String docDirLocation = "";

2009年8月9日 星期日

svn merge 合併 用法理解

svn merge 是用來合併 "其他" repos目錄的某段版本之間的 diff 到你指定的目錄(一般為 . )
假設 有 trunk/stable 和 branches/maintain 兩個目錄都是同一個專案的程式碼,

直接以範例來解釋:
一開始,在trunk下已經有一個穩定版本,但是在 ver 27 時發現一個 bug,
於是將 stable 以 svn copy 到 branches/maintain 並 commit 準備進行修正,此時,
ver 28 時 trunk/stable 和 branches/maintain 均為同一版本的程式碼。

maintain 開始修正 bug ...
在 bug 修正的過程中,一共 commit 了10個版本,並將 bug修正完成。
同時 stable 也有做一些新功能開發,但和 maintain 正在修正的 bug 無太大關聯。

此時 ver為 38,但 maintain 的程式碼和 stable 的程式碼,
已經有 28->38 之間 10個版本的落差,

為了將 maintain 做的修正 "補回" 到 trunk 中,我們要做 merge,首先 cd 到 stable 目錄下
執行 svn merge -r 28:38 ../../branches/maintain/ .
結果即是將 maintain 在版本 28->38 之間做的變更(diff) ,合併到目前的 stable 目錄下。

此階段也許會產生衝突,因為trunk也有可能和 maintain 在同一段程式碼有做修改。
解決衝突後,stable的版本就會是 maintain bug 修正 加 stable 新功能開發版本,
但是 "尚未 commit"。
再進行 stable 的 commit 後,stable 即是最新的版本。

2009年7月31日 星期五

java ee servlet response

HttpServletResponse 物件是用來傳回結果到 browser,有些方法常用的方法:

設定 mime type:以下為 open office 的 odt 文件的 mime type
res.setContentType("application/vnd.oasis.opendocument.text");
設定編碼:
res.setCharacterEncoding("utf-8");
設定元件檔名:
res.addHeader("Content-Disposition", "attachment; filename=project-plan-book.odt");

2009年7月22日 星期三

hql 結合 distinct 過瀘重復的查詢結果

有些情況下,會有查詢到重復物件的問題,
舉一個例子直接說明:
A -> B :1 -> 多
from A as a left join fetch a.b as b
由於A與B是一對多的關係,即許多個B可能以外鍵指向同一個A
以上的hql查詢結果會返回許多重覆的A物件,
假設某A有3個B指向他,則會返回3個某A物件。
這時可以透過distinct將重復的A物件去除,如下:
select distinct a from A as a left join fetch a.b as b

2009年7月6日 星期一

debian 簡易檔案加密解密 ccrypt

安裝:
sudo aptitude install ccrypt

加密:
ccencrypt target-file
Enter encryption key:
Enter encryption key: (repeat)
target-file -> 變成 target-file.cpt 檔案

解密:
ccdecrypt target-file.cpt
Enter decryption key:
target-file.cpt -> 變成 target-file 檔案

顯示加密檔的內容但不解密:
ccat target-file.cpt
Enter decryption key:
.....秘密的資料內容....#@$
target-file.cpt 維持不變。

2009年7月2日 星期四

使用JFreeChart畫甘特圖(gantt)範例

JFreeChart主要分為 JFreeChart 物件表示圖表 及 Dataset 物件表示資料
不同的圖表物由 ChartFactory 不同的 static 方法建立,而不同的圖表物件也需要不同的 Dataset
來儲存資料,如甘特圖的 Dataset 為 IntervalCategoryDataset :

/**
*主程式進入點
*/
public static void main(String[] args){

final IntervalCategoryDataset dataset = createFakeDataset();
final JFreeChart chart = createChart(dataset);
// 輸出圖表成png檔(如果是web servlet可以輸出到response.getOutputStream())
ChartUtilities.writeChartAsPNG(target.getOutputStream(), outputChart, 2000, 600);
}

/**
* 建立甘特圖資料
*
* @return The dataset.
*/
public IntervalCategoryDataset createDataset() {

final TaskSeries s1 = new TaskSeries("計劃");
s1.add(new Task("許功蓋中文測試", new SimpleTimePeriod(date(1, Calendar.APRIL, 2001), date(5, Calendar.APRIL, 2001))));
s1.add(new Task("Obtain Approval", new SimpleTimePeriod(date(9, Calendar.APRIL, 2001), date(9, Calendar.APRIL, 2001))));
s1.add(new Task("Requirements Analysis", new SimpleTimePeriod(date(10, Calendar.APRIL, 2001), date(5, Calendar.MAY, 2001))));
s1.add(new Task("Design Phase", new SimpleTimePeriod(date(6, Calendar.MAY, 2001), date(30, Calendar.MAY, 2001))));
s1.add(new Task("Design Signoff", new SimpleTimePeriod(date(2, Calendar.JUNE, 2001), date(2, Calendar.JUNE, 2001))));
s1.add(new Task("Alpha Implementation", new SimpleTimePeriod(date(3, Calendar.JUNE, 2001), date(31, Calendar.JULY, 2001))));
s1.add(new Task("Design Review", new SimpleTimePeriod(date(1, Calendar.AUGUST, 2001), date(8, Calendar.AUGUST, 2001))));
s1.add(new Task("Revised Design Signoff", new SimpleTimePeriod(date(10, Calendar.AUGUST, 2001), date(10, Calendar.AUGUST, 2001))));
s1.add(new Task("Beta Implementation", new SimpleTimePeriod(date(12, Calendar.AUGUST, 2001), date(12, Calendar.SEPTEMBER, 2001))));
s1.add(new Task("Testing", new SimpleTimePeriod(date(13, Calendar.SEPTEMBER, 2001), date(31, Calendar.OCTOBER, 2001))));
s1.add(new Task("Final Implementation", new SimpleTimePeriod(date(1, Calendar.NOVEMBER, 2001), date(15, Calendar.NOVEMBER, 2001))));
s1.add(new Task("Signoff", new SimpleTimePeriod(date(28, Calendar.NOVEMBER, 2001), date(30, Calendar.NOVEMBER, 2001))));

final TaskSeries s2 = new TaskSeries("實際");
s2.add(new Task("許功蓋中文測試", new SimpleTimePeriod(date(1, Calendar.APRIL, 2001), date(5, Calendar.APRIL, 2001))));
s2.add(new Task("Obtain Approval", new SimpleTimePeriod(date(9, Calendar.APRIL, 2001), date(9, Calendar.APRIL, 2001))));
s2.add(new Task("Requirements Analysis", new SimpleTimePeriod(date(10, Calendar.APRIL, 2001), date(15, Calendar.MAY, 2001))));
s2.add(new Task("Design Phase", new SimpleTimePeriod(date(15, Calendar.MAY, 2001), date(17, Calendar.JUNE, 2001))));
s2.add(new Task("Design Signoff", new SimpleTimePeriod(date(30, Calendar.JUNE, 2001), date(30, Calendar.JUNE, 2001))));
s2.add(new Task("Alpha Implementation", new SimpleTimePeriod(date(1, Calendar.JULY, 2001), date(12, Calendar.SEPTEMBER, 2001))));
s2.add(new Task("Design Review", new SimpleTimePeriod(date(12, Calendar.SEPTEMBER, 2001), date(22, Calendar.SEPTEMBER, 2001))));
s2.add(new Task("Revised Design Signoff", new SimpleTimePeriod(date(25, Calendar.SEPTEMBER, 2001), date(27, Calendar.SEPTEMBER, 2001))));
s2.add(new Task("Beta Implementation", new SimpleTimePeriod(date(27, Calendar.SEPTEMBER, 2001), date(30, Calendar.OCTOBER, 2001))));
s2.add(new Task("Testing", new SimpleTimePeriod(date(31, Calendar.OCTOBER, 2001), date(17, Calendar.NOVEMBER, 2001))));
s2.add(new Task("Final Implementation", new SimpleTimePeriod(date(18, Calendar.NOVEMBER, 2001), date(5, Calendar.DECEMBER, 2001))));
s2.add(new Task("Signoff", new SimpleTimePeriod(date(10, Calendar.DECEMBER, 2001), date(11, Calendar.DECEMBER, 2001))));

final TaskSeriesCollection collection = new TaskSeriesCollection();
collection.add(s1);
collection.add(s2);

return collection;
}

/**
* 方便建立日期
*
* @param day
* the date.
* @param month
* the month.
* @param year
* the year.
*
* @return a date.
*/
public Date date(final int day, final int month, final int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, month, day);
Date result = calendar.getTime();
return result;
}

/**
* 產生甘特圖物件
*
* @param dataset
* the dataset.
*
* @return The chart.
*/
public JFreeChart createChart(final IntervalCategoryDataset dataset) {
final JFreeChart chart = ChartFactory.createGanttChart("測試甘特圖 Demo", // chart title
"事件", // domain axis label
"日期", // range axis label
dataset, // data
true, // include legend
true, // tooltips
false // urls
);
//設定各處的字型(需設定為支援中文的字型,才不會造成中文亂碼)
Font font = new Font("標楷體", Font.BOLD, 16);
chart.getLegend().setItemFont(font);
chart.getTitle().setFont(font);
chart.getCategoryPlot().getDomainAxis().setLabelFont(font);
chart.getCategoryPlot().getDomainAxis().setTickLabelFont(font);
chart.getCategoryPlot().getRangeAxis().setLabelFont(font);
chart.getCategoryPlot().getRangeAxis().setTickLabelFont(font);
return chart;
}

結果如下(web)

2009年6月26日 星期五

hibernate order by

假設 Account 的主鍵是 username VARCHAR,如果想要列出所有帳號資料,並依主鍵排序的話。
可以使用 id 進行排序即可,不一定要指定 username,如:

from Account as acc order by acc.id

這樣的寫法等同於

from Account as acc order by acc.username

但由於以 id 排序,不需要知道特定表格的主鍵 column 的名稱,
在某些無法得知 column 名稱的場合,可以派得上用場

2009年6月19日 星期五

hibernate 關聯 hbm.xml 設定 範例

many-to-one範例 -
<many-to-one name="targetGroup" column="group_id" class="com.transtep.green.servlet.framework.hibernate.GreenGroup" insert="false" update="false" cascade="save-update" outer-join="true" />

one-to-many範例 -
<set name="relAccExtSet" cascade="all" inverse="true" lazy="true">
<key>
<column name="account_id" />
</key>
<one-to-many class="com.transtep.green.servlet.framework.hibernate.GreenAccountExt" />
</set>

one-to-one範例 -
<one-to-one name="relSauth" class="com.transtep.green.servlet.framework.hibernate.GreenSimpleAuth" cascade="all" property-ref="relAccount" />

<many-to-one name="relAccount" column="account_id" class="com.transtep.green.servlet.framework.hibernate.GreenAccount" insert="false" update="false" cascade="save-update" outer-join="true" unique="true"/>