Tải bản đầy đủ (.docx) (67 trang)

Phân tích luồng dữ liệu nhằm xây dựng phụ thuộc giữa các thành phần mã nguồn trong các ứng dụng doanh nghiệp

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.25 MB, 67 trang )

© GIA HÀ NỘI
ĐẠI HỌC QUỐC
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

Đinh Tiến Lộc

PHÂN TÍCH LUỒNG DỮ LIỆU NHẰM XÂY DỰNG
PHỤ THUỘC GIỮA CÁC THÀNH PHẦN MÃ NGUỒN
TRONG CÁC ỨNG DỤNG DOANH NGHIỆP

KHOÁ LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY
Ngành: Công nghệ thông tin

HÀ NỘI – 2018


ĐẠI HỌC QUỐC GIA HÀ NỘI
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

Đinh Tiến Lộc

PHÂN TÍCH LUỒNG DỮ LIỆU NHẰM XÂY DỰNG
PHỤ THUỘC GIỮA CÁC THÀNH PHẦN MÃ NGUỒN
TRONG CÁC ỨNG DỤNG DOANH NGHIỆP

KHOÁ LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY
Ngành: Công nghệ thông tin

Cán bộ hướng dẫn: PGS. TS. Phạm Ngọc Hùng

HÀ NỘI – 2018




VIETNAM NATIONAL UNIVERSITY, HANOI
LỜI CẢM ƠNAND TECHNOLOGY
UNIVERSITY OF ENGINEERING

Đầu tiên, em xin gửi lời cảm ơn chân thành và sâu sắc tới PGS. TS. Phạm Ngọc
Hùng – người đã trực tiếp hướng dẫn tận tình, tỉ mỉ trong suốt quá trình em học tập,
nghiên cứu và đặc biệt khi tôi làm khóa luận tốt nghiệp này. Thầy đã cho em không chỉ
kiến thức, mà còn nhiều lời động viên,
kiến đóng
Dinhý Tien
Loc góp quý báu trong cuộc sống. Em
cảm thấy tự hào và may mắn khi là một sinh viên được học tập, làm việc dưới sự
hướng dẫn của thầy trong những năm tháng đại học.
Phương pháp và công cụ trong khoá luận này đều có sự đóng góp một phần từ các
bạn và anh/chị trong phòng Nghiên cứu và Phát triển 320-E3. Vì vậy, tôi xin gửi lời
GENERATING
BUSINESS
DATA
FLOWS
cảm ơn chân
thành nhất đến các bạn
và anh/chị đã hỗ
trợ, giúp
tôi có thể hoàn thành
khoá luận
này.ENTERPRISE APPLICATIONS BASED ON
FOR
Tôi xin gửi lời cảmSOURCE

ơn đến nhữngCODE
người bạnANALYSIS
trong tập thể K59-CLC, những người
bạn đồng hành trong bốn năm đại học. Các bạn đã giúp đỡ tôi trong học tập, có những
động viên, góp ý khi tôi chia sẻ những khó khăn, bế tắc trong cuộc sống. Đó là những
đóng góp không nhỏ để giúp tôi có thể hoàn thành khóa luận này.

THE
Tiếp theo tôi xin gửi lời cảm ơn
đếnBS
cácTHESIS
thầy cô giảng viên Trường Đại học Công
Nghệ - Đại học Quốc GiaMajor:
Hà Nội Information
– những ngườiTechnology
đã tận tâm truyền đạt tất cả kiến thức
quý báu của mình, làm nền tảng để tôi tiếp tục đi xa hơn nữa trong lĩnh vực công nghệ
thông tin.
Cuối cùng tôi xin được gửi lời cảm ơn sâu sắc nhất đến gia đình đã nuôi tôi khôn
lớn, trưởng thành hôm nay, cảm ơn cha, mẹ, em gái và người thân đã luôn động viên,
Supervisor: Assoc. Prof. Pham Ngoc Hung
là điểm tựa tinh thần giúp tôi vượt qua những khó khăn, thử thách.

HANOI – 2018


TÓM TẮT
Ngày nay, Java và cụ thể là J2EE là một trong những nền tảng tốt nhất để xây dựng các
hệ thống ứng dụng web quy mô lớn. Trong quá trình hệ thống phát triển, qua nhiều lần bảo trì
nâng cấp, các doanh nghiệp rất khó kiểm soát và đảm chất lượng các ứng dụng này do mã

