Vous êtes sur la page 1sur 66

Individual Assignment

DISTRIBUTED COMPUTER SYSTEMS

NEEZ FOOD DELIVERY SYSTEM


Name

: SHAMNEEZ MOHAMUDBUCUS

Student ID

: TP022221

Intake

: UC3f1211SE

Module CODE

: CT024 3 3 DCOMS

Lecturer

DR. MOHD AMRIL NURMAN BIN MOHD

NAZIR

Submission DATE

: 13 august 2013

DUE DATE

: 23 august 2013

Distributed Computer Systems

2013

ACKNOWLEDGEMENT.......................................................................................................4
ABSTRACT..............................................................................................................................4
GANTT CHART......................................................................................................................5
1.0

INTRODUCTION........................................................................................................6

2.0

PROGRAM DESIGN..................................................................................................7

2.1

Screen Design..............................................................................................................7

2.1.1

Login Interface...............................................................................................................7

2.1.2

Select and Purchase Food Interface................................................................................7

2.1.3

Personal Details Interface..............................................................................................8

2.1.4

Wallet Interface..............................................................................................................8

2.2
3.0

Use Case Diagram.......................................................................................................9


IMPLEMENTATION................................................................................................10

3.1

Technical Document..................................................................................................10

3.1.1

Relationship between the different Packages...............................................................10

3.1.2

Class Diagram..............................................................................................................10

3.1.3

Concepts Used in Application......................................................................................12

3.1.3.1

File handling using Arrays....................................................................................................12

3.1.3.2

Swing Components................................................................................................................12

3.1.3.3

Remote Method Invocation (RMI).......................................................................................12

3.1.4

Questions Answered.....................................................................................................12

3.1.4.1

QUESTION 1.........................................................................................................................12

File Handling for Registering User (LoginRegistrationFunctions.java).............................................13


Adding User Details to User.txt File (UserPanelFunctions.java).......................................................14
Implementing Clear and Register Button (LoginUI.java)..................................................................15
3.1.4.2

QUESTION 2.........................................................................................................................16

File Handling for User Login (LoginRegistrationFunctions.java).....................................................16


Validations for Username and Password Textboxes (Validation.java)................................................17
Implementation For Login Button (LoginUI.java).............................................................................17
3.1.4.3

QUESTION 3.........................................................................................................................18

File Handling for Getting Balance (Functions.java)...........................................................................18


Implementing Refresh Button for Balance (TransactionPanel.java)..................................................19
Calculating New Balance and Updating Balance.txt (TransactionFunctions.java)............................19
File Handling for Credit Card Number and CVV2 Code (TransactionFunctions.java).....................20
Validating Amount (Validation.java)..................................................................................................21
Validating Credit Card Length (Validation.java)................................................................................22
Validating CVV2 Code (Validation.java)...........................................................................................22
Implementing Deposit Button (TransactionPanel.java)......................................................................23
SHAMNEEZ MOHAMUDBUCUS TP022221

Distributed Computer Systems


3.1.4.4

2013

QUESTION 4.........................................................................................................................24

File Handling for Getting Food List and Food Code (Functions.java)...............................................24
Displaying Food Image and List (FoodMenuFunctions.java)............................................................25
Displaying Food Details on Interface (FoodMenuPanel.java)...........................................................26
3.1.4.5

QUESTION 5.........................................................................................................................26

IRemote.java.......................................................................................................................................27
Obj.java...............................................................................................................................................28
File Handling for Purchase (Functions.java and FoodMenuFunctions.java).....................................31
Performing Purchase and Generating Receipts (FoodMenuFunctions.java)......................................35
Put Food Items in Order Table (Functions.java).................................................................................36
Setting Order Table (FoodMenuFunctions.java).................................................................................36
Update Order Table with New Orders (FoodMenuFunctions.java)....................................................36
Checking Customer Order Quantity against Food Quantity (FoodMenuFunctions.java)..................37
Check Customer Order Quantity with Food Quantity (FoodMenuFunctions.java)...........................38
Implementing Discard Button (FoodMenuPanel.java).......................................................................38
Implementing Order Button (FoodMenuPanel.java)..........................................................................39
Implementing Confirm Button (FoodMenuPanel.java)......................................................................40
3.1.4.6

QUESTION 6.........................................................................................................................41

File Handling for Voucher.txt (TransactionFunctions.java)................................................................41


Validating Voucher Code (Validation.java).........................................................................................43
Implementing Check Voucher Button (TransactionPanel.java)..........................................................44
Implementing Confirm Voucher Button (TransactionPanel.java).......................................................44
3.1.4.7

QUESTION 7.........................................................................................................................45

Implementing SSL for Receiving Cash (Server.java).........................................................................45


Implementing SSL for Sending Cash (Server.java)............................................................................45
Implementing Server for SSL (ServerImpl.java)................................................................................46
3.1.4.8

QUESTION 8.........................................................................................................................46

File Handling for Updating Quantity (FoodMenuFunctions.java).....................................................47


Update Quantity Function (FoodMenuFunctions.java)......................................................................48

3.1.5

Additional Components Encryption of User Details.................................................49


Encryption Code (SecurityFunctions.java).........................................................................................49
Decryption Code (SecurityFuctions.java)...........................................................................................49
Algorithm for Encryption (SecurityFunctions.java)...........................................................................49
Implementing the Encryption for attributes (UserPanelFunctions.java)............................................49

3.2

User Document..........................................................................................................50

3.2.1

Running the Server.......................................................................................................50

3.2.2

Login Interface.............................................................................................................50

3.2.3

User Details Interface...................................................................................................51

3.2.4

Food Menu and Purchase Interface..............................................................................51

SHAMNEEZ MOHAMUDBUCUS TP022221

Distributed Computer Systems


3.2.5

4.0

2013

Transaction Interface....................................................................................................52

TESTING....................................................................................................................53

4.1

Unit Testing Table......................................................................................................53

4.2

Test Results................................................................................................................55

5.0

CRITICAL EVALUATION.......................................................................................63

5.1

Limitations.................................................................................................................63

5.2

Future Enhancements................................................................................................63

6.0

CONCLUSION...........................................................................................................64

REFERENCES.......................................................................................................................65

SHAMNEEZ MOHAMUDBUCUS TP022221

Distributed Computer Systems

2013

ACKNOWLEDGEMENT
I am grateful to the ALMIGHTY ALLAH, The Most Merciful for enabling me to
complete this assignment with success. My inspiration for building the two applications
successfully came from my lecturer, Dr Amril, who kept motivating me throughout the
semester to improve my work and present fully workable systems at the end. I would like to
thank my lecturer for giving me feedback on my work from time to time, keeping track of my
work and trusting my abilities to deliver a project of this quality.
I would like to show my gratitude to my parents, who have done a lot of sacrifices and
efforts to bring me to this stage, by giving me moral and financial support throughout my life
as well as physical support when I fell seriously ill during my sixth semester. Without them, I
would not have been able to complete my last semester. I would like to thank the most
wonderful mom and dad for making me what I am today.

ABSTRACT
This assignment is about developing a Food Delivery System, using the RMI (Remote
Method Invocation) Technology. The document introduces the system and its functions. It
discusses the different stages of development.
The design section consists of screen design and use case diagram. Coming to the
implementation, it consists of the technical document which has the code listings and
explanations for the major components as well as answering the questions of the assignment
and the user document which explains the program functioning.
The testing section is about the different tests performed and the results given in the
test results section. After testing is done, a critical evaluation of the system is done and the
document is concluded.

SHAMNEEZ MOHAMUDBUCUS TP022221

Distributed Computer Systems

2013

GANTT CHART

SHAMNEEZ MOHAMUDBUCUS TP022221

Distributed Computer Systems

1.0

2013

INTRODUCTION
Neez Food Delivery System has been developed in Netbeans, using the Remote

Method Invocation (RMI) technology in Java. It consists of designing a fully functional


program to allow users to do the following:

Select and Purchase Food of their choice over a secure connection


Store their personal details
Send Cash Vouchers to other accounts over a secure connection
Deposit money in their own account through credit card over a secure connection
The RMI Technology is used to create simple distributed system that can be invoked

from other java virtual machines, possibly from different hosts (Oracle, 2013). The Food
Delivery System has been developed using Graphical User Interfaces (GUIs) in order to
provide user-friendly environment for customers. Security Module, namely Secure Socket
Layer (SSL) protocol has been used to manage security of the application as it deals with
purchase, credit cards and money transfer.
The aim of the project was to provide a fully functioning application to show
functioning of a distributed system involving security. In the following sections, the different
stages of development have been described and questions related to the assignment have been
answered.

SHAMNEEZ MOHAMUDBUCUS TP022221

Distributed Computer Systems

2.0

2013

PROGRAM DESIGN
The program design consists of the primary idea of the system which includes designs

of the screens and the Use Case Diagram for the system.

2.1

Screen Design
The different interfaces for the system have been given, with description as follows.
2.1.1

Login Interface

The Login Interface allows a new customer to register and an existing customer to log
into the system.

2.1.2

Select and Purchase Food Interface

The user can select the food he wants and then purchase it via this interface.

SHAMNEEZ MOHAMUDBUCUS TP022221

Distributed Computer Systems


2.1.3

2013

Personal Details Interface

The personal details interface allows the user to key in his personal details such as
phone number and address and then click on the save button to save the details.

2.1.4

Wallet Interface

The wallet interface allows the customer to deposit money in his account using a valid
credit card number and transfer valid vouchers to another customer account.

SHAMNEEZ MOHAMUDBUCUS TP022221

Distributed Computer Systems


2.2

2013

Use Case Diagram


The Use Case Diagram represents all the activities that a user can do in the Food

Delivery System.

Customer

SHAMNEEZ MOHAMUDBUCUS TP022221

Distributed Computer Systems

3.0

IMPLEMENTATION

3.1

Technical Document
3.1.1

2013

Relationship between the different Packages

The diagram below shows the relationship between the different packages of the
application. The two-way arrows show that the relationship is two-way (classes of both
packages depend on each other to a certain extent) while the single directional arrow show
that the relationship is one way only (the classes of one package depends partially on the
pointed package).

3.1.2

Class Diagram

The Class Diagram on the following page shows the relationships between all the
classes in the system. The dotted lines represent dependencies of the classes of each other
while the single line arrows show that the classes make use of the other classes as a whole.
For example, the classes FoodMenuPanel, UserPanel, TransactionPanel and LoginUI depend
on the ClientMain class in order to obtain the username and password to identify the user
during transactions while the ClientMain class needs the classes User and IRemote to
authenticate the customer using the application.

SHAMNEEZ MOHAMUDBUCUS TP022221

10

Distributed Computer Systems

SHAMNEEZ MOHAMUDBUCUS TP022221

2013

11

Distributed Computer Systems


3.1.3

2013

Concepts Used in Application

Various concepts have been used in the implementation of the application listed
below.
3.1.3.1

