ĐẠ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 N
Trang 1TRONG 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
Trang 2ĐẠ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
Trang 3LỜI CẢM ƠN
Đầ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ọcHù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 góp quý báu trong cuộc sống Emcả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ácbạ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ờicả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ànhkhoá luận này
Tôi xin gửi lời cảm ơn đến những người bạn trong tập thể K59-CLC, những ngườibạ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
Tiếp theo tôi xin gửi lời cảm ơn đến các thầy cô giảng viên Trường Đại học CôngNghệ - Đại học Quốc Gia Hà Nội – những người đã tận tâm truyền đạt tất cả kiến thứcquý 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ônlớ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,
là điểm tựa tinh thần giúp tôi vượt qua những khó khăn, thử thách
VIETNAM NATIONAL UNIVERSITY, HANOI UNIVERSITY OF ENGINEERING AND TECHNOLOGY
Dinh Tien Loc
GENERATING BUSINESS DATA FLOWS
FOR ENTERPRISE APPLICATIONS BASED ON
SOURCE CODE ANALYSIS
THE BS THESIS Major: Information Technology
Supervisor: Assoc Prof Pham Ngoc Hung
HANOI – 2018
Trang 4TÓ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ầnthiế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ụngJ2EE 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êntrì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ôngnghệ 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áckiể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ởiviệ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ằngcá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ảochất lượng mã nguồn JCIA-VT JCIA-VT được xây dựng bằng ngôn ngữ Java JCIA-VTdù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âydự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
Trang 5Nowaday, Java and J2EE in particular is one of the best platform in order to build webapplication systems in large scale Through several maintenance upgrades, it is difficult forcompanies to control and ensure the quality of these applications because of the huge andcomplex source code On the other hand, for a heavy system, the issues related to the designare often extremely complex The data flows offers a perspective running through theapplication presenting all the application architecture based on transfering data betweencomponents, make companies easy to control their application
This study put forward a great ideas to generate data flows of J2EE application byanalyzing 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, thesource code is parsed to build a structure tree Next, the structure tree is got into the secondparser which finding and establishing dependency between node based on the detectedframework After that a graph of data flows in basic form is created by convert dependencyinto a set of edges, named data-edge Finally, all verticed in data flows are simplified, andedges are normalized by adding, removing or modifying to show the order of application’scomponent in transfering data It is considered a feature of JCIA-VT – the toolkit forguarantee the source code quality of J2EE applications JCIA-V is developed in Java Thepurpose of this toolkit is analyze source code of application that is build by frameworks suchas: Struts, Hibernate, JDBC, Spring, v.v This study also assess the correctness of this toolkitand 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 thistoolkit by support a variaty real-life application’s source code and response effectivefeedbacks in order to complete this tookit
Keywords: source code analysis, software quality assurance, data flows, dependency, J2EE
Trang 6LỜ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áocá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àntoàn chịu trách nhiệm theo quy định của trường Đại học Công Nghệ - Đại học QuốcGia Hà Nội
Hà Nội, ngày tháng … năm 20
Sinh viên
Đinh Tiến Lộc
Trang 7MỤC LỤC
Đặt vấn đề 1
Chương 1 Cơ sở nền tảng 3
1.1 Cây cấu trúc và tiền xử lý mã nguồn 3
1.1.1 Xử lý mã nguồn Java 4
1.1.2 Xử lý mã nguồn tệp XML và JSP 6
Chương 2 Phân tích sâu mã nguồn theo công nghệ và xây dựng phụ thuộc 10
2.1 Phân tích phụ thuộc mã nguồn Java Core 10
2.2 Phân tích phụ thuộc mã nguồn Struts 11
2.3 Phân tích phụ thuộc cơ sở dữ liệu của JDBC 13
2.3.1.1 Phân tích câu truy vấn dưới dạng biến 18
2.3.1.2 Phân tích câu truy vấn dưới dạng biểu thức trung tố 19
2.3.1.3 Phân tích câu truy vấn đầy đủ 20
2.4 Phân tích phụ thuộc mã nguồn Hibernate 20
2.4.1 Phân tích sự ánh xạ qua tệp cấu hình XML 23
2.4.2 Phân tích sự ánh xạ qua Java Annotation 24
2.4.3 Phân tích phương thức tương tác cơ sở dữ liệu 26
Chương 3 Phương pháp phân tích và xây dựng luồng dữ liệu 28
3.1 Phân tích cây cấu trúc và xây dựng luồng dữ liệu thô 28
3.2 Chuẩn hóa luồng dữ liệu 30
3.2.1 Xử lý cạnh hai chiều và loại bỏ chu trình 32
3.2.2 Xử lý chu trình dữ liệu trong đồ thị 34
Chương 4 Cài đặt công cụ và thử nghiệm 35
4.1 Giới thiệu tổng quan công cụ đảm bảo chất lượng mã nguồn JCIA-VT 35
4.2 Cài đặt thành phần phân tích phụ thuộc tương tác cơ sở dữ liệu 37
4.3 Cài đặt thành phần xây dựng luồng dữ liệu 42
4.4 Xây dựng giao diện hiển thị luồng dữ liệu 44
4.5 Ví dụ thử nghiệm 46
Trang 84.5.1 Hiển thị đồ thị phụ thuộc của mã nguồn 46
4.5.2 Đồ thị luồng dữ liệu 49
4.6 Thảo luận 50
Kết luận
52 Tài liệu tham khảo và phụ lục 53
Trang 9DANH MỤC HÌNH VẼ
Hình 2.1 Cấu trúc mã trung gian AST của mã nguồn Java 4
Hình 2.2 Cấu trúc mã trung gian bytecode của Mã nguồn 2.1 5
Hình 2.3 Quá trình xử lí mã nguồn tệp Java 5
Hình 2.4 Cấu trúc cây của mã nguồn XML 7
Hình 3.1 Quan hệ phụ thuộc thừa kế trong mã nguồn Java 10
Hình 3.2 Quan hệ phụ thuộc sử dụng trường trong mã nguồn Java 10
Hình 3.3 Quan hệ sử dụng phụ thuộc gọi phương thức trong mã nguồn Java 11
Hình 3.4 Mô hình thiết kế của ứng dụng Struts 2 12
Hình 3.5 Cơ chế hoạt động của Xwork 12
Hình 3.6 Cơ chế phân tích và xây dựng câu truy vấn từ mã nguồn 15
Hình 3.7 Mô tả cấu trúc AST của mã nguồn: “select ”+ “ * ” +“from ”+“Table” 19
Hình 3.8 Cấu trúc của Hibernate Framework 21
Hình 3.9 Quá trình phân tích sâu Hibernate 23
Hình 4.1 Quá trình phân tích và xây dựng luồng dữ liệu 28
Hình 4.2 Mô hình biểu diễn đồ thị luồng dữ liệu thô 30
Hình 4.3 Các bước chuẩn hóa luồng dữ liệu 31
Hình 4.4 Đồ thị luồng dữ liệu sau khi được loại bỏ các đường dư thừa 32
Hình 4.5 Mô hình luồng dữ liệu tường minh 33
Hình 4.6 Mô tả quá trình phân 33
Hình 4.7 Đồ thị luồng dữ liệu sau khi xử lý các cạnh hai chiều 33
Hình 4.8 Quá trình xử lý chu trình dữ liệu trong đồ thị 34
Hình 5.1 Các thành phần chính bộ công cụ JCIA-VT 35
Hình 5.2 Cấu trúc bộ quản lý DAO 38
Hình 5.3 Sơ đồ lớp thành phần phân tích tương tác CSDL 39
Hình 5.4 Cách thức gộp hai tập chuỗi theo tích Đề-các 40
Hình 5.5 Sơ đồ lớp trong gói operator 41
Hình 5.6 Sơ đồ lớp trong gói dependency của mô-đun phân tích tương tác CSDL 42
Hình 5.7 Sơ đồ lớp thành phần xây dựng luồng dữ liệu 43
Hình 5.8 Dữ liệu phần hiển thị của đồ thị luồng dữ liệu 44
Hình 5.9 Ví dụ về giá trị đỉnh và cạnh của dữ liệu phía giao diện 45
Hình 5.10 Màn hình đầu tiên của công cụ sau khi phân tích 46
Hình 5.11 Danh sách các bảng trong CSDL được phân tích từ mã nguồn 47
Hình 5.12 Ví dụ về phụ thuộc CSDL được bộ công cụ phân tích 47
Hình 5.13 Cách sử dụng chức năng luồng dữ liệu trong công cụ 49
Trang 10Hình 5.14 Ví dụ xây dựng luồng dữ liệu 50 Hình 5.15 Tài liệu lưu danh sách chi tiết phụ thuộc theo từng công nghệ 51 Hình 5.16 Tài liệu kiểm thử của bộ công cụ 51
Trang 11DANH MỤC MÃ NGUỒN
Mã nguồn 2.1 Ví dụ một đoạn mã nguồn do-while của Java 4
Mã nguồn 2.2 Ví dụ về nội dung của một tệp XML 6
Mã nguồn 2.3 Ví dụ về nội dung của một tệp JSP 9
Mã nguồn 3.1 Ví dụ một đoạn mã nguồn truy xuất CSDL bằng Java 14
Mã nguồn 3.2 Mã nguồn thể hiện sử dụng phương thức tương tác CSDL 15
Mã nguồn 3.3 Mã nguồn của một phương thức trong Java 17
Mã nguồn 3.4 Mã nguồn tệp cấu hình hibernate.cfg.xml 22
Mã nguồn 3.5 Mã nguồn tệp ánh xạ tên category.hbm.xml 23
Mã nguồn 3.6 Mã nguồn tệp User.java chứa thông tin ánh xạ bằng annotation 25
Mã nguồn 5.1 Mã nguồn thuật toán bố trí phân lớp chiều ngang 46
Mã nguồn 5.2 Mã nguồn phương thức findByStatus() 48
Mã nguồn 5.3 Mã nguồn phương thức findById() 48
Mã nguồn 5.4 Mã nguồn phương thức attachDirty() 49
Trang 12DANH MỤC BẢNG BIỂU
Bảng 2.1 Danh sách các thẻ kịch bản trong JSP 8
Bảng 3.1 Danh sách phụ thuộc trong Struts 13
Bảng 3.2: Thứ tự bộ phân tích truy vấn tùy theo các kiểu mã nguồn 17
Bảng 3.3: Phụ thuộc tương ứng với từng kiểu truy vấn 21
Bảng 3.4 Danh sách các phương thức truy xuất CSDL có sẵn của Hibernate 27
Trang 13DANH MỤC TỪ VIẾT TẮT
API Application Programming Interface Giao diện lập trình ứng dụng
DAO Data Access Object Các đối trượng Java phục vụ tương tác với cơ sở dự liệu
J2EE Java 2 Platform, Enterprise Edition Nền tảng phát triển các công
nghệ Web trên JavaJDBC The Java Database Connectivity Công nghệ tương tác với cở sở dữ liệu của Java
MVC Model-View-Controller 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
POJO Plain Old JavaObject Các đối tượng Java thuẩn chỉ để lưu trữ dữ liệu
Trang 14Đặ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 doanhnghiệ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ầnmề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ềutrườ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 Đồngthờ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ụnggặ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ảngWeb, 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ảithuậ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 ứngdụ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 đảmbả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ì quantrọ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ấtluô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étluồ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àndiệ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 TIOBE1) Java được tạo bởi công ty Sun Microsystems (naythuộc Oracle), là một ngôn ngữ lập trình hướng đối tượng, phục vụ để xây dựng ứngdụ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 https://www.tiobe.com/tiobe-index
Trang 15Java Web Theo khảo sát của trang TopITworks2, 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ồnvới mục đích khác nhau: Java để mô hình hóa dữ liệu và xây dựng nghiệp vụ, XMLdù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ấtlượ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ứcnă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 trongcá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ântí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ởiviệ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 trongCSDL 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áchthủ 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íchphụ 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 đượctrì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êncứu phát triển trong tương lai
2 https://www.topitworks.com/blogs/7-java-framework-pho-bien-nhat-hien-nay
Trang 16Chươ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ồnnhư Java, XML, HTML, JSP, v.v Mỗi định dạng lại có cấu trúc và cú pháp khácnhau Do đó, nhằm mục đích dễ dàng trong việc phân tích xử lý mã nguồn để xâydự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 = {n 1 , n 2 , , n k} 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 = {(n 1 , n 2 ) | n 1 , n 2 ∈ N) ⊆ N × N Mỗi mộtcạnh
(n 1 , p, n 2 ) đại diện cho một phụ thuộc giữa hai nút n 1 và n 2 với loại phụ thuộc p, khi đó
ta coi nút n 1 phụ thuộc nút n 2
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 n 2 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 n 2 là hàm bị gọi, “dữ liệu” được
hiểu là giá trị trả về của nút n 2 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 n 1 là phương thức sử dụng câu truy vấn tới
CSDL, n 2 là bảng trong CSDL bị tác động, “dữ liệu” của phụ thuộc này chính là câutruy 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à n 2 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 tinvới nhau
Trang 17Mã nguồn 1.1 Ví dụ một đoạn mã nguồn do-while của Java
public void doWhileLoop() {
MethodDeclaration
BlockVariableDeclareStatement
DoStatement
InfixStatementExpression
PostfixStatement
Hình 1.1 Cấu trúc mã trung gian AST của mã nguồn Java
3 https://www.eclipse.org/jdt/
4 http://www.eclipse.org/
Trang 18Hì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ếnhà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
Extract Source
code Parsing
Java File Node
Extract Class Attribute
Extract Extended Classes and Interfaces
Parse Java Method
Parse Java Field
Java Class Node AST
Build Java Class Node for JDG
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ácthà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
Trang 19thô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ầnthiế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ệpXML 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
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à
Trang 20số 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à danhsá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.
Document
(null) Text
Element
(null) Text
(null) Text
(null) Text
(null) Text
(null) Text
(null) Text
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ộidung độ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ầnchí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được quy định sẵn, gọi là JSTL (JavaServer Pages Standard Tag Library) Kiểu thứ hai
Trang 21là 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ếtthú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
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-Core5 Trong một trang JSP có thể dùngđượ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ẻ <
5 https://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/c/tld-summary.html
Trang 22%@ 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ănggiố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="http://java.sun.com/jsp/jstl/core" prefix="c" %>
Your number is <%= num %>.
<a href="<%= request.getRequestURI() %>"><h3>Try Again</h3></a>
tượng Document Cấu trúc của JSP khá tương tự HTML, ngoài việc có thể nhúng mã
nguồn Java thông qua thẻ <% %> Việc phân tích mã nguồn Java được nhúng trongtrang JSP cực kỳ khó khăn do các nội dung này phần lớn chỉ là xử lý lô-gíc, không liênquan đến một lớp hay đối tượng Java nào cả Do vậy, nhằm mục đích đơn giản hóaviệc phân tích các thẻ <% %> đều được loại bỏ trong tệp JSP để có thể sử dụng đượcvới Jsoup
Chương 2 Phân tích sâu mã nguồn theo công nghệ và xây dựng phụ thuộc
6 https://jsoup.org/
Trang 232.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ặcmột interface khác Như vậy, phụ thuộc thừa kế được chia thành hai kiểu: phụ thuộcthừ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.
public class B extends A {} public class A {}
JavaExtensionDependency
public class B implement A {} public interface A {}
JavaImplementationDependency
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ộttrườ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ảnnhấ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ếumột lớp
public class A {
protected int a1;
default int a2;
}
public class B {public int b;}
public class C extends A {
int getSuperA1() {return a1;}
int getSuperA2() {return a2;}
int getPublicB() {return new B().b;}
}
JavaFieldAccess Dependency
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
Trang 242 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 trongphươ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.
public static String hello() { return ũHello World!Ū;
} Public static sayHello() { String message = hello();
System.out.println(message);
}
JavaMethodInvocation Dependency
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
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
7 https://struts.apache.org/primer.html
Trang 25Web Browser
Controller
FilterDispatcher Interceptor
Action
View Result
Model
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.
Create Dispatcher Prepare Providers Load Container Create Configuration
Struts Configuration
͞4struts.xml͞6path
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
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ế key- value 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ụ
Trang 26thuộ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 chotrong 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
UseSimpleFieldActionDependency Jsp sử dụng struts-tag để gọi Action
StrutsPackageExtensionDependency Mối quan hệ thừa kế giữa hai thành phần cấu
hình packageStrutsInterceptorToJavaClassDepende
StrutsInterceptorStackRefDependency Các thành phần cấu hình sử dụng Interceptor Stack (action, package)StrutsInterceptorRefDependency Các thành phần cấu hình sử dụng Interceptor
(action, package, interceptor stack)StrutsConfigurationIncludedDepende
StrutsActionConfigurationToJavaClas
sDependency
Tệp cấu hình sử dụng Java Class để định nghĩa 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.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 ứngdụng doanh nghiệp, các câu truy vấn thường được tạo từ trước Sau đó, qua quá trìnhchỉ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 {
DriverManager.getConnection("students.db");
String q = "SELECT * FROM address";
if (id!=0) q = q + "WHERE studentid=" + id;
ResultSet rs = con.createStatement().executeQuery(q);
Trang 27nay 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ântí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ầngiá 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 chungxâ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ácgiá 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ínhxá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)
Mã nguồn 2.5 Mã nguồn thể hiện sử dụng phương thức tương tác CSDL
public ResultSet getAllRecords(String tbl) {
String query = “Select * from ” + tbl;
List<User> users = new ArrayList<>();
// chuyển dữ liệu của đối tượng rs về dữ liệu của users
return users;
}
Bộ phân tích câu truy vấn được xây dựng dựa trên mẫu thiết kế Visitor [7] Cấu
trúc bộ phân tích được minh họa như Hình 2 10, gồm bốn phần chính: JDBC Import
Trang 28Filter, Hotspot Finder, Query Analyzer và Value Tracer
Hình 2.10 Cơ chế phân tích và xây dựng câu truy vấn từ mã nguồn
Hotspot là những vị trí trong mã nguồn Java, nơi mà mã nguồn Java thực hiện
câu truy vấn CSDL Đối với JDBC, hotspot là nơi sử dụng phương thức
createQuery() Để tìm các hotspot này, đầu tiên, JDBC Import Filter sẽ lọc ra những
mã nguồn Java có khả năng là DAO Quá trình lọc này dựa trên ba tiêu chí
Mã nguồn có import java.sql.*,
Mã nguồn có import lớp java.sql.Connection,
Mã nguồn có import lớp java.sql.Statement, java.sql.Statement hoặc java.sql.Statement.
Nếu mã nguồn của một tệp Java chỉ cần đảm bảo được một trong ba tiêu chí này,tệp đó đó sẽ được đưa vào một tập tiềm năng Tiếp theo, mã nguồn của tất cả các tệp
tiềm năng này được quét bằng AST Visitor AST Visitor sẽ đi vào từng thành phần
trong mã nguồn, vào sâu đến tận thành phần nhỏ nhất như các biến của các câu lệnhtrong phương thức Bất cứ khi nào phát hiện có sự sử dụng phương thức
createQuery(), AST Visitor sẽ thông báo cho Hotspot Finder Nhiệm vụ của Hotspot Finder lúc này là kiểm tra xem phương thức có thực sự là dùng để tương tác CSDL
hay không bằng cách kiểm tra tham số Nếu phương thức này sử dụng duy nhất một
tham số, và tham số đó ở dạng String hoặc một đối tượng khác như sử dụng phương thức toString(), phương thức sẽ được chấp nhận và tham số sẽ được đưa vào bộ Query
Trang 29Analyzer Nếu không thỏa mãn điều kiện đó, phương thức sẽ bị bỏ qua và AST Visitor
tiếp tục quá trình quét
Với mỗi một hotspot, bộ quản lý DAO sẽ tạo ra một bộ mô tả tương tác dữ liệu (Data Access Descriptor) để lưu trữ các thông tin trong quá trình phân tích như là tập
câu truy vấn, danh sách các bảng trong CSDL được sử dụng, phương thức sử dụng,v.v Bộ quản lý DAO sẽ đảm bảo trong suốt quá trình phân tích truy vấn của mộtphương thức, chỉ có một bộ mô tả được tạo ra và có thể sử dụng mọi lúc trong quátrình phân tích Nếu kết thúc quá trình phân tích không xảy ra lỗi và phát hiện đượcbảng có tham gia vào câu truy vấn, việc phân tích được coi là thành công, bộ mô tảhiện tại sẽ chứa đầy đủ thông tin về việc tương tác dữ liệu và được lưu trữ vào danhsách của bộ quản lý DAO Một bộ mô tả mới tiếp tục được tạo ra để lưu trữ thông tincho hotspot tiếp theo
Query Analyzer đảm nhận nhiệm vụ phân tích cụ thể tham số của
createQuery(), kết hợp với bộ Value Tracer để xây dựng giá trị của chuỗi theo thứ
tự xử lý câu lệnh của mã nguồn Tham số truyền vào sẽ thuộc một trong bốn nhãn nhưsau
Raw Statement: Tham số là một câu truy vấn đầy đủ
Tương ứng với bốn nhãn là bốn kiểu phân tích tương ứng: Infix Analyzer, Method Analyzer, Variable Analyzer, Raw Statement Analyzer Chi tiết nhiệm việc phân loại
tham số và các kiểu phân tích tương ứng được cho trong Bảng 2 3 Do đặc thù mỗimột kiểu tham số là khác nhau, nên một kiểu tham số tương ứng với một nhãn sẽ được
phân tích bởi bộ phân tích khác nhau Với nhãn Infix tương ứng với biểu thức, bộ phân tích biểu thức Infix Analyzer được sử dung Với nhãn Variable tương ứng với một biến, bộ phân tích biến Variable Analyzer được sử dụng Tương tự như vậy với tham
số là phương thức, hoặc một giá trị chuỗi cụ thể, các bộ phân tích Method Analyzer hoặc Raw Statement Analyzer được sử dụng.
Trong các bộ phân tích, bộ phân tích phương thức là đơn giản nhất Do giá trị
thay thế của phương thức trong Java chính là biểu thức trong câu lệnh return Với một
phương thức như Mã nguồn 2 .6, khi sử dụng trong biểu thức
Trang 30“from”+getTableName(), thì giá trị của biểu thức đó sẽ tương đương
“from”+“Table”.
Mã nguồn 2.6 Mã nguồn của một phương thức trong Java
public String getTableName() { String tbl = “Table”;
return tbl;
}
Bảng 2.3: Thứ tự bộ phân tích truy vấn tùy theo các kiểu mã nguồn
createQuery(query) SimpleName Variable Variable Analyzer
createQuery(“from…”)
Analyzer
Như vậy, thay vì phân tích cả phương thức, ta chỉ cần phân tích câu lệnh return.
Tương tự như tham số của phương thức createQuery(), câu lệnh return có thể chứa
biểu thức thuộc cả bốn kiểu nhãn Do đó, bộ phân tích phương thức phải xác định xem
biểu thức trong câu lệnh return sử dụng kiểu biểu thức nào Sau đó, tùy vào kiểu biểu
thức là biểu thức trung tố, biến, phương thức hay là chuỗi để sử dụng bộ phân tích hợp
lý Ví dụ như Mã nguồn 2 6, biểu thức trong câu lệnh return là một biến có tên tbl.
Do đó, bộ phân tích phương thức phải sử dụng bộ phân tích biến để đoán nhận giá trịchỗi của biến này
2.3.1.1 Phân tích câu truy vấn dưới dạng biến
Theo AST, biến trong mã nguồn Java được thể hiện là kiểu SimpleName Để tìm
giá trị chuỗi mà biến này lưu trữ, ta cần phải “giả lập” đoạn mã nguồn có thao tác vớibiến, nghĩa là xây dựng giá trị của chuỗi bằng cách thực hiện lại cách thức giá trị củabiến được thay đổi trong mã nguồn Bộ phân tích sẽ truy ngược lại nơi mà biến được
khởi tạo, và bắt đầu thực hiện việc truy vết Mỗi một vết là một vị trí trong mã nguồn,
nơi giá trị của biến bị thay đổi Sau đó, tùy vào câu lệnh, bộ phân tích sẽ thực hiện lạigiống hệt cách thức mà giá trị của biến bị thay đổi Sau quá trình này, giá trị tính toáncủa biến được lưu lại trong bộ phân tích Có hai cách thức thay đổi của giá trị chuỗi
của một biến: công gộp (sử dụng toán tử “+”) và sử dụng các phương thức xây dựng
Trang 31sẵn (replace, trim, insert, v.v.).
Trong trường hợp gặp một vết kiểu cộng gộp chuỗi đơn giản (ví dụ var + “b”), chuỗi “b” sẽ được gộp trực tiếp vào giá trị của biến var mà đang bộ phân tích đang
đoán nhận Trong trường hợp thành phần được cộng gộp là một biến khác hoặc một
phương thức, tương ứng Variable Analyzer hoặc một Method Analyzer khác sẽ được
sử dụng và phân tích giá trị chuỗi cho biến hoặc phương thức mới đó, giá trị sau khiphân tích sẽ được thêm vào giá trị chuỗi đang được đoán nhận hiện tại
Trong trường hợp gặp vết là một phương thức xây dựng sẵn, bộ phân tích phải sử
dụng thêm bộ String Manipulation để cập nhật lại chuỗi theo từng phương thức Đầu vào của String Manipulation là tập truy vấn đang được đự đoán ở hiện tại, cùng với các thông tin của phương thức như: tên, tham số đi kèm, v.v Như hiện tại bộ String Manipulation mới xử lý được cho các phương thức cơ bản như: replace (Replace Operation), trim (Trim Operation), insert (Insert Operation), v.v
Ngoài đối tượng String, trong Java, có một kiểu đối tượng dùng để lưu giá trị chuỗi như StringBuilder, StringBuffer Các lớp của đối tượng này đều kế thừa lớp Appendable Lớp Appendable định nghĩa cách thức cộng gộp giá trị chuỗi bằng phương thức append() Do có tính chất tương tự một biến đơn giản, nên các đối tượng
này được coi như là một biến Để sử dụng giá trị chuỗi được lưu bên trong, các đối
tượng này phải sử dụng phương thức toString() Như vậy, bộ phân tích phải xác định những vị trí mà biến sử dụng phương thức toString() Sau đó, truy ngược lại vị trí biến được khởi tạo để kiểm tra biến có thuộc các đối tượng loại Appendable hay không Nếu có, bộ phân tích sẽ tìm các vị trí thay đổi giá trị của biến là phương thức append()
và các phương thức xây dựng sẵn khác để thực hiện việc đoán nhận giá trị
2.3.1.2 Phân tích câu truy vấn dưới dạng biểu thức trung tố
Như đã nêu ở mục trước, tham số của biểu thức trung tố có dạng: a 1 +a 2 +a 3 +… trong đó a i (i ∈ N) có thể là một hàm, biến, chuỗi String hoặc có thể là một biểu thức trung tố khác Thực chất, a i có thể là bất kỳ đối tượng nào, kể cả số, nhưng phiên bảnnày chỉ xét đến những đối tượng có thể quy về chuỗi, và bỏ qua các kiểu dữ liệu khác
Do biểu thức không thể có toán tử nào khác ngoài toán tử “+”, nên cấu trúc AST chiabiểu thức thành bốn phần:
Toán hạng trái: Toán hạng đầu tiên của biểu thức (a 1)
Trang 32 Toán hạng phải: Toán hạng thứ hai của biểu thức (a 2)
Tập toán tử mở rộng: Tập các toán hạng tiếp theo (a 3 , a 4 , a 5,…)
Hình 2.11 Mô tả cấu trúc AST của mã nguồn: “select ”+ “ * ” +“from ”+“Table”
Ví dụ với mã nguồn “select ” + “* ” + “from ” + “Table” , cấu trúc AST sẽ được
xây dựng như Hình 2 11 Đại diện của biểu thức trung tố trong AST là đối tượng
InfixExpression Toán hạng trái của biểu thức là chuỗi “select” Toán tử sử dụng trong biểu thức là phép “+” Toán hạng phải của biểu thức là chuỗi “*” Còn lại, tập toán tử
mở rộng có hai phần tử: chuỗi “from” và chuỗi “Table”.
Cần lưu ý rằng, vị trí của cặp đóng mở ngoặc “()” gây ảnh hưởng đến thứ tự các
toán tử Với biểu thức (a 1 + a 2 )+ a 3 + a 4 + …, toán hạng trái là a 1 + a 2, toán hạng phải
là a 3 còn tập toán tử mở rộng là a 4 , a 5 , … Còn với biểu thức a 1 + (a 2 + a 3 ) + a 4 + … thì
toán hạng trái lại là a 1 , toán hạng phải là a 2 + a 3 và tập toán tử mở rộng là a 4 , a 5, … Từng toán hạng trong biểu thức trung tố sẽ được đưa đoán nhận giá trị theo đúngthứ tự từ trái sang phải Tùy theo mỗi kiểu thể hiện của từng toán hạng, bộ phân tíchbiểu thức trung tố sẽ sử dụng một bộ phân tích khác nhau:
Toán hạng là một chuỗi (kiểu StringLiteral theo AST), giá trị chuỗi sẽ được
thêm gộp trực tiếp vào giá trị dự đoán của bộ phân tích
Toán hạng là một biến hoặc phương thức toString() của đối tượng dạng Appendable (sử dụng phương thức append()), bộ phân tích biến được khởi tạo
Trang 33 Toán hạng là một biểu thức trung tố nhỏ hơn, bộ phân tích biểu thức trung tốkhác được sử dụng để phân tích toán hạng này.
Tất cả giá trị chuỗi được phân tích bởi mỗi toán hạng đều được thêm vào tập giá trị dựđoán của bộ phân tích theo đúng thứ tự của toán hạng đó trong biểu thức
2.3.1.3 Phân tích câu truy vấn đầy đủ
Bộ phân tích câu truy vấn đầy đủ được sử dụng khi tham số truyền vào phương
thức createQuery() là một chuỗi Nhưng trong thực tế, đây thường là bước cuối cùng
sau khi các bộ phân tích câu truy vấn phức tạp khác phân tích xong Đầu tiên, câu truyvấn sẽ được chia nhỏ thành một tập các từ Tập các từ sẽ được chuẩn hóa (loại bỏ kí tựrỗng, loại bỏ khoảng trắng,…), sau đó lần lượt được kiểm tra Nếu bộ phân tích so
sánh thấy một từ giống với một trong các từ như: from, update, delete, join,… thì từ ở ngay sau đó sẽ chính là tên bảng Nếu từ này là các chuỗi như “null”, ”undefined” thì
bỏ qua Còn lại sẽ được lưu vào trong Invoking Descriptor hiện tại Và cuối cùng phụthuộc giữa hàm gọi với bảng được tạo tùy theo kiểu câu truy vấn Bảng 2 4 liệt kêdanh sách quan hệ phụ thuộc giữa phương thức với bảng trong CSDL Nếu phươngthức có sử dụng câu truy vấn, và câu truy vấn có mục đích xóa dữ liệu Khi đó, giữa
phương thức với bảng được sử dụng sẽ có phụ thuộc SQLDeleteDependency Tương
tự, khi câu truy vấn có mục đích thêm dữ liệu vào CSDL, phụ thuộc sẽ là
SQLInsertDependency, v.v.
2.4 Phân tích phụ thuộc mã nguồn Hibernate
ORM Framework (Object Relational Mapping Framework) là những công nghệgiúp chuyển đổi và ánh xạ cấu trúc dữ liệu từ những hệ thống không tương thích vềđối tượng phù hợp Hibernate là một trong những công nghệ này, ánh xạ các bảng
trong CSDL với Persistent Objects Các Persistent Objects là các lớp Java (goi là thực
thể)
Bảng 2.4: Phụ thuộc tương ứng với từng kiểu truy vấn
SQLDeleteDependency Phương thức DAO truy vấn xóa bản ghi
SQLInsertDependency Phương thức DAO truy vấn thêm bản ghi
SQLInsertOrUpdateDependency Phương thức DAO truy vấn thêm hoặc cập nhật bản ghiSQLSelectDependency Phương thức DAO truy vấn lấy thông tin bản ghi
SQLUpdateDependency Phương thức DAO truy vấn cập nhật bản ghi
Trang 34Hibernate được xây dựng trên nền của JDBC để quản lí và cải tiến các thao tác đến
CSDL Hibernate sử dụng hai phương pháp ánh xạ là dùng tệp XML hoặc dùng Java Annotation để định nghĩa thông tin bảng trong lớp Java Cấu trúc của Hibernate và vị
trí của nó trong ứng dụng Java được thể hiện như trong Hình 2 12
Hình 2.12 Cấu trúc của Hibernate Framework
Ứng dụng sử dụng Hibernate phải sử dụng một tệp cấu hình Tệp cấu hình có thể
là một tệp XML (tên là hibernate.cfg.xml) hoặc là một tệp properties (hibernate.properties) dưới dạng key-value Tệp hibernate.properties chỉ có thể chứa
các tham số cấu hình việc kết nối như đường dẫn đến CSDL, tài khoản/mật khẩu kếtnối CSDL, driver thực hiện kết nối và nhiều thông tin khác Còn đối với tệp
hibernate.cfg.xml, ngoài chứa các tham số kể trên, nó còn có thể chứa thông tin của những tệp mô tả việc ánh xạ Một ví dụ của tệp hibernate.cfg.xml được mô tả như Mã
nguồn 2 7 Trong trường hợp ứng dụng định nghĩa cả hai loại cấu hình XML vàProperties, Hibernate sẽ ưu tiên sử dụng tệp cấu hình XML
Mã nguồn 2.7 Mã nguồn tệp cấu hình hibernate.cfg.xml
?xml version='1.0'encoding='utf-8'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
2.0.dtd">
Trang 35jdbc:mysql://localhost:3306/Sample
</property>
<property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">pass</property> <property name="hibernate.show_sql">true</property>
<mapping resource="book.hbm.xml" />
</session-factory>
</hibernate-configuration>
Quá trình phân tích sâu mã nguồn của Hibernate được mô tả như Hình 2 13, tệp
hibernate.cfg.xml được chuyển từ kiểu nút XmlFileNode thành kiểu nút HibernateConfigNode Sau đó, nội dung của tệp này được xử lý, các thẻ XML được phân tích Các thẻ khai báo thông tin ánh xạ được chuyển từ kiểu nút XmlTagNode thành kiểu nút HibernateCfgMappingNode Nút này có lưu một thuộc tính là typeMapping thể hiện kiểu khai báo Với kiểu ánh xạ bằng XML, thẻ khai báo ánh xạ
(thẻ <mapping>) có thuộc tính resource với giá trị là đường dẫn tệp ánh xạ XML,
khi đó giá trị của typeMapping được lưu thành “xml” Còn kiểu ánh xạ bằng Java
Annotation, thẻ khai báo ánh xạ có thuộc tính class với nội dung là tên lớp Java với
đầy đủ package, giá trị của typeMapping được lưu là “annotation” Tùy vào từng kiểu
khai báo ánh xạ, ta sẽ tìm được tệp ánh xạ tương ứng, hoặc XML hoặc Java Tệp ánh
xạ này tiếp tục được đưa vào phân tích để tạo thành nút DatabaseTableNode chứa
thông tin về tên bảng, các cột, v.v đại diện cho các bảng trong CSDL Cuối cùng, các
nút DatabaseTableNode sẽ được chứa trong nút DatabaseSchemaNode 8 và thêm như
là con của nút gốc trong JDG
Parse
hibernate.cfg.xml
with Decorator Pattern
Find mapping file Parse mapping file
Hình 2.13 Quá trình phân tích sâu Hibernate
8 Nếu nút DatabaseTableNode có định nghĩa thông tin schema thì sẽ thuộc nút DatabaseSchemaNode với tên schema tương ứng Nếu không định nghĩa, nút DatabaseTableNode sẽ thuộc nút DatabaseSchemaNode được tạo
ra mặc định bởi bộ phân tích