nguồn rất lớn và phức tạp. Mặt khác, đối với một hệ thống lớn, các vấn đề liên quan đến phần
thiết kế thường cực kỳ phức tạp. Luồng dữ liệu giúp ta hình dùng được toàn bộ thiết kế của
ứng dụng dưới khía cạnh trao đổi dữ liệu, giúp việc kiểm soát ứng dụng dễ dàng hơn.
Vì thế, khóa luận đề xuất một phương pháp để sinh ra các luồng dữ liệu của ứng dụng
J2EE từ việc phân tích mã nguồn.. Đầu vào của công cụ là một tệp nén toàn bộ mã nguồn của
ứng dụng J2EE. Đầu ra là các luồng dữ liệu dưới dạng đồ thị có hướng được hiển thị trên
trình duyệt web. Cụ thể quá trình sinh luồng dữ liệu gồm bốn bước. Bước đầu tiên, toàn bộ
mã nguồn trong tệp đưa vào được phân tích để xây dựng cây cấu trúc. Tiếp theo, các công
nghệ sử dụng được phát hiện, cây cấu trúc sẽ trải qua quá trình phân tích sâu để xác định các
kiểu phụ thuộc có trong mã nguồn. Sau đó, đồ thị luồng dữ liệu ở dạng đơn giản tạo ra bởi
việc chuyển đổi mỗi phụ thuộc thành một tập các cạnh, gọi là cạnh dữ liệu. Cuối cùng, các
đỉnh của đồ thị luồng dữ liệu đươc đơn giản hóa, đồng thời các cạnh sẽ được chuẩn hóa bằng
cách xử lý thêm, bớt hoặc thay đổi để thể hiện được quá trình tuần tự trao đổi dữ liệu trong
mã nguồn. Phương pháp này được cài đặt như là một chức năng trong bộ công cụ đảm bảo
chất lượng mã nguồn JCIA-VT. JCIA-VT được xây dựng bằng ngôn ngữ Java. JCIA-VT dùng
để phân tích các ứng dụng Web xây dựng bằng các công nghệ của J2EE như: Struts,
Hibernate, JDBC, Spring, v.v. Khóa luận cũng đánh giá tính đúng đắn của công cụ JCIA-VT
và cụ thể là quá trình xây dựng luồng dữ liệu bằng cách tự nghiên cứu các công nghệ để xây
dựng ca kiểm thử cho mọi trường hợp xảy ra. Hơn nữa, công cụ cũng được hợp tác thử
nghiệm trên mã nguồn ứng dụng của một số doanh nghiệp lớn như Viettel, Mitami, v.v. và
nhận được nhiều phản hồi tích giúp công cụ trở nên hoàn thiện hơn.

Từ khóa: phân tích mã nguồn, luồng dữ liệu, phụ thuộc, J2EE

4


ABSTRACT
Nowaday, Java and J2EE in particular is one of the best platform in order to build web
application systems in large scale. Through several maintenance upgrades, it is difficult for

companies to control and ensure the quality of these applications because of the huge and
complex source code. On the other hand, for a heavy system, the issues related to the design
are often extremely complex. The data flows offers a perspective running through the
application presenting all the application architecture based on transfering data between
components, make companies easy to control their application.
This study put forward a great ideas to generate data flows of J2EE application by
analyzing source code. The input of this toolkit is a zip file of J2EE application’s source code.
The output is create data flows term of graph, a graph make a display of web. Firstly, the
source code is parsed to build a structure tree. Next, the structure tree is got into the second
parser which finding and establishing dependency between node based on the detected
framework. After that a graph of data flows in basic form is created by convert dependency
into a set of edges, named data-edge. Finally, all verticed in data flows are simplified, and
edges are normalized by adding, removing or modifying to show the order of application’s
component in transfering data. It is considered a feature of JCIA-VT – the toolkit for
guarantee the source code quality of J2EE applications. JCIA-V is developed in Java. The
purpose of this toolkit is analyze source code of application that is build by frameworks such
as: Struts, Hibernate, JDBC, Spring, v.v. This study also assess the correctness of this toolkit
and the building data flows processes by using testcase of self-researching case study.
Moreover, some big companies such as Viettel, Mitati, v.v. is participating in testing this
toolkit by support a variaty real-life application’s source code and response effective
feedbacks in order to complete this tookit.

Keywords: source code analysis, software quality assurance, data flows, dependency, J2EE

5


LỜI CAM ĐOAN
Tôi xin cam rằng những nghiên cứu và đề xuất phương pháp về xây dựng luồng dữ
liệu được trình bày trong khóa luận này là của tôi và chưa từng được nộp như một báo

cáo khóa luận tại trường Đại học Công Nghệ - Đại học Quốc Gia Hà Nội hoặc bất kỳ
trường đại học khác. Những gì tôi viết ra không sao chép từ các tài liệu, không sử
dụng các kết quả của người khác mà không trích dẫn cụ thể.
Tôi xin cam đoan công cụ xây dựng luồng dữ liệu mà tôi trình bày trong khoá
luận là do tôi tự phát triển, không sao chép mã nguồn của người khác. Nếu sai tôi hoàn
toàn chịu trách nhiệm theo quy định của trường Đại học Công Nghệ - Đại học Quốc
Gia Hà Nội.

Hà Nội, ngày ... tháng … năm 20...
Sinh viên

Đinh Tiến Lộc

6


MỤC LỤC

7


DANH MỤC HÌNH VẼ

8


DANH MỤC MÃ NGUỒN

9



DANH MỤC BẢNG BIỂU

10


DANH MỤC TỪ VIẾT TẮT
Từ viết tắt
Nội dung
API
Application Programming Interface
AST
Abstract Syntax Tree
CSDL
Cơ sở dữ liệu
DAO

Data Access Object

HTML

HyperText Markup Language

J2EE

Java 2 Platform, Enterprise Edition

JDBC

The Java Database Connectivity


JSP

JavaServer Page

MVC

Model-View-Controller

ORM

Object Relational Mapping

POJO

Plain Old JavaObject

XML

eXtensible Markup Language

11

Ý nghĩa
Giao diện lập trình ứng dụng
Cấy cú pháp trừu tượng
Các đối trượng Java phục vụ
tương tác với cơ sở dự liệu
Ngôn ngữ đánh dấu siêu văn bản
Nền tảng phát triển các công