File handling using Arrays

In order to be able to read and write from the text files, arrays have been used.
3.1.3.2

Swing Components

Swing implements a set of GUI components that is built on the Abstract Windows
Toolkit (AWT) technology that provides a pluggable look and feel (EDN, 1994).
3.1.3.3

Remote Method Invocation (RMI)

The RMI technology is a way which a programmer, using the Java programming
language and development environment, writes object-oriented programming in which
objects on different computers can interact in a distributed network.
It is also important to draw attention to the fact that different packages have been created
with classes related to functions, interfaces, security, server and main classes (server and
client). This has been done to provide an organized way of writing the codes for better
understanding.
The codes related to the questions have been broken down into different parts, namely,
File Handling, Interface and Validations. The class name and test number of tests related to
each question have been given in each part.
3.1.4

Questions Answered
3.1.4.1

QUESTION 1

A new user should be able to register a new account to the online food delivery system. The
user should be able to register by using his/her username and password. If the username
exists in the system, the user will be notified to enter a different username. (See Test# T2T3)
ANSWER:
The customer can register/log into the system through the login interface (shown in
the User Document). When the user registers with his username and password, it is checked
for existence in the User.txt file and an error message is displayed if the username already
SHAMNEEZ MOHAMUDBUCUS TP022221

12

Distributed Computer Systems

2013

exists. The code handling registration of new Users is given below. When the registration is
accepted, a record is created in the Balance.txt for the user to update his balance.
File Handling for Registering User (LoginRegistrationFunctions.java)
The registerUser() method is used to get the user details in order to store them in the
User.txt file. The code given creates a User.txt File if the file doesnt exist and add a new
record to the file, with the username and password from the registration screen.
//register user writing details to files
public static int registerUser(User p) {
int iRet = -1;
String path = System.getProperty("user.dir") + "/src/Database
Files/User.txt";
File file = new File(path);
String username = p.getUsername();
String password = p.getPassword();
String name = " ";
String ic = " ";
String phoneNo = " ";
String address = " ";
String email = " ";
String newUserRecord = username + ";" + password + ";" + name + ";"
+ ic + ";" + phoneNo + ";" + address + ";" + email + ";";
try {
//if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
//true = append file; false = overwrite
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true));
writer.write(newUserRecord);
writer.newLine();
writer.close();
//create an initial balance record
insertBalanceRecord(p.getUsername());
} catch (Exception e) {
System.out.println("RegisterUser Exception: " + e);
}
return iRet;}
//insert balance record for new user
public static void insertBalanceRecord(String username) {
try {
String newBalance = "0.00";
String newBalanceRecord = username + ";" + newBalance + ";";
String path = System.getProperty("user.dir") + "/src/Database
Files/Balance.txt";
File file = new File(path);
//if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();}
//true = append file; false = overwrite
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true));
writer.write(newBalanceRecord);
writer.newLine();
writer.close();
} catch (Exception e) {
System.out.println("insertBalanceRecord Exception: " + e); }}
SHAMNEEZ MOHAMUDBUCUS TP022221

13

Distributed Computer Systems

2013

Adding User Details to User.txt File (UserPanelFunctions.java)


Once the User enter all his details and clicks on save button, all the data, excluding
the username and password is encrypted and written to the User.txt file via an array, without
changing the username and password.
//after encryption //write update to file
String path = System.getProperty("user.dir") + "/src/Database
Files/User.txt";
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
StringBuilder fileContent = new StringBuilder();
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
String user[] = strLine.split(";");
if (user.length > 0) {
if (user[0].equals(username)) {
//user[1] password remains unchanged
user[2] = name;
user[3] = ic;
user[4] = phone;
user[5] = address;
user[6] = email;
String newLine = user[0] + ";" + user[1] + ";" + user[2] + ";" + user[3] +
";" + user[4] + ";" + user[5] + ";" + user[6] + ";";
fileContent.append(newLine);
fileContent.append("\r\n");
} else {
// update content as it is
fileContent.append(strLine);
fileContent.append("\r\n"); } }}
// Now fileContent will have updated content,which u can override into file
String path2 = System.getProperty("user.dir") + "/src/Database
Files/User.txt";
FileWriter fstreamWrite = new FileWriter(path2);
BufferedWriter out = new BufferedWriter(fstreamWrite);
out.write(fileContent.toString());
out.close();
//Close the input stream
in.close();
} catch (Exception e) {//Catch exception if any
System.out.println("Update Personal Details Error: " +
e.getMessage());}//display msg
JOptionPane.showMessageDialog(null, "Personal Details Saved.",
"Details Saved", JOptionPane.INFORMATION_MESSAGE);}

SHAMNEEZ MOHAMUDBUCUS TP022221

14

Distributed Computer Systems

2013

Implementing Clear and Register Button (LoginUI.java)


The clear button found in the Registration/Login Interface can reset all the textboxes
by clearing all the data. When the register button is clicked, the validateUsername() method
is called from the Validation class in order to check for existence of the username in the
User.txt file and generates an error message in case of existing username. In case of a new
username the record is accepted and the user is asked to input his remaining details.
private void jtfClearActionPerformed(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_jtfClearActionPerformed
//to clear the login & password field
jtfUsername.setText("");
jpfPassword.setText("");
}//GEN-LAST:event_jtfClearActionPerformed
private void jbtRegisterActionPerformed(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_jbtRegisterActionPerformed
String username = jtfUsername.getText();
String password = jpfPassword.getText();
if (Validation.validateUsername(jtfUsername) == 0) {
try {
//check if the username exists in db
if (ClientMain.c.isUsernameExist(username) == 0) {
JOptionPane.showMessageDialog(null, "Please register
with another username", "Username Occupied", JOptionPane.WARNING_MESSAGE);
jtfUsername.requestFocus();
//if the username not exists in db, proceed
} else {
//make sure password is entered
if (Validation.validatePassword(jpfPassword) == 0) {
//username not exists in db, allow registration
int register = JOptionPane.showConfirmDialog(null,
"Register this user?", "Register", JOptionPane.YES_NO_CANCEL_OPTION);
if (register == 0) {
ClientMain.user.setUsername(username);
ClientMain.user.setPassword(password);
LoginRegistrationFunctions.registerUser(ClientMain.user);
//dipose LOGIN frame, show MENU frame
this.dispose();
//show main menu
MenuUI frame = new MenuUI();
frame.setTitle("Menu");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1040, 740);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
MenuUI.JTabPane.setSelectedComponent(MenuUI.jpUser);
JOptionPane.showMessageDialog(null, "Welcome.
Please update your personal information", "Welcome New User",
JOptionPane.INFORMATION_MESSAGE);
UserPanel.jtfName.requestFocus(); }} }
} catch (Exception e) {
System.out.println(e);
}}}

SHAMNEEZ MOHAMUDBUCUS TP022221

15

Distributed Computer Systems


3.1.4.2

2013

QUESTION 2

After the user has registered to the online food delivery system, the user should be
allowed to log in with username and password he/she registered earlier. (See Test# T4-T6)
ANSWER:
If an existing user logs in, the following code is executed to allow the user to log into
the system and an error message is displayed if the username or password is incorrect.
File Handling for User Login (LoginRegistrationFunctions.java)
When the user logs into the system, the login() method is called in order to retrieve
the users details from the User.txt file.
//login
public static int login(String username, String password) {
int login = 1;
String path = System.getProperty("user.dir") + "/src/Database
Files/User.txt";
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line and when username is not found
while ((strLine = br.readLine()) != null && login == 1) {
//read line and seperate string with delimiter semicolon
String[] data = strLine.split(";");
String fileUsername = data[0];
String filePassword = data[1];
String fileName = data[2];
String fileIC = data[3];
String filePhoneNo = data[4];
String fileAddress = data[5];
String fileEmail = data[6];
//if username found in file
if (fileUsername.equals(username)) {
if (filePassword.equals(password)) {
login = 0;
}}}
in.close();//Close the input stream
} catch (Exception e) {
System.out.println("Login Exception: " + e);}
return login;}

SHAMNEEZ MOHAMUDBUCUS TP022221

16

Distributed Computer Systems

2013

Validations for Username and Password Textboxes (Validation.java)


The validateUsername() and validatePassword() methods are used to validate the text
fields in order to check for empty username and password.
//to check if user enters empty username
public static int validateUsername(JTextField jtf) {
if (jtf.getText().equals("")) {
JOptionPane.showMessageDialog(null, "Please enter username.",
"Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
return 1;
} else {
return 0; }}
//to check if user enters empty password
public static int validatePassword(JPasswordField jpf) {
if (jpf.getText().equals("")) {
JOptionPane.showMessageDialog(null, "Please enter password.",
"Warning", JOptionPane.WARNING_MESSAGE);
jpf.requestFocus();
return 1;
} else {
return 0;
}}

Implementation For Login Button (LoginUI.java)


The Login button code allows the system to check the username and password for
existence in the User.txt file for existence. If the username and password matches one record
in the User.txt file, the values username and password are passed to the server class, User to
allow the user to use the sytem and perform different transactions.
private void jtfLoginActionPerformed(java.awt.event.ActionEvent evt) {
if (Validation.validateUsername(jtfUsername) == 1 ||
Validation.validatePassword(jpfPassword) == 1) {
} else {
try {
if (ClientMain.c.login(jtfUsername.getText().toLowerCase(),
jpfPassword.getText())== 0) {
JOptionPane.showMessageDialog(null, "Welcome, " + jtfUsername.getText());
ClientMain.user.setUsername(jtfUsername.getText());
ClientMain.user.setPassword(jpfPassword.getText());
//dipose LOGIN frame, show MENU frame
this.dispose();
MenuUI frame = new MenuUI();
frame.setTitle("Menu");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1040, 750);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}else{
JOptionPane.showMessageDialog(null, "Invalid
Username/Password. Please try again.", "Warning",
JOptionPane.WARNING_MESSAGE);}
} catch (Exception e) {System.out.println("c object login Exception");}}}
SHAMNEEZ MOHAMUDBUCUS TP022221

17

Distributed Computer Systems


3.1.4.3

2013

QUESTION 3

When log in, the user should be able deposit money (add money to his/her account),
and the online food delivery system should update the cash balance of the user. At any point
of time, the user should also be able to inquire current balance of his/her account from online
food delivery system. (See Test# T14-T19)
ANSWER:
When a user logs in and wish to deposit any amount of money into his account or
checks his balance, he can go to his wallet and deposit money via a credit card number and its
CVV2 code. The credit card number should exist in the Card.txt File in order to be valid.
Moreover, the refresh Balance Textbox displays the balance remaining for the user. The
following code allows the customer to do the transactions.
File Handling for Getting Balance (Functions.java)
The getBalance() method is used in order to obtain the current amount of money the
user has in his account. To do so, the Balance.txt file is read and the balance is value is
returned.
//get balance
public static String getBalance(String username) {
String balance = "";
int found = 1;
String path = System.getProperty("user.dir") + "/src/Database
Files/Balance.txt";
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new
InputStreamReader(in));
String strLine;
//Read File Line By Line and when username is not found
while ((strLine = br.readLine()) != null && found == 1) {
//read line and seperate string with delimiter semicolon
String[] data = strLine.split(";");
String fileUsername = data[0];
//if username found in file
if (fileUsername.equals(username)) {
balance = data[1]; } }
//Close the input stream
in.close();
} catch (Exception e) {
System.out.println("getBalance Exception: " + e); }
return balance;
}
SHAMNEEZ MOHAMUDBUCUS TP022221

