Sunday, April 30, 2006

ทำความเข้าใจ Ant Task

Ant เป็นอะไรที่ผมหลีกเลี่ยง ไม่ค่อยอยากเข้าไปทำความรู้จักมากนัก
เวลาจะทำอะไรที ก็เปิดตัวอย่างดูอย่างเดียว จากนั้นก็ เดาๆ มั่วๆไปเรื่อยๆ จนกว่าจะทำงานได้
เมื่อวานมีคนถามเรื่องการใช้งาน war task
กรณีที่มี directory ที่เก็บ lib แยกอยู่หลายที่
จะเขียนอย่างไร

ตัวอย่างโปรเจค structure ของ case นี้ก่อน

+ project
+ src
+ bin
+ lib
+ hibernate
+ jdbc
+ doclet
+ dbunit
+ context (www root dir)

ผมก็ใช้วิธีเอาตัวรอดวิธีเดิม มั่วไป 2-3 ที มันก็ work
<war destfile="myapp.war" webxml="src/metadata/myapp.xml">
<fileset dir="context"/>
<lib dir="lib/hibernate">
<lib dir="lib/jdbc">
<classes dir="bin"/>
</war>

แต่ระหว่างที่เดินทางกลับบ้าน ก็เกิดอาการปิ๊งขึ้นในหัว
เข้าใจขึ้นมาทันทีว่าอะไรเป็นอะไร ทำไมใส่อย่างนี้ work
ใส่อย่างนี้ไม่ work

วันนี้ก็เลยนั่งดู code ของ Ant เพิ่มเติม
เริ่มที่ hirarchy tree ของ War Class ก่อน



จะเห็นว่า hirarachy tree ยาวเป็นหางว่าวเลย
ตัว Abstract Class MatchingTask
เป็น base task สำหรับ งานที่ต้องการให้สามารถ include, exclude file
โดยใช้ pattern matching ได้
ซึ่งทำให้เราเขียน ant ประมาณนี้ได้
<xxx includes="**/*.xx" excludes="yy/zz">
</xxx>

<xxx>
<include name="**/*.html"/>
<exclude name="**/*.page"/>
</xxx>

<xxx>
<and>
<size value="4" units="Ki" when="more"/>
<date datetime="01/01/2001 12:00 AM" when="before"/>
</and>
</xxx>

ส่วน Zip รับผิดชอบ logic ในการสร้าง zip file
โดยมีการเพิ่ม element ที่ทำให้กำหนด fileset ที่ต้องการได้
รวมทั้งเพิ่ม ZipFileset ที่ extend มาจาก FileSet โดยมี feature ที่ทำให้เรา ระบุ prefix ของ target file ได้



ซึ่งตัวอย่างของการใช้ zip task ใน ant
<zip destfile="${dist}/manual-and-src.zip">
<fileset dir="${server.src}" casesensitive="yes">
<include name="**/*.java"/>
<exclude name="**/*Test*"/>
</fileset>
<zipfileset dir="htdocs/manual" prefix="docs/user-guide"/>
<zipfileset dir="." includes="ChangeLog27.txt" fullpath="docs/ChangeLog.txt"/>
<zipfileset src="examples.zip" includes="**/*.html" prefix="docs/examples"/>
</zip>

ซึ่ง Jar extend Zipไปใช้งาน
โดยเพิ่ม function ส่วนที่จัดการ Manifest ลงไป
<jar destfile="${dist}/lib/app.jar">
<fileset dir="${build}/classes"
excludes="**/Test.class"
/>
<fileset dir="${src}/resources"/>
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<section name="common/class1.class">
<attribute name="Sealed" value="false"/>
</section>
</manifest>
</jar>

สุดท้าย War ก็ extend จาก Jar อีกที
โดยเพิ่มส่วน element ที่ช่วยจัดการพวก file ที่อยู่ใน lib, classes, WEB-INF



จริงๆแล้ว features ที่เพิ่มเข้าไปใน war task
มีรากฐานจาก features เดิมใน zip task ทั้งสิ้น
จากตัวอย่างข้างบน
<war destfile="myapp.war" webxml="src/metadata/myapp.xml">
<fileset dir="context"/>
<lib dir="lib/hibernate">
<lib dir="lib/jdbc">
<classes dir="bin"/>
</war>

เราสามารถเขียน ในแบบ zip task ได้ดังนี้
(ได้ผลลัพท์เหมือนกัน แต่ editor ที่มี feature dtd-checking
มันจะฟ้องว่าผิด syntax ในส่วนของ file='src/meta..')
<zip destfile="myapp.war">
<zipfileset file="src/metadata/myapp.xml" fullpath="WEB-INF/web.xml"/>
<fileset dir="context"/>
<zipfileset dir="lib/hibernate" prefix="WEB-INF/lib"/>
<zipfileset dir="lib/jdbc" prefix="WEB-INF/lib"/>
<zipfileset dir="bin" prefix="WEB-INF/classes"/>
</zip>


ความยากในการทำความเข้าใจ ant ส่วนหนึ่งน่าจะมาจากการที่มันสามารถเขียนได้มากกว่า 1 วิธี
แล้วก็ element อะไรอยู่ใต้ element อะไรได้บ้าง
รวมทั้ง Types ที่มีมากมายให้เลือกใช้

Related link from Roti

2 comments:

Anonymous said...

คุณ pok ใช้โปรแกรมอะไรวาดไดอะแกรมหรอครับ
ไม่ทราบว่าเป็นโปแกรมบน Win หรือ OS อะไรครับ

PPhetra said...

ใช้ตัวนี้ครับ
http://www.omnigroup.com/applications/omnigraffle/
มีเฉพาะบน mac os x ครับ