nghệ Web trên Java
Công nghệ tương tác với cở sở
dữ liệu của Java
Công nghệ xây dựng Web của
Java
Mô thích thiết kế mã nguồn cho
các ứng dụng Web hiện đại
Kĩ thuật chuyển đổi dữ liệu của
hệ thống khác sang đối tượng
trong ngôn ngữ lập trình hướng
đối tượng
Các đối tượng Java thuẩn chỉ để
lưu trữ dữ liệu
Ngôn nghữ đánh đấu mở rộng


Đặt vấn đề
Trong quá trình phát triển phần mềm, do nhiều hạn chế về tài nguyên, các doanh
nghiệp thường không chú trọng vào quá trình đảm bảo chất lượng cho ứng dụng phần
mềm của mình, khiến phần mềm tiềm ẩn nhiều rủi ro. Trong thực tế, đã có rất nhiều
trường hợp xảy ra rủi ro và gây ra những thiệt hại không hề nhỏ. Bên cạnh đó, những
ứng dụng được phát triển trong thời gian dài sẽ có quy mô và độ phức tạp cao. Đồng
thời trải qua nhiều phiên bản nâng cấp, doanh nghiệp thường khó có cái nhìn bao quát
về thiết kế của ứng dụng. Những điều đó làm cho việc quản lí chất lượng của ứng dụng
gặp nhiều khó khăn: về chi phí, chất lượng cũng như tính khả thi.
Các ứng dụng ngày này, đặc biệt là những ứng dụng xây dựng trên nền tảng Web,
thường được xây dựng bởi nhiều mô-đun, quy mô lớn cũng như độ phức tạp cao. Do
đó các vấn đề liên quan đến phần thiết kế thường phức tạp hơn các vấn đề giải thuật
hay cấu trúc dữ liệu. Luồng dữ liệu là một thành phần trong thiết kế của ứng dụng.
Luồng dữ liệu là một tập hợp thứ tự các phần tử của ứng dụng, thể hiện cách dữ liệu

được sử dụng và trao đổi trong quá trình ứng dụng hoạt động [3]. Do đó, việc đảm bảo
các phần tử được xây dựng với luồng chính xác theo thiết kế đưa ra là cực kì quan
trọng. Theo thời gian phát triển của ứng dụng, mã nguồn có thể coi là tài liệu duy nhất
luôn có sẵn và thể hiện chính xác nhất tính chất của ứng dụng. Bằng việc xem xét
luồng dữ liệu từ mã nguồn, người phát triển ứng dụng có thể đưa ra những nhận xét,
đánh giá về việc thực hiện hóa thiết kế. Đồng thời, xác định được những thành phần có
ràng buộc phụ thuộc với nhau về mặt dữ liệu, giúp người phát triển hình dung toàn
diện hơn về ứng dụng. Hơn nữa, các công cụ kiểm thử trang web hiện nay đều chỉ
kiểm thử sự tương tác với người dùng thông qua giao diện đồ họa, chưa đảm bảo được
sự chính xác khi ứng dụng xử lí dữ liệu. Việc xây dựng và phân tích luồng dữ liệu sẽ là
một hướng tiếp cận tốt để khắc phục được vấn đề này và giúp hoàn thiện quá trình tự
động hóa khi kiểm thử các ứng dụng Web.
Tính đến tháng 4 năm 2018, Java vẫn được coi là ngôn ngữ phổ biến nhất thế
giới (theo điểm xếp hạng TIOBE 1). Java được tạo bởi công ty Sun Microsystems (nay
thuộc Oracle), là một ngôn ngữ lập trình hướng đối tượng, phục vụ để xây dựng ứng
dụng trên nhiều nền tảng như Web, Desktop hoặc trên các thiết bị di động. Đại đa số
trong các doanh nghiệp Việt Nam hiện nay đều sử dụng JavaEE để phát triển ứng dụng
1 />
12


Java Web. Theo khảo sát của trang TopITworks 2, Spring, Struts, Hibernate và JDBC là
những công nghệ được các ứng dụng JavaEE sử dụng nhiều nhất. Những ứng dụng sử
dụng các công nghệ nêu trên thường phức tạp do sử dụng nhiều định dạng mã nguồn
với mục đích khác nhau: Java để mô hình hóa dữ liệu và xây dựng nghiệp vụ, XML
dùng trong việc cấu hình ứng dụng và JSP để xây dựng trang Web.
Với các thực trạng đang rất nan giải trong các doanh nghiệp CNTT như đã nêu ở
trên, bộ công cụ JCIA-VT đã được xây dựng để giải quyết hai vấn đề: đảm bảo chất
lượng phần mềm và tổng quát hóa kiến trúc thiết kế của ứng dụng dưới dạng các biểu
đồ, đồ thị. Bông cụ JCIA-VT được xây dựng bằng ngôn ngữ Java, gồm nhiều chức