18

Distributed Computer Systems

2013

Implementing Refresh Button for Balance (TransactionPanel.java)


The refresh button is used to call the getBalance() method in order to display the latest
value of users balance.
private void jbtRefreshActionPerformed(java.awt.event.ActionEvent evt) {
//get balance of user
try {
jtfBalance.setText(ClientMain.c.getBalance(ClientMain.user.getUsername()));
} catch (Exception e) {
System.out.println("Get user balance exception"); }}

Calculating New Balance and Updating Balance.txt (TransactionFunctions.java)


When the user makes a deposit, the balance needs to be updated in the file which is
done by the calculateBalance() method.
//calculate balance
public static String calculateBalance(String balance, String amount) {
DecimalFormat decim = new DecimalFormat("0.00"); //set 2 decimal places
Double b = Double.parseDouble(balance);
Double a = Double.parseDouble(amount);
//calculate balance
b = b + a;
//convert the figure back to string
balance = Double.toString(b);
balance = decim.format(b);
return balance;
}
//update balance
public static void updateBalance(String amount, String username) {
try {
String path = System.getProperty("user.dir") + "/src/Database
Files/Balance.txt";
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new
InputStreamReader(in));
String strLine;
StringBuilder fileContent = new StringBuilder();
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
String user[] = strLine.split(";");
if (user.length > 0) {
if (user[0].equals(username)) {
user[1] = amount;
String newLine = user[0] + ";" + user[1] + ";";
fileContent.append(newLine);
fileContent.append("\r\n");
} else {
// update content as it is

SHAMNEEZ MOHAMUDBUCUS TP022221

19

Distributed Computer Systems

2013

fileContent.append(strLine);
fileContent.append("\r\n");
} }}
// Now fileContent will have updated content, which you can
override into file
String path2 = System.getProperty("user.dir") + "/src/Database
Files/Balance.txt";
FileWriter fstreamWrite = new FileWriter(path2);
BufferedWriter out = new BufferedWriter(fstreamWrite);
out.write(fileContent.toString());
out.close();
//Close the input stream
in.close();
} catch (Exception e) {//Catch exception if any
System.err.println("Update Balance Exception: " +
e.getMessage()); }
}

File Handling for Credit Card Number and CVV2 Code (TransactionFunctions.java)
The method deposit() is used to call the method calculateBalance() to update the
Balance.txt file if and only if the checkCard() return true. The checkCard() method is used to
check for existence of credit card number and CVV2 code in the Card.txt file.
public static int deposit(String username, String cardNo, String cvv2,
String balance, String amount) {
//indicates whether deposit is successful
//1=unsuccessful; 0=successful
int success = 1;
String latestBalance = "";
//check if the credit card is exists
success = checkCard(cardNo, cvv2);
//if card exists, proceed deposit function
if (success == 0) {
//calculate balance after deposit
latestBalance = calculateBalance(balance, amount);
//update latest balance
updateBalance(latestBalance, username);
}
return success;
}
//check credit card function
public static int checkCard(String cardNo, String cvv2) {
//1=card not exists; 0=card exists
int exist = 1;
String path = System.getProperty("user.dir") + "/src/Database
Files/Card.txt";
try {// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line and when username is not found
while ((strLine = br.readLine()) != null && exist == 1) {
//read line and seperate string with delimiter semicolon
String[] data = strLine.split(";");
String fileCardNo = data[0];
String fileCVV2 = data[1];
//if username found in file
SHAMNEEZ MOHAMUDBUCUS TP022221

20

Distributed Computer Systems

2013

if (cardNo.equals(fileCardNo)) {
if (fileCVV2.equals(cvv2)) {
exist = 0;
} } }
//Close the input stream
in.close();
} catch (Exception e) {
System.out.println("checkCard Exception: " + e); }
return exist; }

Validating Amount (Validation.java)