năng như: phân tích phụ thuộc, phân tích ảnh hưởng thay đổi, phân tích độ phức tạp
mã nguồn, xây dựng các biểu đồ thiết kế,…
Khoá luận này sẽ đề xuất phương pháp nhằm xây dựng công cụ phân tích và
trình diễn luồng dữ liệu của các ứng dụng sử dụng JavaEE. Công cụ này là một trong
các tiện ích của JCIA-VT. Khoá luận đề xuất giải pháp xây dựng luồng dữ liệu từ sự
phụ thuộc giữa các thành phần trong ứng dụng. Cụ thể, mã nguồn về phần công nghệ
web được phân tích là Spring, Struts và về phần các framework tương tác cơ sở dữ liệu
(CSDL) là Hibernate và JDBC. Đồng thời, khóa luận cũng đề xuất phương pháp phân
tích phụ thuộc tương tác CSDL. Phụ thuộc tương tác CSDL là phụ thuộc thể hiển bởi
việc các phương thức Java tạo câu truy vấn và truy xuất dữ liệu của các bảng trong
CSDL. Phương pháp phân tích này được xây dựng dựa trên ý tưởng truy vết sự thay
đổi các thành phần trong mã nguồn và cố gắng thực hiện các sự thay đổi đó một cách
thủ công.
Các phần còn lại của khoá luận này được trình bày như sau. Chương 2 trình bày
về việc xây dựng JDG từ mã nguồn ứng dụng. Chương 3 mô tả phương pháp phân tích
phụ thuộc các thành phần mã nguồn. Cách thức xây dựng luồng dữ liệu từ JDG được
trình bày trong Chương 4. Tiếp theo đó Chương 5 trình bày tổng quan về cách cài đặt
và triển khai của bộ công cụ JCIA-VT và cụ thể là chức năng đồ thị luồng dữ liệu.
Cuối cùng, Chương 6 tóm tắt những kết quả đã đạt được, kết luận và hướng nghiên
cứu phát triển trong tương lai.

2 />
13


Chương 1.

Cơ sở nền tảng

1.1.Cây cấu trúc và tiền xử lý mã nguồn


Các ứng dụng J2EE có nhiều thành phần, sử dụng nhiều định dạng mã nguồn
như Java, XML, HTML, JSP, v.v. Mỗi định dạng lại có cấu trúc và cú pháp khác nhau.
Do đó, nhằm mục đích dễ dàng trong việc phân tích xử lý mã nguồn để xây dựng các
luồng dữ liệu, cần thiết phải định nghĩa một cây cấu trúc dữ liệu để có thể thể hiện và
phân tích được nội dung của tất cả các định dạng nêu trên. Theo [1], đồ thị phụ thuộc
Java EE là phương pháp tốt nhất để lưu trữ tất cả thông tin của mã nguồn cũng như
mối quan hệ giữa các thành phần trong mã nguồn với nhau.
Định nghĩa: (Đồ thị phụ thuộc Java EE) Cho mã nguồn ứng dụng J2EE, một đồ thị
phụ thuộc Java EE, gọi tắt là JDG (Java EE Dependency Graph), được định nghĩa là
một cặp (N, D) với N = {n1, n2,..., nk} là nút đại diện cho các thành phần như thư mục,
tệp, lớp, phương thức, trường v,v. và D = {(n1, n2) | n1, n2 N) ⊆ N N. Mỗi một cạnh
(n1, p, n2) đại diện cho một phụ thuộc giữa hai nút n1 và n2 với loại phụ thuộc p, khi đó
ta coi nút n1 phụ thuộc nút n2.
Một cạnh của JDG được gọi là phụ thuộc dữ liệu nếu phụ thuộc này được sinh ra
bởi việc nút n1 sử dụng “dữ liệu” của nút n2. Ví dụ như phụ thuộc với tên gọi là
JavaMethodInvocationDependency thể hiện việc sử dụng phương thức trong một
phương thức khác của Java, nút n1 là hàm gọi, nút n2 là hàm bị gọi, “dữ liệu” được
hiểu là giá trị trả về của nút n2. Một ví dụ khác là phụ thuộc với tên gọi
SQLInsertDependency thể hiện phương thức của DAO sử dụng truy vấn thêm bản ghi.
DAO chính là các đối tượng Java có nhiệm vụ tương tác với cơ sở dữ liệu (CSDL).
Như vậy, với kiểu phụ thuộc nêu trên, nút n1 là phương thức sử dụng câu truy vấn tới
CSDL, n2 là bảng trong CSDL bị tác động, “dữ liệu” của phụ thuộc này chính là câu
truy vấn mà phương thức đó sử dụng.
Một cạnh của JDG được gọi là phụ thuộc cấu trúc nếu phụ thuộc được sinh ra bởi
quan hệ giữa hai nút n1 và n2. Ví dụ như phụ thuộc JavaExtensionDependency chỉ thể
hiện mối quan hệ thừa kế giữa hai lớp Java, hoặc phụ thuộc
JavaClassToDbDependency chỉ thể hiện tồn tại ánh xạ từ một bảng trong CSDL với
một lớp Java. Giữa hai nút của hai phụ thuộc này đều không có sự trao đổi thông tin
với nhau.


14


1.1.1.

Xử lý mã nguồn Java

Mã nguồn Java đầu tiên cần được chuyển đổi sang một cấu trúc mã trung gian để
phục vụ cho quá trình phân tích. Hiện tại ta chỉ xét hai cấu trúc mã trung gian tiêu
biểu: dạng bytecode hoặc cây cú pháp trừu tượng (Abstract Syntax Tree – AST), đơn
giản là cây cú pháp. Còn với cây cú pháp, mã nguồn được phân tích và lưu trữ theo
cấu trúc cú pháp cấp bậc, theo cấu trúc dữ liệu dạng cây [3].
Mã nguồn 1.1. Ví dụ một đoạn mã nguồn do-while của Java
public void doWhileLoop() {
int i = 0;
do {
i++;
}
while (i < 10);
}

Mã nguồn 1 mô tả một phương thức trong Java. Để xây dựng AST ta có thể sử
dụng thư viện JDT3. Với đầu vào là mã nguồn java, cùng với cú pháp của Java, JDT sẽ
phân tích từng câu chữ của mã nguồn để tạo ra AST. JDT là một một thành phần trong
Eclipse IDE4 – công cụ lập trình mã nguồn mở cho Java và các ngôn ngữ lập trình
khác. Hình 1-1 minh họa cấu trúc AST ứng với Mã nguồn 1.1.

Hình 1.1. Cấu trúc mã trung gian AST của mã nguồn Java


3 />4 />
15


Hình 1.2. Cấu trúc mã trung gian bytecode của Mã nguồn 2.1.
Ở cấu trúc dạng bytecode, mã nguồn được mã hóa và lưu trữ dưới dạng tập thứ tự
các mã chỉ thị. Trình biên dịch của Java dịch các đoạn mã nguồn do người dùng viết để
tạo ra các tệp bytecode [6]. Các tệp bytecode sẽ được máy áo Java (JVM) thông dịch
sang ngôn ngữ máy để máy tính có thể thực hiện. Hình 2.2 minh họa dạng bytecode
ứng với Mã nguồn 1.1.
Do mã trung gian dạng bytecode lưu các chỉ thị ở dạng mã nhị phân, nên nó giúp
chương trình thực thi nhanh hơn, nhưng khiến ta khó phân tích và xử lý. Ngược lại, mã
trung gian dạng AST hướng đối tượng và có cấu trúc dữ liệu dạng cây, nên có khả
năng đọc và phân tích tốt hơn hẳn. Chính vì lí do này, cấu trúc AST được chọn để tiến
hành phân tích xây dựng JDG. Toàn bộ quá trình xử lý mã nguồn Java được mô tả như
Hình 1.3

Hình 1.3. Quá trình xử lí mã nguồn tệp Java
Đầu vào của quá trình này là một nút chứa thông tin của tệp Java trong JDG. Các
thành phần con của nút này chưa được xử lí thành JDG mà mới chỉ chứa mã nguồn.
Để xây dựng JDG, đầu tiền JDT phân tích mã nguồn để hình thành cây AST. Các
16


thông tin cần thiết trong AST sẽ được trích xuất và được lưu vào một nút biểu diễn lớp
là JavaClassNode. Các thuộc tính cơ bản về các lớp trong AST sẽ được lấy ra như: tên
lớp, các trạng thái static, final, abstract hay là phạm vi truy câp của lớp. Ngoài ra,
thông tin về các lớp cha và các lớp interface cũng là những thông tin quan trọng cần
thiết cho JDG. Mỗi phương thức, hoặc mỗi trường có trong lớp sẽ được lưu như là một
nút trong JDG, là nút con của JavaClassNode. Các nút phương thức chứa thông tin về

tham số, kiểu trả về, trạng thái. Còn các nút trường chứa thông tin về kiểu dữ liệu, tên
trường và giá trị khởi tạo của chúng. Cuối cùng, nút JavaClassNode chứa nội dung của
lớp Java với các thành phần con được thêm vào JDG.
1.1.2.

Xử lý mã nguồn tệp XML và JSP

XML (Extensible Markup Language) là ngôn ngữ đánh dấu, được dùng để mô tả
dữ liệu. Các thẻ (tag) trong XML không được xác định trước mà do người dùng tự
định nghĩa. Tệp XML bao gồm các phần tử có dạng: <tên thuộc_tính = "giá trị"> nội
dung </tên>. Mỗi phần tử có một thẻ bắt đầu và một thẻ kết thúc, ở giữa hai thẻ là nội
dung. Nội dung của phân tử có thể bao gồm văn bản và các phần tử con khác. Mỗi tệp
XML chỉ được có một phần tử gốc (phần tử chứa tất cả các phần tử khác).
Mã nguồn 1.2. Ví dụ về nội dung của một tệp XML
<?xml version="1.0"?>


<name>
<first_name>Alan</first_name>
<last_name>Turing</last_name>
</name>
computer scientist</profession>
</person>
</people>

Hai công cụ DOMParser và SAXParser là các thư viện có sẵn của Java, được sử
dụng để xử lý mã nguồn XML. DOMParser phân tích mã nguồn XML về một kiểu dữ
liệu dạng cây với các nút là các đối tượng Java. Còn SAXParser tính toán tọa độ (số
hàng, số cột) của từng thẻ để phục vụ cho yêu cầu định danh và tìm kiếm nút. Cấu trúc
cây của Mã nguồn 1.2 được mô tả như hình Hình 1.4. Nút lớn nhất của cây là đối

tượng lớp Document, mô tả toàn bộ nội dung của một tệp XML. Mỗi một cặp thẻ được
đại diện bởi lớp Element. Trong nút kiểu Element có thể có các nút con như nút Text
(văn bản) hoặc các nút Element khác. Ngoài ra, nút Attr (thuộc tính của thẻ) cũng được
xếp vào tập nút con của Element. Mỗi một nút trong cây còn chứa tọa độ (x:y) với x là
17