In order to validate the amount to be deposit to the users account, the
validateAmount() method.
//validate amount to deposite, withdraw, transfer
public static int validateAmount(JTextField jtf) {
//1=false; 0=true
int valid = 1;
if (jtf.getText().equals("")) {
JOptionPane.showMessageDialog(null, "Please enter an amount to
be deposited", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
} else {
try {
double amt = Double.parseDouble(jtf.getText());
if (jtf.getText().matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+"))
{
valid = 0;
} else {
JOptionPane.showMessageDialog(null, "Please enter
integer only for amount", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Please enter integer
only for amount", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
}
}
return valid;
}

Validating Credit Card Length (Validation.java)


The validateCardNo() is used to validate entry for credit card as the length of the
credit card number need to be between 12 and 19 and the input needs to be a number.
//validate card number length
public static int validateCardNo(JTextField jtf) {
//0 = true; 1 = false
int valid = 1;
if (jtf.getText().equals("")) {

SHAMNEEZ MOHAMUDBUCUS TP022221

21

Distributed Computer Systems

2013

JOptionPane.showMessageDialog(null, "Please your credit card


number", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
} else {
try {
double amt = Double.parseDouble(jtf.getText());
//check if non-digit is entered
if (jtf.getText().matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+"))
{
//check if the number entered has length 12-19
if (jtf.getText().length() >= 12 ||
jtf.getText().length() <= 19) {
valid = 0;
} else {
JOptionPane.showMessageDialog(null, "Your credit
card number should be in 12 to 19 digits", "Warning",
JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
}
} else {
JOptionPane.showMessageDialog(null, "Please enter
integer only", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Please enter integer
only", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
} }
return valid;
}

Validating CVV2 Code (Validation.java)


The validateCVV2() is used to validate entry for CVV2 as the length of the number
need to be 3 and the input needs to be a number.
//validate cvv2
public static int validateCVV2(JTextField jtf) {
//0 = true; 1 = false
int valid = 1;
if (jtf.getText().equals("")) {
JOptionPane.showMessageDialog(null, "Please enter CVV2, the 3
security digits on the back of your credit card", "Warning",
JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
} else {
try {
double num = Double.parseDouble(jtf.getText());
//check if non-digit is entered
if (jtf.getText().matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+"))
{
//check if the number entered has length 3
if (jtf.getText().length() == 3) {
valid = 0;
} else {
JOptionPane.showMessageDialog(null, "CVV2 number
should be in 3 digits", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
}
} else {
SHAMNEEZ MOHAMUDBUCUS TP022221

22

Distributed Computer Systems

2013

JOptionPane.showMessageDialog(null, "Please enter


integer only", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus(); }
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Please enter integer
only", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
}
}
}

return valid;

Implementing Deposit Button (TransactionPanel.java)


When the deposit button is clicked, the methods validateCardNo(), validateCVV2()
and validateAmount() to allow the user to deposit money in his account.
private void jbtProceedActionPerformed(java.awt.event.ActionEvent evt) {
String msg = "";
String balance = jtfBalance.getText();
DecimalFormat decim = new DecimalFormat("0.00");
String amount = "";
String cardNo = "";
String cvv2 = "";
//if user enters valid credit card number
if (Validation.validateCardNo(jtfCardNo) == 0) {
//if user enters valid cvv2 number
if (Validation.validateCVV2(jtfCVV2) == 0) {
cardNo = jtfCardNo.getText();
//if user enters valid amount
if (Validation.validateAmount(jtfAmount) == 0) {
cvv2 = jtfCVV2.getText();
amount = decim.format(Double.parseDouble(jtfAmount.getText()));
msg = "Are you sure to deposit this amount: ";
//prompt user whether to proceed deposit or not
int de = JOptionPane.showConfirmDialog(null, msg + amount + "?",
"Deposit", JOptionPane.YES_NO_CANCEL_OPTION);
if (de == 0) {
try {
//perform deposit
int success = ClientMain.c.deposit(ClientMain.user.getUsername(),
cardNo, cvv2, balance, amount);
//if deposit successful
if (success == 0) {
//Empty fields
jtfAmount.setText("");
jtfCardNo.setText("");
jtfCVV2.setText("");
//get balance of user
jtfBalance.setText(ClientMain.c.getBalance(ClientMain.user.getUsername()));
JOptionPane.showMessageDialog(null, "Deposit successful");
} else {
JOptionPane.showMessageDialog(null, "Deposit failed.
Please check if your credit card information is entered correctly",
"Warning", JOptionPane.WARNING_MESSAGE);
}
} catch (RemoteException ex) {
SHAMNEEZ MOHAMUDBUCUS TP022221

23

Distributed Computer Systems

2013

System.out.println("Deposit exception"); }}}}}}

3.1.4.4
`

QUESTION 4

The user should be able to request a list of available food menu from the online food

delivery system. The system should return a list of available food menu to the user. (See
Section 3.2 for Screens)
ANSWER:
A food Menu is available in the application that allows the user to choose the food he
needs and purchases it. The code below displays the list of food for the user.
File Handling for Getting Food List and Food Code (Functions.java)
//get food info into list
public static ArrayList getFoodList() {
ArrayList foodListArr = new ArrayList();
String path=System.getProperty("user.dir")+"/src/Database Files/Food.txt";
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new
InputStreamReader(in));
String strLine;
//Read File Line By Line and when username is not found
while ((strLine = br.readLine()) != null) {
//read line and seperate string with delimiter semicolon
String[] data = strLine.split(";");
foodListArr.add(data[0]); //foodNo
foodListArr.add(data[1]); //foodTitle
foodListArr.add(data[2]); //foodPrice
foodListArr.add(data[3]); //foodDes}
//Close the input stream
in.close();
} catch (Exception e) {
System.err.println("File Error: " + e);
}
return foodListArr;}
//get food code into jcmb
public static ArrayList setFoodNoJcmb() {
ArrayList foodNoArr = new ArrayList();
String path=System.getProperty("user.dir")+"/src/Database Files/Food.txt";
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
SHAMNEEZ MOHAMUDBUCUS TP022221

24

Distributed Computer Systems

2013

DataInputStream in = new DataInputStream(fstream);


BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line and when username is not found
while ((strLine = br.readLine()) != null) {
//read line and seperate string with delimiter semicolon
String[] data = strLine.split(";");
foodNoArr.add(data[0]); //foodNo

}
//Close the input stream
in.close();
} catch (Exception e) {
System.err.println("File Error: " + e);
}
return foodNoArr;

Displaying Food Image and List (FoodMenuFunctions.java)


public static void loadMenuFoodImage(JLabel jlblFoodImage, JComboBox jcmb)
{
//get food number into jcmb
try {
//clear food jcmb
jcmb.removeAllItems();
//get food number arraylist
ArrayList arrFoodNo = null;
arrFoodNo = ClientMain.c.setFoodNoJcmb();
//set food number into jcmb
for (int i = 0; i < arrFoodNo.size(); i++) {
jcmb.addItem(arrFoodNo.get(i));
}
FoodMenuPanel.jbtBuyFood.setEnabled(true);
} catch (Exception e) {
System.out.println("get Food Number exception");
}
//get food menu list into table
try {
//get food menu list arraylist
ArrayList arrFoodList = null;
arrFoodList = ClientMain.c.getFoodList();
//get dsn of food menu image
ImageIcon foodImage = new
ImageIcon(ImageIcon.class.getClass().getResource("/Food Images/" +
arrFoodList.get(1) + ".jpg"));
//set jtf & cover for the first item
jlblFoodImage.setIcon(foodImage);
FoodMenuPanel.jtfFoodName.setText(arrFoodList.get(2).toString());
FoodMenuPanel.jtfFoodPrice.setText(arrFoodList.get(3).toString());
FoodMenuPanel.jtfFoodQuantity.setText(arrFoodList.get(4).toString());
} catch (Exception e) {
//System.out.println("get Food Menu list exception");
}
}

SHAMNEEZ MOHAMUDBUCUS TP022221

25

Distributed Computer Systems

2013

Displaying Food Details on Interface (FoodMenuPanel.java)


public FoodMenuPanel() {
initComponents();
//load menu food image
FoodMenuFunctions.loadMenuFoodImage(jlblFoodImage, jcmbFoodNumber);}

3.1.4.5 QUESTION 5
Based on a list food menu given, the user should be able to purchase food by selecting
from the list above. Upon confirmation, the user cash balance from his/her account should be
deducted from the food price. It should not be possible to purchase the food if the cash is not
sufficient from the user account. If the server crashes during purchasing transaction, what
would happen? How would your RMI program handle this problem? (See Test# T7 T19)
ANSWER:
In order to understand question 5 and question 8, the RMI concept need to be
understood. In RMI the client has no function at all. Instead the client uses the services
provided by the server. The server maintains a list of services in the IRemote.java, which
stores all the functions that can be invoked by the client. The Obj.java is the middleman that
redirects the function name registered in IRemote.java to the actual location of the coding.
For example, in this particular application, getFoodList is a function registered in
IRemote.java. It sees the Obj.java for redirecting of the function. The actual location is
Functions.getFoodList().
The application allows the user to select food and the selected food with the quantity
is displayed in the Order List. When the user clicks on purchase, if the balance of his account
is greater than or equal to the purchasing amount the purchase is confirmed, else an error
message is displayed and the application allows the user to redirect to the deposit amount
section.
Based on the RMI technology, described above, in case the server crashes, the user
can still use the application to enter data but the purchase will not be complete as all the
functions are obtained from the server. Moreover an error message will be displayed and the
text files will not be updated. The following codes are for the IRemote.java, Obj.java and
purchase transactions.

SHAMNEEZ MOHAMUDBUCUS TP022221

26

Distributed Computer Systems

2013

IRemote.java
The server maintains a list of services in the IRemote.java, which stores all the
functions that can be invoked by the client.
package Server;
import
import
import
import

java.rmi.Remote;
java.rmi.RemoteException;
java.util.ArrayList;
javax.swing.JTable;

public interface IRemote extends Remote {


public int registerUser(User u) throws RemoteException;
public int isUsernameExist(String criteria) throws RemoteException;
public int login(String username, String password) throws
RemoteException;
public ArrayList getFoodList() throws RemoteException;
public ArrayList setFoodNoJcmb() throws RemoteException;
public String getTodayDate() throws RemoteException;
public String getCurrentTime() throws RemoteException;
public String getBalance(String username) throws RemoteException;
public void updateBalance(String amount, String username) throws
RemoteException;
public void purchaseOrder(String username, double foodPrice, ArrayList
arrOrder) throws RemoteException;
public ArrayList getUserDetails(String username) throws
RemoteException;
public void updatePersonalDetails(String username, String name, String
ic, String phone, String address, String email) throws RemoteException;
public int deposit(String username, String cardNo, String cvv2, String
balance, String amount) throws RemoteException;
public ArrayList checkVoucher(String VoucherNo) throws RemoteException;
public void voucherTransfer(String transferToUser, String voucherNo,
String voucherAmount) throws RemoteException;
public double calculateOrderTotal(ArrayList arr) throws
RemoteException;
}

SHAMNEEZ MOHAMUDBUCUS TP022221

27

Distributed Computer Systems

2013

Obj.java
public class Obj extends UnicastRemoteObject implements IRemote {
public Obj() throws RemoteException {
super();
}
//check if the username exists in DB
public int isUsernameExist(String criteria) {
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
isUsernameExist from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return LoginRegistrationFunctions.isUsernameExist(criteria);

//register the user


public int registerUser(User p) {
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
registerUser from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return LoginRegistrationFunctions.registerUser(p);
}
//login
public int login(String username, String password) {
try {
System.out.println(Functions.getCurrentTime() + ": Invoke login
from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return LoginRegistrationFunctions.login(username, password);
}
//get food info into list
public ArrayList getFoodList(){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
getFoodList from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return Functions.getFoodList();
}
//get food code into jcmb
public ArrayList setFoodNoJcmb(){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
getFoodNo into jcmb from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return Functions.setFoodNoJcmb();
}
//get today date
public String getTodayDate(){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
getTodayDate from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return Functions.getTodayDate();
}
SHAMNEEZ MOHAMUDBUCUS TP022221

28

Distributed Computer Systems

2013

//get current time


public String getCurrentTime(){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
getCurrentTime from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return Functions.getCurrentTime();
}
//calculate total price of food order
public double calculateOrderTotal(ArrayList arr){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
calculateOrderTotal from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return FoodMenuFunctions.calculateOrderTotal(arr);
}
//************************* transaction panel ************************
//check account balance
public String getBalance(String username){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
getBalance from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return Functions.getBalance(username);}
//update balance
public void updateBalance(String amount, String username){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
updateBalance from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
TransactionFunctions.updateBalance(amount, username);
}
//deposit
public int deposit(String username, String cardNo, String cvv2, String
balance, String amount){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
deposit from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return TransactionFunctions.deposit(username, cardNo, cvv2,
balance, amount);
}
//check voucher
public ArrayList checkVoucher(String voucherNo){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
updateBalance from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return TransactionFunctions.checkVoucher(voucherNo); }

SHAMNEEZ MOHAMUDBUCUS TP022221

29

Distributed Computer Systems

2013

//voucher transfer
public void voucherTransfer(String transferToUser, String voucherNo,
String voucherAmount){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
voucherTransfer from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
TransactionFunctions.voucherTransfer(transferToUser, voucherNo,
voucherAmount);
}
//*************************** food menu panel ************************
//place order
public void purchaseOrder(String username, double foodPrice, ArrayList
arrOrder){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
purchaseOrder from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
FoodMenuFunctions.purchaseOrder(username, foodPrice, arrOrder);
}
//********************************* user panel ************************
//check if the username exists in DB
public ArrayList getUserDetails(String username) {
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
getUserDetails from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
return UserPanelFunctions.getUserDetails(username);
}
//update personal details
public void updatePersonalDetails(String username, String name, String
ic, String phone, String address, String email){
try {
System.out.println(Functions.getCurrentTime() + ": Invoke
updatePersonalDetails from " + getClientHost());
} catch (ServerNotActiveException snae) {
snae.printStackTrace();
}
UserPanelFunctions.updatePersonalDetails(username, name, ic, phone,
address, email);
}}

SHAMNEEZ MOHAMUDBUCUS TP022221

30

Distributed Computer Systems

2013

File Handling for Purchase (Functions.java and FoodMenuFunctions.java)


//get today date From System
public static String getTodayDate() {
Calendar currentDate = Calendar.getInstance();
SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy");
String todayDate = f.format(currentDate.getTime());
return todayDate; }
//get current time From System
public static String getCurrentTime() {
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Calendar cal = Calendar.getInstance();
String currentTime = dateFormat.format(cal.getTime());
return currentTime; }
//get balance
//get food code into jcmb
public static String getBalance(String username) {
String balance = "";
int found = 1;
String path = System.getProperty("user.dir") + "/src/Database
Files/Balance.txt";
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line and when username is not found
while ((strLine = br.readLine()) != null && found == 1) {
//read line and seperate string with delimiter semicolon
String[] data = strLine.split(";");
String fileUsername = data[0];
//if username found in file
if (fileUsername.equals(username)) {
balance = data[1];
}
}
//Close the input stream
in.close();
} catch (Exception e) {
System.out.println("getBalance Exception: " + e);
}
return balance;
}
//generate new recordNo based on tablename
//recordNo format = 5 characters
public static String generateRecordNo(String tableName) {
String newRecordNo = "";
int number = 0;
String code = "";
String fileName = tableName + ".txt";
String path = System.getProperty("user.dir") + "/src/Database
Files/" + fileName;
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
SHAMNEEZ MOHAMUDBUCUS TP022221

31

Distributed Computer Systems

2013

DataInputStream in = new DataInputStream(fstream);


BufferedReader br = new BufferedReader(new
InputStreamReader(in));
String strLine;
//if database has existing record
if ((strLine = br.readLine()) != null) {
//get recordNo without the first code character. Example: R10001 -> 1001
//read line and seperate string with delimiter semicolon
String[] data = strLine.split(";");
int DBnumber = Integer.parseInt(data[0].substring(1));
code = data[0].substring(0, 1);
//get the largest record number
if (DBnumber > number) {
number = DBnumber;
}
//while there is record
while ((strLine = br.readLine()) != null) {
String[] data2 = strLine.split(";");
//get recordNo without the first code character. Example: R10001 -> 1001
DBnumber = Integer.parseInt(data2[0].substring(1));
if (DBnumber > number) {
number = DBnumber;}}
//if there is no record in the receipt table
} else {
newRecordNo = code + "1001";}
//get the last receiptNo in the record and +1 to gen new receiptNo
newRecordNo = code.concat(Integer.toString(number + 1));
//Close the input stream
in.close();
} catch (Exception e) {
System.err.println("generateRecordNo Exception: " + e);}
return newRecordNo;
}

//put record in table into arraylist


public static ArrayList putTableRecordsIntoArrayList(JTable table) {
ArrayList arr = new ArrayList();
try {
int row = table.getRowCount();
int column = table.getColumnCount();
//check every row in the table
for (int i = 0; i < row; i++) {
//check if table has record
if (table.getValueAt(i, 0) != null) {
//put every detail of the record into arraylist
for (int j = 0; j < column; j++) {
arr.add(table.getValueAt(i, j));
}
} else {
//to terminate the for loop
i = row; }}
} catch (Exception e) {
System.out.println("putTableRecordsIntoArrayList: " + e);
return arr;
}

SHAMNEEZ MOHAMUDBUCUS TP022221

32

Distributed Computer Systems

2013

//update food quantity of a certain food


public static void updateFoodQuantity(String foodNo, String
orderQuantity) {
try {
String path = System.getProperty("user.dir") + "/src/Database
Files/Food.txt";
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
StringBuilder fileContent = new StringBuilder();
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
String food[] = strLine.split(";");
String fileFoodNo = food[0];
String fileFoodName = food[1];
String fileFoodPrice = food[2];
String fileFoodQuantity = food[3];
if (food.length > 0) {
if (fileFoodNo.equals(foodNo)) {
//calculate new quantity
//quantity in store minus order quantity
int newQuantity =
Integer.parseInt(fileFoodQuantity) - Integer.parseInt(orderQuantity);
//new record
String newLine = fileFoodNo + ";" + fileFoodName +
";" + fileFoodPrice + ";" + newQuantity + ";";
fileContent.append(newLine);
fileContent.append("\r\n");
} else {
// update content as it is
fileContent.append(strLine);
fileContent.append("\r\n");} } }
//Now fileContent will have updated content , which can override into file
String path2 = System.getProperty("user.dir") + "/src/Database
Files/Food.txt";
FileWriter fstreamWrite = new FileWriter(path2);
BufferedWriter out = new BufferedWriter(fstreamWrite);
out.write(fileContent.toString());
out.close();
//Close the input stream
in.close();
} catch (Exception e) {//Catch exception if any
System.err.println("Update Food Quantity Exception: " +
e.getMessage()); }}
//update food quantity in store
public static void updateStoreFoodQuantity(ArrayList arrOrder) {
for (int i = 0; i < arrOrder.size(); i = i + 4) {
try { String foodNo = arrOrder.get(i).toString();
String orderQuantity = arrOrder.get(i + 3).toString();
//update each foodNo's quantity in store
updateFoodQuantity(foodNo, orderQuantity);
} catch (Exception e) {
System.out.println("updateStoreFoodQuantity: " + e);}}}
SHAMNEEZ MOHAMUDBUCUS TP022221

33

Distributed Computer Systems

2013

//get store quantity of food


public static int getFoodStoreQuantity(String foodNo) {
int fileQuantity = 0;
int found = 1;
String path = System.getProperty("user.dir") + "/src/Database
Files/Food.txt";
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line and when username is not found
while ((strLine = br.readLine()) != null && found == 1) {
//read line and seperate string with delimiter semicolon
String[] food = strLine.split(";");
String fileFoodNo = food[0];
//if foodNo found in file
if (fileFoodNo.equals(foodNo)) {
fileQuantity = Integer.parseInt(food[3]);
found = 0;}}
//Close the input stream
in.close();
} catch (Exception e) {
System.out.println("get FoodStore Quantity Exception: " + e);}
return fileQuantity; }

SHAMNEEZ MOHAMUDBUCUS TP022221

34

Distributed Computer Systems

2013

Performing Purchase and Generating Receipts (FoodMenuFunctions.java)


//purchase order function will do the below:
//1. generate receipt (extra, can be improved)
//2. update balance
//3. update food quantity in store
public static void purchaseOrder(String username, double foodPrice,
ArrayList arrOrder) {
//get balance n calculate balance
double balance =
Double.parseDouble(Functions.getBalance(username));
balance = balance - foodPrice;
String newRecordNo = Functions.generateRecordNo("Receipt");
String date = Functions.getTodayDate();
String time = Functions.getCurrentTime();
DecimalFormat decim = new DecimalFormat("0.00");
String price = decim.format(foodPrice);
String path = System.getProperty("user.dir") + "/src/Database
Files/Receipt.txt";
File file = new File(path);
String newReceiptRecord = newRecordNo + ";" + username + ";" +
price + ";" + date + ";" + time + ";";
try {
//if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile(); }
//true = append file; false = overwrite
BufferedWriter writer = new BufferedWriter(new FileWriter(path, true));
writer.write(newReceiptRecord);
writer.newLine();
writer.close();
} catch (Exception e) {
System.out.println("purchaseOrder Exception: " + e); }
//update balance after place order
TransactionFunctions.updateBalance(Double.toString(balance), username);
//update food quantity in store
updateStoreFoodQuantity(arrOrder);
}
//calculate total price of food order
public static double calculateOrderTotal(ArrayList arr) {
double total = 0;
//check each row of table for non-empty row
for (int i = 0; i < arr.size(); i = i + 4) {
double price = 0;
int quantity = 0;
price = Double.valueOf(arr.get(i + 2).toString());
quantity = Integer.parseInt(arr.get(i + 3).toString());
total = total + (price * quantity); }
return total;}

SHAMNEEZ MOHAMUDBUCUS TP022221

35

Distributed Computer Systems

2013

Put Food Items in Order Table (Functions.java)


//put record in table into arraylist
public static ArrayList putTableRecordsIntoArrayList(JTable table) {
ArrayList arr = new ArrayList();
try {
int row = table.getRowCount();
int column = table.getColumnCount();
//check every row in the table
for (int i = 0; i < row; i++) {
//check if table has record
if (table.getValueAt(i, 0) != null) {
//put every detail of the record into arraylist
for (int j = 0; j < column; j++) {
arr.add(table.getValueAt(i, j));
}
} else {
//to terminate the for loop
i = row; }
}
} catch (Exception e) {
System.out.println("putTableRecordsIntoArrayList: " + e);}
return arr; }

Setting Order Table (FoodMenuFunctions.java)


//set order table
public static void setOrderTable(JTable orderTable, ArrayList arrOrder){
Functions.clearTable(orderTable);
int j = 0;
for (int i = 0; j < arrOrder.size(); i++) {
orderTable.setValueAt(arrOrder.get(j), i, 0);
j++;
orderTable.setValueAt(arrOrder.get(j), i, 1);
j++;
orderTable.setValueAt(arrOrder.get(j), i, 2);
j++;
orderTable.setValueAt(arrOrder.get(j), i, 3);
j++; } }

Update Order Table with New Orders (FoodMenuFunctions.java)


//get details from table into array, to update the order table
public static void getTableOrderIntoArray(String foodNo, String
foodName, String foodPrice, JTable orderTable, ArrayList arrOrder) {
try {
//get value from order table
String tableFoodNo = "";
int tableOrderQuantity = 0;
//check each row of table for non-empty row
for (int i = 0; i < 25; i++) {
try {
//foodNo in table
tableFoodNo = orderTable.getValueAt(i, 0).toString();
//Order quantity of the particular food
tableOrderQuantity =
Integer.parseInt(orderTable.getValueAt(i, 3).toString());
} catch (Exception e) {
SHAMNEEZ MOHAMUDBUCUS TP022221

36

Distributed Computer Systems

2013

if (tableFoodNo.equals(foodNo)) {
tableOrderQuantity += 1;
}
//check if table has record
if (orderTable.getValueAt(i, 0) != null) {
arrOrder.add(orderTable.getValueAt(i, 0)); //foodNo
arrOrder.add(orderTable.getValueAt(i, 1)); //foodName
arrOrder.add(orderTable.getValueAt(i, 2)); //price
arrOrder.add(tableOrderQuantity); //quantity
} else {
if (tableFoodNo.equals(foodNo) == false) {
arrOrder.add(foodNo);
arrOrder.add(foodName);
arrOrder.add(foodPrice);
arrOrder.add(1);
}
//to terminate the for loop
i = 25; }}
//if the order table is empty, place the order at the first row
} catch (NullPointerException e) {
System.out.println("null pointer in table"); }}

Checking Customer Order Quantity against Food Quantity (FoodMenuFunctions.java)


//check customer order quantity against available food quantity in store
public static ArrayList orderVSquantity(String foodNo, int foodQuantity,
ArrayList arr) {
ArrayList arrNew = new ArrayList();
//check each row of table for non-empty row
for (int i = 0; i < arr.size(); i = i + 4) {
//get value from order retrived in order table
String tableFoodNo = arr.get(i).toString();
String tableFoodName = arr.get(i + 1).toString();
String tableFoodPrice = arr.get(i + 2).toString();
int tableFoodQuantity = Integer.parseInt(arr.get(i + 3).toString());
//check order of customer
if (foodNo.equals(tableFoodNo)) {
//order quantity vs food quantity from file
if (tableFoodQuantity > foodQuantity) {
String msg = "The selected food has insufficient quantity in store.";
//if food quantity = 0
if (foodQuantity == 0) {
msg = "The selected food is out of stock."; }
JOptionPane.showMessageDialog(null, msg, "Information",
JOptionPane.INFORMATION_MESSAGE);
tableFoodQuantity -= 1;
}}
//display purpose, not to display food order which store quantity = 0
if (tableFoodQuantity != 0) {
//to update new order array
arrNew.add(tableFoodNo);
arrNew.add(tableFoodName);
arrNew.add(tableFoodPrice);
arrNew.add(tableFoodQuantity);
} }
//update new order array;
return arrNew; }

SHAMNEEZ MOHAMUDBUCUS TP022221

37

Distributed Computer Systems

2013

Check Customer Order Quantity with Food Quantity (FoodMenuFunctions.java)


//check customer's orders against store food quantity
public static int checkOrder(JTable table) {
int valid = 0;
ArrayList arrOrder = Functions.putTableRecordsIntoArrayList(table);
for (int i = 0; i < (arrOrder.size() / 4) && valid == 0; i = i + 4) {
//get customer's order
String orderFoodNo = arrOrder.get(i).toString();
int orderFoodQuantity = Integer.parseInt(arrOrder.get(i + 3).toString());
int storeQuantity = getFoodStoreQuantity(orderFoodNo);
//check customer order agaisnt available quantity in store
if (storeQuantity < orderFoodQuantity) {
valid = 1;
//show message to indicate customer
String msg = orderFoodNo + " has insufficient stock.\n" +
"Store Quantity: " + storeQuantity + "\n" + "Order Quantity: " +
orderFoodQuantity;
JOptionPane.showMessageDialog(null, msg, "Information",
JOptionPane.INFORMATION_MESSAGE); }}
return valid;}

Implementing Discard Button (FoodMenuPanel.java)


private void jbtDiscardActionPerformed(java.awt.event.ActionEvent evt) {
if (jtfTotalPurchase.getText().equals("")) {
JOptionPane.showMessageDialog(null, "Order List is empty.",
"Information", JOptionPane.INFORMATION_MESSAGE);
} else {
//clear orderTable
int dis = JOptionPane.showConfirmDialog(null, "Are you sure you
want to discard the order?", "Discard Order",
JOptionPane.YES_NO_CANCEL_OPTION);
if (dis == 0) {
Functions.clearTable(orderTable);
jtfTotalPurchase.setText("");}}

SHAMNEEZ MOHAMUDBUCUS TP022221

38

Distributed Computer Systems

2013

Implementing Order Button (FoodMenuPanel.java)


private void jbtPlaceOrderActionPerformed(java.awt.event.ActionEvent evt) {
//place selected food into the order table
String foodNo = jcmbFoodNumber.getSelectedItem().toString();
String foodName = jtfFoodName.getText();
String foodPrice = jtfFoodPrice.getText();
int foodQuantity = Integer.parseInt(jtfFoodQuantity.getText());
ArrayList arrOrder = new ArrayList();
//get details in table into array to be updated
FoodMenuFunctions.getTableOrderIntoArray(foodNo, foodName,
foodPrice, orderTable, arrOrder);
//validate order quantity against quantity in store (from file)
//this is to make sure the system getting the real time quantity
arrOrder = FoodMenuFunctions.orderVSquantity(foodNo, foodQuantity,
arrOrder);
//set orderTable
FoodMenuFunctions.setOrderTable(orderTable, arrOrder);
//get total price for order
try {
double total = ClientMain.c.calculateOrderTotal(arrOrder);
//format the double value with 2 decimal places
DecimalFormat df = new DecimalFormat("###,##0.00");
jtfTotalPurchase.setText(String.valueOf(df.format(total)));
} catch (Exception e) {
System.out.println("Get Order Total Exception: " + e);}}

SHAMNEEZ MOHAMUDBUCUS TP022221

39

Distributed Computer Systems

2013

Implementing Confirm Button (FoodMenuPanel.java)


private void jbtBuyFoodActionPerformed(java.awt.event.ActionEvent evt) {
if (jtfTotalPurchase.getText().equals("") ||
jtfTotalPurchase.getText().equals("0.00")) {
JOptionPane.showMessageDialog(null, "Order List is empty.
Please place your order", "Warning", JOptionPane.WARNING_MESSAGE);
} else {
double foodPrice =
Double.parseDouble(jtfTotalPurchase.getText());
double balance = 0;
double lack = 0;
//get user's balance
try { balance =
Double.parseDouble(ClientMain.c.getBalance(ClientMain.user.getUsername()));
} catch (Exception e) {
System.out.println("get balance exception");}
//check if user has insufficient balance to buy food
if (foodPrice > balance) {
lack = foodPrice - balance;
int de = JOptionPane.showConfirmDialog(null, "Your balance:
RM" + balance + ", lack of RM" + lack + " to make the purchase.\nDeposite
money into account?", "Insufficient balance",
JOptionPane.YES_NO_CANCEL_OPTION);
if (de == 0) {
//deposite balance panel
MenuUI.JTabPane.setSelectedIndex(2);
TransactionPanel.jtfAmount.setText(Double.toString(lack));}
} else if (foodPrice != 0) {
//prompt user to confirm to place order
int buy = JOptionPane.showConfirmDialog(null, "Are you sure
you want to make the purchase?", "Confirm Purchase",
JOptionPane.YES_NO_CANCEL_OPTION);
if (buy == 0) {
//check customer's orders against store quantity
int proceed = FoodMenuFunctions.checkOrder(orderTable);
//if customer's order has stock in store
if (proceed == 0) {
try {
ArrayList arrOrder = Functions.putTableRecordsIntoArrayList(orderTable);
//purchase order
ClientMain.c.purchaseOrder(ClientMain.user.getUsername(), foodPrice,
arrOrder);
JOptionPane.showMessageDialog(null, "Done", "Information",
JOptionPane.INFORMATION_MESSAGE);
//after purchase, clear order table list
Functions.clearTable(orderTable);
jtfTotalPurchase.setText("");
try {
//update balance field
TransactionPanel.jbtRefresh.doClick();
} catch (Exception e) {}
//update menu food quantity
jcmbFoodNumber.removeAllItems();
FoodMenuFunctions.loadMenuFoodImage(jlblFoodImage, jcmbFoodNumber);
} catch (Exception ex) {
System.out.println("place order exception: " + ex); }
} else {
//reload menu food menu
FoodMenuFunctions.loadMenuFoodImage(jlblFoodImage, jcmbFoodNumber);}}}}}
SHAMNEEZ MOHAMUDBUCUS TP022221

40

Distributed Computer Systems


3.1.4.6

2013

QUESTION 6

Finally, given two users in the system e.g., usernames A and B, User A should be able
to transfer cash voucher from his/her account to other user's B account. (See Test# T19 T24)
ANSWER:
The transfer of vouchers from a users account to another users account has been
implemented through a voucher system whereby the voucher code will be verified in
Voucher.txt and an error message is displayed if the voucher doesnt exist or the voucher is
expired. After a valid voucher is transferred the voucher is deleted from the Voucher.txt file.
File Handling for Voucher.txt (TransactionFunctions.java)
//check voucher
public static ArrayList checkVoucher(String voucherNo) {
ArrayList arr = new ArrayList();
String path = System.getProperty("user.dir") + "/src/Database
Files/Voucher.txt";
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new
InputStreamReader(in));
String strLine;
//Read File Line By Line and when username is not found
while ((strLine = br.readLine()) != null) {
//read line and seperate string with delimiter semicolon
String[] data = strLine.split(";");
String fileVoucherNo = data[0];
String fileAmount = data[1];
String fileExpiryDate = data[2];
if (voucherNo.equals(fileVoucherNo)) {
arr.add(fileAmount);
arr.add(fileExpiryDate);}}
//Close the input stream
in.close();
} catch (Exception e) {
System.out.println("check Voucher Exception: " + e);}
return arr;}
//check voucher expiry date against today date
public static int checkVoucherDate(String date) {
//1=expired; 0=not expired
int ex = 0;
//voucher expiry year, month, day
int vDay = Integer.parseInt(date.substring(0, 2));
int vMonth = Integer.parseInt(date.substring(3, 5));
int vYear = Integer.parseInt(date.substring(6));
//today date
String todayDate = Functions.getTodayDate();
int tDay = Integer.parseInt(todayDate.substring(0, 2));
SHAMNEEZ MOHAMUDBUCUS TP022221

41

Distributed Computer Systems

2013

int tMonth = Integer.parseInt(todayDate.substring(3, 5));


int tYear = Integer.parseInt(todayDate.substring(6));
//check if voucher is expired
//check year
if (vYear < tYear) {
ex = 1;
} else {
if (vYear == tYear) {
//check month
if (vMonth < tMonth) {
ex = 1;
} else if (vMonth == tMonth) {
//check day
if (vDay < tDay) {
ex = 1;}}}}
//display msg if voucher is expired
if (ex == 1) {
JOptionPane.showMessageDialog(null, "Transaction failed. Your
voucher is expired.", "Warning", JOptionPane.WARNING_MESSAGE);}
return ex;
}
//voucher transfer
//1. update balance of user who receives the voucher
//2. delete voucher record
public static void voucherTransfer(String transferToUser, String
voucherNo, String voucherAmount) {
System.out.println(transferToUser);
System.out.println(voucherNo);
System.out.println(voucherAmount);
//get receiver's balance
String receiverBalance = Functions.getBalance(transferToUser);
String newBalance;
DecimalFormat decim = new DecimalFormat("0.00"); // set 2 decimal places
Double b = Double.parseDouble(receiverBalance);
Double a = Double.parseDouble(voucherAmount);
//calculate balance
b = b + a;
//convert the figure back to string
newBalance = Double.toString(b);
newBalance = decim.format(b);
//update receiver's balance
updateBalance(newBalance, transferToUser);
//delete Voucher record
deleteVoucher(voucherNo);
//display successful transfer msg
JOptionPane.showMessageDialog(null, "Voucher Transfer successful.",
"Information", JOptionPane.INFORMATION_MESSAGE);}
//delete voucher record
public static void deleteVoucher(String voucherNo) {
try {
String path = System.getProperty("user.dir") + "/src/Database
Files/Voucher.txt";
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
SHAMNEEZ MOHAMUDBUCUS TP022221

42

Distributed Computer Systems

2013

String strLine;
StringBuilder fileContent = new StringBuilder();
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
String user[] = strLine.split(";");
String fileVoucherNo = user[0];
if (user.length > 0) {
if (fileVoucherNo.equals(voucherNo)) {
System.out.println("Delete " + user[0]);
} else {
// update content as it is
fileContent.append(strLine);
fileContent.append("\r\n");}}}
// Now fileContent will have updated content , which has override into file
String path2 = System.getProperty("user.dir") + "/src/Database
Files/Voucher.txt";
FileWriter fstreamWrite = new FileWriter(path2);
BufferedWriter out = new BufferedWriter(fstreamWrite);
System.out.println("sss: \n" + fileContent.toString());
out.write(fileContent.toString());
out.close();
//Close the input stream
in.close();
} catch (Exception e) {//Catch exception if any
System.err.println("Error: " + e.getMessage());}}

Validating Voucher Code (Validation.java)


//to validate voucher number
public static int validateVoucherNo(JTextField jtf) {
if (jtf.getText().equals("")) {
JOptionPane.showMessageDialog(null, "Please enter voucher
number.", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
return 1;
} else if (jtf.getText().length() != 16) {
JOptionPane.showMessageDialog(null, "A vouncher number should
be in 16 characters.", "Warning", JOptionPane.WARNING_MESSAGE);
jtf.requestFocus();
return 1;
} else {
return 0;
}
}

SHAMNEEZ MOHAMUDBUCUS TP022221

43

Distributed Computer Systems

2013

Implementing Check Voucher Button (TransactionPanel.java)


private void jbtCheckActionPerformed(java.awt.event.ActionEvent evt) {
//validate user entered voucher number
if (Validation.validateVoucherNo(jtfVoucherNo) == 0) {
//check if entered voucher number exists in the database
try {
ArrayList arr = new ArrayList();
arr = ClientMain.c.checkVoucher(jtfVoucherNo.getText());
//display voucher info
jtfVoucherAmount.setText(arr.get(0).toString());
jtfExpiryDate.setText(arr.get(1).toString());
jtfTransferTo.setEnabled(true);
jtfTransferTo.requestFocus();
jpVoucher.setVisible(true);
jbtDiscard.setVisible(true);
jbtCheck.setEnabled(false);
jbtConfirm.setEnabled(true);
jtfVoucherNo.setEnabled(false);
} catch (Exception e) {
System.out.println("Check Voucher Exception");}}}

Implementing Confirm Voucher Button (TransactionPanel.java)


private void jbtConfirmActionPerformed(java.awt.event.ActionEvent evt) {
//validate voucher expiry date
if (TransactionFunctions.checkVoucherDate(jtfExpiryDate.getText()) == 0) {
//validate user entered username
if (Validation.validateUsername(jtfTransferTo) == 0) {
//check if the entered username is exists
if (LoginRegistrationFunctions.isUsernameExist(jtfTransferTo.getText())==
0) {
//prompt user to confirm
int sure = JOptionPane.showConfirmDialog(null, "Are you sure to proceed
the voucher transfer?", "Voucher Transfer",
JOptionPane.YES_NO_CANCEL_OPTION);
if (sure == 0) {
//perform voucher tranfer
try {
ClientMain.c.voucherTransfer(jtfTransferTo.getText().toLowerCase(),
jtfVoucherNo.getText(), jtfVoucherAmount.getText());
//set components
jtfTransferTo.setText("");
jtfTransferTo.setEnabled(false);
jpVoucher.setVisible(false);
jtfVoucherNo.setText("");
jtfVoucherNo.setEnabled(true);
jbtConfirm.setEnabled(false);
jbtCheck.setEnabled(true);
jbtRefresh.doClick();
} catch (Exception e) {
System.out.println("Voucher Transfer: " + e);}}
} else {
JOptionPane.showMessageDialog(null, "Username entered
is not exists. Please try again", "Warning", JOptionPane.WARNING_MESSAGE);
jtfTransferTo.requestFocus();}}}}

SHAMNEEZ MOHAMUDBUCUS TP022221

44

Distributed Computer Systems


3.1.4.7

2013

QUESTION 7

Implement secure communication between session with the user and the food online
system (i) when user purchases food and (ii) when the user performs cash transfer (Hint: use
either SSL, SSH or any other security protocols for security needs). (See Test # T1)
ANSWER:
Required validations have been used in the applications to validate the values entered
in the system. However, SSL (Secure Socket Layer) has been used in order to provide
security over networks when purchasing food, depositing money and transferring vouchers as
it involves sensitive data.
Secure Sockets Layer (SSL), now known as Transport Layer Security (TLS) is a
cryptographic protocol providing provides security for communications over networks such
as the Internet. It encrypts the segments of network connections at the Transport Layer endto-end. (Sanjaal, 2013)
Implementing SSL for Receiving Cash (Server.java)
public static byte[] ReceiveCash(String fileName, int index){
try {
File file = new File(fileName);
byte buffer[] = new byte[(int)file.length()];
BufferedInputStream input = new
BufferedInputStream(new FileInputStream(file));
input.read(buffer, 0, buffer.length);
input.close();
return(buffer);
} catch(Exception e){
e.printStackTrace();
return(null);}}

Implementing SSL for Sending Cash (Server.java)


public static void SendCash(byte[] filedata, String fileName, int index) {
try {
fileName = uploadingFolder + fileName;
new File(new File(fileName).getParent()).mkdirs();
File file = new File(fileName);
BufferedOutputStream output = new
BufferedOutputStream(new FileOutputStream(file));
output.write(filedata, 0, filedata.length);
output.flush();
output.close();
} catch (Exception e) {
e.getStackTrace();}}

SHAMNEEZ MOHAMUDBUCUS TP022221

45

Distributed Computer Systems

2013

Implementing Server for SSL (ServerImpl.java)


public class ServerImpl extends UnicastRemoteObject {
public ServerImpl () throws RemoteException {}
public ServerImpl (
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf) throws RemoteException {
super(0, csf, ssf);
}
public byte[] ReceiveFile(String cashAmount, int index) {
return Server.ReceiveCash(cashAmount, index);
}

public void SendFile(String cashAmount, int index) {


Server.SendCash(cashAmount, index);
}

3.1.4.8

QUESTION 8

What happen if multiple users use the online food system at the same time? What
if/she purchases the same food item from the online system at the same time? What issues
you might face? How can we resolve the issues? Implement your program to resolve the
potential issues. Indicate exactly in the report of the code segment that you have written to
resolve the issues and please provide detailed explanations. (See Test# T25)
ANSWER:
Using RMI technology, one of the advantages the developer gains is to allow multiple
users to access the system. All services invoked by clients are treated as independent and it
does not affect the other clients. However, the quantity of food in the system is updated on
the spot as soon as an order is made, therefore any customer, who first purchases the last set
of a particular food item, while the remaining clients who order at the same time cannot book
the same food item.
In the application, in order to allow the quantity of food items to be up to date the
Update Food Quantity Class, given on the following pages, updates the quantity immediately
after the order is made so as to allow clients to have the most updated value of quantity.
However in order to protect integrity of the different client threads, the following
Concurrency class may be adapted.

SHAMNEEZ MOHAMUDBUCUS TP022221

46

Distributed Computer Systems

SHAMNEEZ MOHAMUDBUCUS TP022221

2013

47

Distributed Computer Systems

2013

File Handling for Updating Quantity (FoodMenuFunctions.java)


//update food quantity of a certain food
public static void updateFoodQuantity(String foodNo, String
orderQuantity) {
try {
String path = System.getProperty("user.dir") + "/src/Database
Files/Food.txt";
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
StringBuilder fileContent = new StringBuilder();
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
String food[] = strLine.split(";");
String fileFoodNo = food[0];
String fileFoodName = food[1];
String fileFoodPrice = food[2];
String fileFoodQuantity = food[3];
if (food.length > 0) {
if (fileFoodNo.equals(foodNo)) {
//calculate new quantity
//quantity in store minus order quantity
int newQuantity =
Integer.parseInt(fileFoodQuantity) - Integer.parseInt(orderQuantity);
//new record
String newLine = fileFoodNo + ";" + fileFoodName +
";" + fileFoodPrice + ";" + newQuantity + ";";
fileContent.append(newLine);
fileContent.append("\r\n");
} else {
// update content as it is
fileContent.append(strLine);
fileContent.append("\r\n");} } }
//Now fileContent will have updated content , which can override into file
String path2 = System.getProperty("user.dir") + "/src/Database
Files/Food.txt";
FileWriter fstreamWrite = new FileWriter(path2);
BufferedWriter out = new BufferedWriter(fstreamWrite);
out.write(fileContent.toString());
out.close();
//Close the input stream
in.close();
} catch (Exception e) {//Catch exception if any
System.err.println("Update Food Quantity Exception: " +
e.getMessage()); }}

SHAMNEEZ MOHAMUDBUCUS TP022221

48

Distributed Computer Systems

2013

Update Quantity Function (FoodMenuFunctions.java)


//update food quantity in store
public static void updateStoreFoodQuantity(ArrayList arrOrder) {
for (int i = 0; i < arrOrder.size(); i = i + 4) {
try { String foodNo = arrOrder.get(i).toString();
String orderQuantity = arrOrder.get(i + 3).toString();
//update each foodNo's quantity in store
updateFoodQuantity(foodNo, orderQuantity);
} catch (Exception e) {
System.out.println("updateStoreFoodQuantity: " + e);}}}

SHAMNEEZ MOHAMUDBUCUS TP022221

49

Distributed Computer Systems


3.1.5

2013

Additional Components Encryption of User Details

In order to protect confidentiality of user details, encryption and decryption methods


have been used in the application. The implementation for encryption and decryption are as
follows.
Encryption Code (SecurityFunctions.java)
public static String encrypt(String Data) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}

Decryption Code (SecurityFuctions.java)


public static String decrypt(String encryptedData) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new
BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}

Algorithm for Encryption (SecurityFunctions.java)


The algorithm used is from the crypto package in the java libraries. It is implemented
as follows.
private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGO);
return key;

Implementing the Encryption for attributes (UserPanelFunctions.java)


//update personal details
public static void updatePersonalDetails(String username, String name,
String ic, String phone, String address, String email){
//encrypt member details before update
try {
name = SecurityFunctions.encrypt(name);
ic = SecurityFunctions.encrypt(ic);
phone = SecurityFunctions.encrypt(phone);
address = SecurityFunctions.encrypt(address);
email = SecurityFunctions.encrypt(email);
} catch (Exception e) {
System.out.println("Encrypt Personal Details Exception: " + e);}
SHAMNEEZ MOHAMUDBUCUS TP022221

50

Distributed Computer Systems


3.2

2013

User Document
The User Document, also known as User Manual allows the User to browse through

the application.

It consists of explaining functions of different interfaces.

The User

Document only explains the different interfaces while the testing sections provides full
testing and proofs of the functioning of the application.
3.2.1

Running the Server

When the server program is run with the SSL, a confirmation message is displayed on
the screen.

The following output screen shows that the SSL has been configured.

3.2.2 Login Interface


When the client is run, the register/login interface allows the user to sign into the
system. The login interface is as follows.
A new user has to register with a username that doesnt exist, else an error message is
generated. When an existing user logs in, if the username or password is not valid, an error is
displayed, else they are redirected to the Menu Screen (existing Users) and User Details
Screen (new users).

SHAMNEEZ MOHAMUDBUCUS TP022221

51

Distributed Computer Systems


3.2.3

2013

User Details Interface

The User Details allows a new user to enter his personal details. If the field is left
blank or inappropriate data type is used, an error message is generated when the user clicks
on Save button.

3.2.4 Food Menu and Purchase Interface


The Food Menu Interface allows the user to choose their food, discard their order or
confirm their order. If the food selected is not sufficient or out of stock, then an error
message is displayed.

When the user clicks on confirm button, if the amount in the

customers account is not sufficient, an error message is generated.

SHAMNEEZ MOHAMUDBUCUS TP022221

52

Distributed Computer Systems


3.2.5

2013

Transaction Interface

The transaction interface allows the user to deposit money in his account or send a
voucher to another user of the system. If any invalid data type or character length is use, an
error message is displayed. When the user clicks on Deposit button with valid credit card
number and CVV2 code, the balance of the user is updated.
The Transfer Voucher allows the user to transfer vouchers to other users accounts.
When a valid voucher code and customer username is entered, then the balance of the other
customer is updated and the voucher is deleted from the Voucher File. Any expired voucher
is not acceptable to the system.

SHAMNEEZ MOHAMUDBUCUS TP022221

53

Distributed Computer Systems

4.0

2013

TESTING
During the testing process, all buttons and text boxes of the application were

thoroughly tested to find errors. The Unit Test Table shows all the tests performed on the
Neez Food Delivery System.

4.1

Unit Testing Table


The types of Data used to test the system are:

Test
#

T1

N- Normal
A-Abnormal
E-Extreme (Border Values)

Item

Run the
Server

T2

T3

Test
data
Type
-

Username
&
Password

T4

T5

T6

Clear
button

T7

Place

Test Data

Purpose &
Test

Expected
Result

Running Server
Purpose:
A confirmation
Running the
message should
Server
be displayed.
Customer Register/Login Form
An error
message to
Username: neez
choose a new
Password: 1234
Purpose:
Username
Reject wrong
should appear.
username or
A confirmation
password
box for user
registration
Test: Click on
Username: neez1
should appear
Register in
Password: 12345
and user should
button
be redirected to
the User Details
Page.
The user should
Purpose:
Username: neez
Reject wrong be redirected to
Password: 1234
the Food Menu
username or
and order Page.
password
An error
Test: Click on message should
Username: neez
Login in
Password: 12345
be displayed on
button
the screen.
Purpose:
The Username
To check if
and Password
clear button
textboxes
clears all data should be
from textbox
emptied.
Food Menu & Order Form
Test:
The selected

SHAMNEEZ MOHAMUDBUCUS TP022221

Actual Result

Test
Result #

A confirmation
message is
displayed.

R1

An error message
to choose a new
username
appeared.

R2

A confirmation
box for user
registration
appears and user
is redirected to the
User Details Page.

R3

The user is
redirected to the
Food Menu and
order Page.

R4

An error message
is displayed on
the screen.

R5

The Username
and password
Textboxes are
emptied.

R6

The selected food

R7

54

Distributed Computer Systems


Test
#

Item

Test
data
Type

Purpose &
Test

Test Data

Click on the
Place Order
button to put
selected food
item in order
table.
Purpose:
To check if
discard
button
empties order
table
Purpose: To
test whether
quantity more
than available
food item is
rejected

Order
button

T8

Discard
button

Food ID: F1001


Quantity Entered: 2
Stored Quantity: 0

T10

Food ID: F1005


Quantity Entered: 2
Stored Quantity:8

T11

Balance: 36
Order amount: 40

T9
Customer
Food
Quantity

T12

T13

User
Order
Balance

Save
Button

T14

T15

T16

N
Credit
Card
Number
& CVV2

Balance: 36
Order Amount: 30

Test: Click on
Confirm
button
Purpose: To
test whether
order is
rejected when
user balance
is less than
order amount
Test: Click on
Confirm
Button
User Details Form

2013
Expected
Result

Test
Result #

food should
appear in the
order table.

items appear in
the order table.

The order table


should be
emptied.

The Order Table


is emptied.

R8

An error
message should
be displayed.

An error message
is displayed.

R9

The order
should be
accepted.

The order is
accepted.

R10

An error
message should
be displayed.

An error message
is displayed.

R11

Order should be
accepted and
new amount
balance
displayed in
Transaction
Interface.

Order is accepted
and new amount
balance is
displayed in
Transaction
Interface.

R12

A save
confirmation is
displayed.

R13

The Balance is
updated.

R14

An error message
is displayed.

R15

An error message
is displayed.

R15

Full Name: john


A save
IC: 123456
Purpose: To
confirmation
Phone: 012345678
see if data of
should be
Address: APU City
user is saved.
displayed
Email: 123@mail.com
Transaction Form Deposit
Credit Card Number:
Purpose: To
The Balance
4444333322221111000
check if
should be
wrong
updated.
CVV2: 321
combinations
Credit Card Number:
of Credit
An error
4444333322221111000
Card Number
message should
and CVV2
be displayed.
CVV2: 322
are rejected
Credit Card Number:
Test: Click on An error
4444333322221111001
message should
Confirm
be displayed.
Button
CVV2: 321

SHAMNEEZ MOHAMUDBUCUS TP022221

Actual Result

55

Distributed Computer Systems


Test
#

Item

Test
data
Type

Test Data

20

T18

Ss

T19

T17
Amount

T20

Voucher
Code

T21

A
E

T22

N
Transfer
to

T23

T24

T25

Multiple
Users
Effect on
quantity

4.2

Purpose &
Test
Purpose:
To check if
data type
other than
integer is
rejected

2013
Expected
Result

Actual Result

Test
Result #

Deposit should
be successful.

Deposit is
successful.

R14

An error
message should
be displayed.

An error message
is displayed.

R16

Voucher amount
and expiry date
are displayed.

R17

An error message
is displayed.

R18

An error message
is displayed.

R19

Amount is
transferred and
Voucher Code is
deleted from
Voucher File.

R20

An error message
is displayed.

R21

An error message
is displayed.

R22

The second user


cannot order and a
stock error
message is
displayed.

R23

Test: Click on
Confirm
Button
Transaction Form Voucher Transfer
Voucher amount
and expiry date
Purpose:
ABCDEFG123456789
should be
To see if
displayed.
incorrect
voucher code An error
Empty
is rejected
message should
be displayed.
Test: Click on An error
Check Button message must
11222211111111
be displayed
Amount should
Purpose:
be transferred
Non-existing
Valid Voucher Code
and Voucher
username
and
&
code should be
invalid
Username: john
deleted from
voucher
Voucher file.
should be
Invalid Voucher Code
rejected
An error
&
message must
Username: john
Test:
be displayed
Click on
Valid Voucher Code
An error
Confirm
&
message must
Button
Username:sss
be displayed
The second user
should not be
Test: Click on
Two user trying to buy
able to order
purchase
the same food which has
and a stock
from both
quantity 1
error message
screens
should be
displayed.

Test Results
The test results are proofs the tests have been carried out and the results are shown in

the table on the following pages.

SHAMNEEZ MOHAMUDBUCUS TP022221

56

Distributed Computer Systems


Test
Result #

2013

Result
Running Server

R1

SSL Configuration:
Customer Register/Login Form

R2

R3

R4

R5

SHAMNEEZ MOHAMUDBUCUS TP022221

57

Distributed Computer Systems


Test
Result #

2013

Result

R6

Food Menu & Order Form

R7

After Clicking Yes:

R8

R9

R10

SHAMNEEZ MOHAMUDBUCUS TP022221

58

Distributed Computer Systems


Test
Result #

2013

Result

R11

R12

New Balance:
User Details Form

R13

SHAMNEEZ MOHAMUDBUCUS TP022221

59

Distributed Computer Systems


Test
Result #

2013

Result
Transaction Form Deposit

R14

R15

R16

Transaction Form Voucher Transfer

R17

R18

R19

SHAMNEEZ MOHAMUDBUCUS TP022221

60

Distributed Computer Systems


Test
Result #

Result

R20

After clicking yes:

2013

Voucher Number no longer exists in voucher file

R21

R22

SHAMNEEZ MOHAMUDBUCUS TP022221

61

Distributed Computer Systems


Test
Result #

2013

Result

R23

The User on the left booked first, therefore he got the last item and the user on the right got the
error message even though the store quantity on the Food Menu shows 1.

SHAMNEEZ MOHAMUDBUCUS TP022221

62

Distributed Computer Systems

5.0

CRITICAL EVALUATION

5.1

Limitations

2013

The RMI concept is a new technology learnt since a short span of time by the
developer which was quite hard. Therefore the system has some limitations which will be
discussed. Firstly, no proper concurrency method has been developed for the application
since the requirement was to allow users to access the server and obtain the most updated
values of quantity which can be satisfied by this application. Secondly, The administrator
does not have any proper interface to input the food details, image, voucher numbers in the
application and therefore has to write directly to the file following the given format.
Moreover, users cannot view their receipts via this system and validations have not
been applied in user details (name, address, phone) due to the lack of time for developing the
system.

5.2

Future Enhancements
The current application is functioning perfectly based on the requirements put forward

in the question. However few additional components that would have made the application
very interesting will be discussed as there was not enough time to implement the features.
.
The receipts generated in the application can only be stored in the Receipts File. A
View Receipt Option can be integrated in order to allow the customers to view the previous
orders made.
The administrator has to enter the food details, voucher numbers and credit card
details manually into the files in the current system which can be improved by adding
interfaces to do the actions and a proper credit card validation system with the banks.
One more feature which may be required in future if more components will be
integrated is the Concurrency Hash Map, which allows threads to use the processes of the
server without the need to use locks, which may slow down the efficiency of the system.

SHAMNEEZ MOHAMUDBUCUS TP022221

63

Distributed Computer Systems

6.0

2013

CONCLUSION
During the course of this assignment, the RMI technology was well grasped in order

to build a system of quality. Moreover one thing to be highlighted while using the RMI
technology is that the server needs to be optimized for performance, i.e., the server should not
be overloaded with functions, which may slow down the processes. Small functions such as
validation of input data can be implemented on the user interface rather than on the server to
optimize efficiency of the server for the major functions.
Since the technology was newly learnt and the time for the coursework was quite less,
the maximum time that could be dedicated to the project was allocated and all the
requirements of the assignment have been fulfilled. It is very important to understand the
advantages of using the RMI technology which are to allow multiple users to access the
server at the same time as well as give a superficial look of simplicity to the code, whereby
objects being remote, are treated as if they were local on the machine the client is being run.
To shed the light on the experience and teachings obtained through the assignment, it
can be said that the basic knowledge of java on object oriented programming that has been
taught in the lower levels, has been greatly enhanced to be applied in the RMI technology,
with Transport Layer Security (TLS) protocol, previously known as Secure Socket Layer
protocol to allow data to be transmitted in a secure network. Moreover manipulation of data
for a large application using arrays and text files was also very challenging to implement as
logic errors could be fatal for the system. An additional feature was also added which was
the encryption and decryption of user details to protect confidentiality and integrity. If more
time was allocated, a better application could have been presented with additional features
like view receipts.

SHAMNEEZ MOHAMUDBUCUS TP022221

64

Distributed Computer Systems

2013

REFERENCES
Code Ranch. 2009. Best Way to Write an Array To A File (Beginning Java forum at
JavaRanch). [online] Available at: http://www.coderanch.com/t/456763/java/java/WriteArray-File [Accessed: 7 Jun 2013].
EDN. 1994. AWT vs Swing. [online] Available at: http://edn.embarcadero.com/article/26970
[Accessed: 5 Jun 2013].
Java Tutorials Point. 2011. Remote Method Invocation (RMI) - javatpoint. [online] Available
at: http://www.javatpoint.com/RMI [Accessed: 20 June 2013].
Oracle Tutorials. 1995. Trail: RMI (The Java Tutorials). [online] Available at:
http://docs.oracle.com/javase/tutorial/rmi/ [Accessed: 22 Jun 2013].
Oracle. 2013. Remote Method Invocation Home. [online] Available at:
http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136424.html [Accessed: 25
Jun 2013].
Sanjaal. 2013. Get Public Key Of SSL Certificate In Java - Kushal's Java Blog | Software
Engineering Blog. [online] Available at: http://sanjaal.com/java/tag/get-public-key-of-sslcertificate-in-java/ [Accessed: 15 Jul 2013].
Stack Overflow. n.d.. encryption - How to encrypt String in Java - Stack Overflow. [online]
Available at: http://stackoverflow.com/questions/1205135/how-to-encrypt-string-in-java
[Accessed: 30 Jun 2013].
Williams, D. 2011. ConcurrentHashMap - avoid a common misuse!. [online] Available at:
http://ria101.wordpress.com/2011/12/12/concurrenthashmap-avoid-a-common-misuse/
[Accessed: 14 Jul 2013].

SHAMNEEZ MOHAMUDBUCUS TP022221

65

Vous aimerez peut-être aussi