số thứ tự theo dòng của thẻ, y là vị trí ký tự đầu tiên của thẻ trong dòng đó. Ví dụ trong
Hình 1.4, nút kiểu Element có tên là person, kí hiệu (3:4) nghĩa là thẻ person nằm ở
dòng 3, và bắt đầu từ ký tự thứ 4 của dòng.
Sau khi có được cây dữ liệu, việc tiếp theo là thêm các nút tương ứng với các thẻ
XML vào JDG. Các nút này chỉ cần lưu trữ các giá trị về tên thẻ, tọa độ thẻ, và danh
sách các thẻ chứa trong nó. Dữ liệu sinh ra bởi DOMParser và SAXParser là các đối
tượng như Document, Element. Attr, v.v. chứa nhiều thông tin không cần thiết và
không phù hợp với các nút trong JDG đã nêu ở trên. Do đó, bộ xử lý XML sẽ loại bỏ
các thông tin không cần thiết, giữ lại các thông tin liên quan để tạo thành nút
XmlTagNode cho JDG.

Hình 1.4. Cấu trúc cây của mã nguồn XML
JSP (JavaServer Page) là một công nghệ phát triển Web hỗ trợ thiết kế các nội
dung động. Điểm đặc biệt của công nghệ này là người sử dụng có thể chèn trực tiếp
mã nguồn Java vào trang JSP, để truy xuất các nội dung động. JSP gồm hai thành phần
chính là: nội dung tĩnh (HTML, SVG, XML) và nội dung động (thể đặc biệt của JSP).
Các thẻ đặc biệt trong JSP có hai kiểu. Một là các thẻ nội dung kiểu XML theo chuẩn

18


được quy định sẵn, gọi là JSTL (JavaServer Pages Standard Tag Library). Kiểu thứ hai
là các thẻ kịch bản. Các thẻ kịch bản tương tự XML đều có ký hiệu bắt đầu và kết

thúc, nhưng chỉ chứa nội dung bên trong mà không có tên thẻ. JSP có năm kiểu thẻ
kịch bản, được liệt kê trong Bảng 1.1. Thẻ chú thích là những thẻ định nghĩa các câu
chú thích trong trang JSP. Thẻ chỉ thị thông báo thông tin cho trang JSP như cách mã
hóa kí tự, danh sách các thư viện thẻ (Tag Library) để sử dụng trong trang, v.v. Thẻ
khai báo và Thẻ mã lệnh đều là hai thẻ có thể nhúng trực tiếp mã nguồn Java. Nhưng
thẻ khai báo có phạm vi sử dụng hẹp hơn, nội dung chỉ là những câu lệnh khởi tạo các
biến và phương thức của Java. Trong khi đó, ngoài khả năng nhúng được câu lệnh khai
báo, thẻ mã lệnh còn có thể gồm các câu lệnh phục vụ việc thực thi và xử lý giá trị
trong Java. Thẻ cuối cùng trong các thẻ kich bản là thẻ hiển thị. Thẻ này dùng để hiển
thị giá trị của một biểu thức, hoặc một biến của Java trên giao diện người dùng.
Bảng 1.1. Danh sách các thẻ kịch bản trong JSP
Thẻ kịch bản
Thẻ chú thích
(Comment Tag)
Thẻ chỉ thị
(Directive Tag)

Cú pháp

Ví dụ

<%-- nội dung --%>

<%-- This is a comment --%>

<%@ nội dung %>

<%@ page
contentType="text/html;charset=
UTF-8" %>

<%!
int count = 0;
int getCount() {
return count;
}
%>
<%
int count = 0;
out.print(++count);
%>
<%= (2*5) %>
<%= count %>
<%= user.name %>

Thẻ khai báo
(Declaration Tag)

<%! nội dung %>

Thẻ mã lệnh
(Scriplet Tag)

<% nội dung %>

Thẻ hiển thị
(Expression Tag)

<%= nội dung %>

Mã nguồn 1.3 là ví dụ về nội dung của một trang JSP. Nội dung của trang này là

khi bắt đầu hiển thị lấy ngẫu nhiên một số thập phân trong khoảng từ 0 đến 1 và hiển
thị số đó trên giao diện. Nếu số đó lớn hơn 0.95 thì màn hình hiển thị dòng chữ “ You'll
have a luck day!”. Ngược lại. màn hình hiển thị “Well, Bad luck.” . Dòng đầu tiên là
thẻ <%@ page … %>, định nghĩa các thông tin cơ bản của trang. Thẻ <%@ taglib
… %> thông báo sử dụng thư viện thẻ JSTL-Core 5. Trong một trang JSP có thể dùng
5 />
19


được nhiều thư viện thẻ. Mỗi một thư viện thẻ đều phải được khai báo trong một thẻ <
%@ taglib … %> riêng rẽ. Thẻ <jsp:setProperty> khai báo một thuộc tính của trang
có tên title và giá trị là chuỗi “Welcome to JSP”. Thẻ <c:out> có chức năng giống thẻ
<%= … %>, hiển thị giá trị của thuộc tính title bằng cách đặt trong cặp dấu “${“và
“}“. Các thẻ kịch bản có thẻ sử dụng tại bất cứ vị trí nào trong trang JSP, vừa có thể xử
lý độc lập, vừa có thể là thành phần của một thẻ khác.
Mã nguồn 1.3. Ví dụ về nội dung của một tệp JSP
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri=" prefix="c" %>
<html>
<jsp:setProperty name=“title” value = “Welcome to JSP”/>
<head><title><c:out value=“${title}”/></title></head>
<body>

<%

%>

double num = Math.random();
if (num > 0.95) {

You'll have a luck day!




<% } else { %>

Well, Bad luck.


<% } %>
Your number is <%= num %>.


phụ thuộc
2.1.Phân tích phụ thuộc mã nguồn Java Core

Các thành phần mã nguồn Java có ba loại phụ thuộc chính: thừa kế, sử dụng trường
và gọi phương thức. Phụ thuộc thừa kế là phụ thuộc khi một lớp kế thừa một lớp hoặc
một interface khác. Như vậy, phụ thuộc thừa kế được chia thành hai kiểu: phụ thuộc
thừa kế lớp và phụ thuộc thừa kế interface. Hình 2.5 mô tả quan hệ phụ thuộc thừa kế
ở hai kiểu. Lớp B và lớp A có quan hệ phụ thuộc thừa kế lớp do lớp B thừa kế lớp A
qua từ khóa extends. Còn phụ thuộc thừa kế interface là phụ thuộc mà lớp B thừa kế
lớp A qua từ khóa implement.

Hình 2.5. Quan hệ phụ thuộc thừa kế trong mã nguồn Java
Quan hệ phụ thuộc sử dụng trường là quan hệ khi phương thức sử dụng một
trường của lớp nào đó. Lưu ý rằng, trong Java, có bốn cách để phương thức có thể sử
dụng một trường. Các trường hợp được mô tả như Hình 2.6. Đầu tiên, cách đơn giản
nhất để phương thức sử dụng được trường là cả hai đều thuộc một lớp. Ngoài ra, nếu
một lớp

21


Hình 2.6. Quan hệ phụ thuộc sử dụng trường trong mã nguồn Java
thừa kế lớp cha mà lớp cha có trường được khai báo phạm vi protected hoặc default,
khi đó các phương thức trong lớp con có thể sử dụng trường đó. Ví dụ trong Hình 2.6,
lớp C thừa kế lớp A, lớp A có trường a1 với phạm vi protected và trường a2 với phạm
vi default. Khi đó, phương thức getSuperA1() và getSuperA2() của lớp C có thể sử
dụng trường a1, a2. Ngoài phạm vi protected và default, trường có phạm vi public có
thể được truy cập bởi mọi phương thức khác. Tiếp tục với Hình 2.6, phương thức
getPublicB() có thẻ sử dụng trường b của lớp B do trường b được khai báo phạm vi là

public.
Quan hệ phụ thuộc cuối cùng trong Java là quan hệ phụ thuộc gọi phương thức.
Đây là phụ thuộc giữa hai phương thức khi phương thức này được sử dụng trong
phương thức kia. Hình 2.7 là ví dụ minh họa cho một phụ thuộc gọi phương thức.
Phương thức hello() trả về một chuỗi “Hello World!”. Phương thức sayHello() sử
dụng hello() để in chuỗi “Hello World!” đó ra màn hình.

Hình 2.7. Quan hệ sử dụng phụ thuộc gọi phương thức trong mã nguồn Java
2.2.Phân tích phụ thuộc mã nguồn Struts

22


Struts là một công nghệ phục vụ phát triển các ứng dụng Web trên nền tảng Java.
Các ứng dụng Struts được thiết kế theo mô hình MVC7 (Model-View-Controller).
View Result thường sử dụng mã nguồn JSP đại diện cho phần View của ứng dụng. Các
yêu cầu của người dùng đều được xử lý bởi Action. Các Action chính là các lớp Java
đại diện cho phần Controller. Các Action được Struts điều hướng tự động thông qua
lớp FilterDispatcher kết hợp với tệp cấu hình là struts.xml. Phần Model gồm các lớp
Java có nhiệm vụ tương tác với các bảng trong CSDL. Các Action chịu trách nhiệm xử
lý các phần lô-gíc nghiệp vụ của ứng dụng bằng cách sử dụng các lớp trong phần
Model. Kết quả sau khi Action xử lý là các trang JSP hoặc dữ liệu để hiển thị lại cho
người dùng.

Hình 2.8. Mô hình thiết kế của ứng dụng Struts 2
Do Struts là một framework mã nguồn mở nên ta có thể sử dụng ngay chính bộ
xử lí được xây dựng bên trong tên là XWork để phân tích các thành phần. Cách hoạt
động của XWork được mô tả như Hình 2.9. Đầu vào của XWork là đường dẫn của tệp
struts.xml. Sau đó, XWork sẽ tạo nên một môi trường để xử lý tệp struts.xml, goi là
XWork Emulator.


Hình 2.9. Cơ chế hoạt động của Xwork
Đầu tiên XWork Emulator sẽ khởi tạo một Dispatcher. Dispatcher có hai nhiệm
vụ chính. Thứ nhất, nó khởi tạo và chạy các providers. Trong XWork Emulator, mỗi
provider sẽ đảm nhiệm một chức năng như: quản lý tệp (File Manager Provider), quản
lý thông số ứng dụng (Properties Provider), xử lý tệp cấu hình (Xml Configuration
7 />
23


Provider), v.v. Nhiệm vụ thứ hai của Dispatcher là điều phối các tham số cấu hình của
HttpRequest vào các provider tương ứng khi nhận yêu cầu từ giao diện. Tất cả các
providers sau khi khởi tạo sẽ được đưa vào trong một Container theo cơ chế keyvalue. Cuối cùng, ta sẽ lấy được Configuration từ Container chứa các thông số cấu
hình của ứng dụng và các thành phần của Struts như StrutsAction, StrutsPackage,
StrutsResult, StrutsInterceptor, v.v.
Tệp struts.xml sau bước xử lý mã nguồn XML được thể hiện như là một nút với
kiểu XmlFileNode trong JDG. Sau bước phân tích sâu mã nguồn của Struts, nút này
được chuyển đổi thành StrutsConfigurationNode bằng mẫu thiết kế Decorator [7]. Nút
kiểu StrutsConfigurationNode chứa các nút StrutsPackage theo đúng thứ tự các thẻ
XML trong mã nguồn. Ngoài ra nút StrutsConfigurationNode còn bao gồm các nút
StrutsConfigurationNode con được khai báo qua thẻ <include>. Mối quan hệ phụ
thuộc giữa các nút đươc liệt kê trong Bảng 2.2. Ý nghĩa của từng phụ thuộc được cho
trong bảng. Tổng cộng có 10 loại phụ thuộc trong Struts.
Bảng 2.2. Danh sách phụ thuộc trong Struts
Tên phụ thuộc
UseSimpleFieldActionDependency
StrutsResultTypeConfiguration
ToJavaClassDependency
StrutsResultConfiguration
ToTilesDefinitionDependency

StrutsResultConfigurationToJsp
Dependency

Ý nghĩa của phụ thuộc
Jsp sử dụng struts-tag để gọi Action
Tệp cấu hình sử dụng Java Class để định nghĩa
Result Type
Tệp cấu hình sử dụng Tiles để định nghĩa View
Result
Tệp cấu hình sử dụng tệp Jsp để định nghĩa View
Result
Mối quan hệ thừa kế giữa hai thành phần cấu
StrutsPackageExtensionDependency
hình package
StrutsInterceptorToJavaClassDepende Tệp cấu hình sử dụng Java Class để định nghĩa
ncy
Interceptor
Các thành phần cấu hình sử dụng Interceptor
StrutsInterceptorStackRefDependency
Stack (action, package)
Các thành phần cấu hình sử dụng Interceptor
StrutsInterceptorRefDependency
(action, package, interceptor stack)
StrutsConfigurationIncludedDepende Tệp cấu hình chính struts.xml khai báo cáo tệp
ncy
cấu hình con
StrutsActionConfigurationToJavaClas Tệp cấu hình sử dụng Java Class để định nghĩa
sDependency
Action
2.3.Phân tích phụ thuộc cơ sở dữ liệu của JDBC


Các ứng dụng Java sử dụng JDBC như là một chuẩn để truy xuất cơ sở dữ liệu.
24


JDBC chịu trách nhiệm quản lí kết nối với CSDL, gửi các câu truy vấn được tạo từ
Java tới CSDL và xử lí kết quả sau truy vấn thành các đối tượng của Java. Trong ứng
dụng doanh nghiệp, các câu truy vấn thường được tạo từ trước. Sau đó, qua quá trình
chỉnh sửa để phù hợp với nghiệp vụ, rồi được gửi cho CSDL bằng cách truyền vào
phương thức createQuery. Một ví dụ về sử dụng câu truy vấn được dùng trong ứng
dụng Sample như Mã nguồn 2.4.
Mã nguồn 2.4. Ví dụ một đoạn mã nguồn truy xuất CSDL bằng Java
public void printAddresses(int id) throws SQLException {
Connection con = DriverManager.getConnection("students.db");
String q = "SELECT * FROM address";
if (id!=0) q = q + "WHERE studentid=" + id;
ResultSet rs = con.createStatement().executeQuery(q);
while(rs.next()){
System.out.println(rs.getString("addr"));
}
}

Làm sao để biết được câu truy vấn cuối cùng có giá trị gì, gây ảnh hưởng đến
bảng nào của CSDL? Như ở Mã nguồn 3, để biết được điều đó ta phải xác định được
biến q trong phương thức executeQuery() có giá trị là gì. Giá trị này thực tế không thể
xác định chính xác hoàn toàn được do bị ảnh hưởng bởi các tham số khác. Hiên nay có
một số công cụ hỗ trợ phân tích dự đoán giá trị của một biến kiểu String như: JSA [2],
JDBC Checker [4],… Nhưng nhược điểm của các công cụ này là chỉ phân tích được
bằng bytecode, không thể phân tích trực tiếp mã nguồn của chương trình. Hơn nữa,
một vấn đề trong Java cũng như mã nguồn của các ngôn ngữ khác, một phần giá trị

của câu truy vấn có thể do hàm khác tạo nên. Ví dụ như Mã nguồn 2.5, phương thức
getAllRecords() là hàm tạo và sử dụng câu truy vấn, nhưng thông tin bảng nào được
truy vấn lại là tham số truyền vào. Trong khi đó, getUsers() phương thức gọi
getAllRecords() và truyền vào tên bảng trong CSDL là User. Vậy hàm getUsers() rõ
ràng là phương thức tương tác với CSDL. Phần lớn các công cụ hiện nay chỉ tập chung
xây dựng giá trị chuỗi mà không tập trung vào vấn đề này.
Do vậy cần thiết phải có một phương pháp để có thể dự đoán chính xác nhất các
giá trị có thể xảy ra của câu truy vấn và phương thức sử dụng chúng ngay từ mã
nguồn. Khóa luận này đề xuất một phương pháp phân tích không những dự đoán chính
xác câu truy vấn mà còn xây dựng một bộ dữ liệu để lưu trữ và quản lý các DAO
(phương thức thực hiện các câu truy vấn để truy cập và xử lý dữ liệu).
25


×