Chat Application
Chat Application
A Project Report
On
Chat Application
I certify that this report is all my work, based on my personal study and knowledge. I have
acknowledged all material and sources used in preparation of the project.
Neha Mahajan
1
Neha Mahajan
ABSTRACT
This project report gives the detailed design and implementation of a chat application. The
chat application is developed for windows operating system. Using this application,
multiple users (clients) can communicate with each other using a single server.
Functionalities like “whisper” and “broadcasting” have been implemented based on client
server architecture. Attention to detail has been paid while developing the UI, including
error handling to make the application robust. The application uses object oriented
concepts and is developed in Java using Socket programming. The UI is developed in Java
Swing. The report includes test cases used to verify the correctness of the application. The
concluding section lists all the classes and the advanced features that can be implemented
to enhance the application.
2
Neha Mahajan
CONTENTS
1 Project Description 5
3
Neha Mahajan
5 Summary 22
6 Appendices
6.1 References 23
6.3 Code
6.3.1 ChatServer.java 42
6.3.2 ConnectionListener.java 46
6.3.3 ClientThread.java 49
6.3.4 SocketUtil.java 56
6.3.5 ServerOnlineUserListUI.java 60
6.3.6 StringLiterals.java 63
6.3.7 WPIChatClient.java 63
6.3.8 Login.java 68
6.3.9 MessageSendRecieve.java 71
6.3.10 OnlineUsersListUI.java 77
6.3.11 OnlineUserCustomButton.java 84
6.3.12 ChatWindow.java 86
4
Neha Mahajan
1. Project Description
Chatting is a method which allows users to communicate with each other despite of
geographical barriers. This chat application project is built on the chat method with
multiple clients and single server. Project consists of two separate applications
1. Client:
2. Server:
5
Neha Mahajan
The server program begins by creating a ServerSocket object on a predefined port and
waits for client connections. Once a client sends a connection request, server validates the
client for a unique username by checking in the list of online users. If successful (username
is unique) it sends list of online users to the newly connected client and updates all other
clients with the new client username. If unsuccessful it sends “not accepted” message to
client. The server handles multiple clients connect/disconnect requests and keep updating
the clients. When a client sends a broadcast message to a server, it forwards the messages
to all clients currently online. When a client wants to whisper, it sends the message to the
server along with the recipient client name. Server filters the list of online clients and sends
the message to the appropriate client. When server receives a disconnect request from a
client it removes the client from the list of online users and updates other clients.
6
Neha Mahajan
The client application begins by displaying a login page. User enters a username and sends
connection request to the server by creating a new socket with hostname of the server (for
this project it is localhost) with the specified port number (predefined for both client and
server). If successful the main page of application is displayed with the list of online users.
Users can either whisper or broadcast a message. When user clicks on a username from the
list, a chat window opens where the user can type message and send. All the exchanged
messages displayed in the scrollable area. If recipient client disconnects, the sender client
cannot send messages anymore. User can chat with multiple other clients in separate
unique chat windows. To broadcast a message user clicks on “broadcast icon” which opens
a new chat window that can be used to send messages to all online clients. All messages
which are broadcasted by any other online client will be displayed in the broadcast chat
window.
7
Neha Mahajan
START START
Open window to accpet username Open a window with Start Server button
yes
8
Neha Mahajan
yes
To all?
To all?
yes
Succesfull disconnect.
Close socket connection
End
End
9
Neha Mahajan
ChatServer
- frame : Jframe
- serverOnlineUserListUI : ServerOnlineUserListUI = null
+ UserSockets : ArrayList<SocketUtil>
+ ClientThreads : ArrayList<ClientThread> 1
- connectionListener : ConnectionListener
+ ChatServer()
- initilaize()
- startServer() «create»
+ removeClientThread(clientThread : ClientThread)
1
ClientThread
ConnectionListener
- disconnect: Boolean = false
- socketUtil: SocketUtil - serverSocket : ServerSocket
- chatServer : ChatServer - chatServer : ChatServer
+ serverSocketClosed : Boolean = false
«create»
+ ClientThread()
+ run() 1..* 1 + ConnectionListener(parentChatServer : ChatServer )
- disconnectClient() + run()
- sendMessageToFromUser(input : String) + closeServerSocket()
- checkIfUsernameExists(username : String) : Boolean
- broadcastOnlineUsers()
- sendMessageToUser(inputMessage : String) «create»
1
«create»
1
SocketUtil
- username : String ServerOnlineUserListUI
:
- socket: Socket
- messageOut: PrintWriter - frame : Jframe
- messageIn: BufferedReader - usersListTextArea: JTextArea
+ SocketUtil(socket : Socket)
+ setSocket(socket : Socket) + ServerOnlineUserListUI()
+ getSocket() : Socket - initilaize()
+ setUsername(username : String) + updateList(userSockets : ArrayList<ServerOnlineUsersListObject>)
+ getUsername() : String + hidePage()
+ sendMessage(message : String) + showPage()
+ getMessage() : String
+ closeSocket()
StringLiterals
+ USER_NOT_ACCEPTED : String
+ FROM : String
+ TO : String
+ ONLINE_USERNAMES : String
+ START_SERVER : String
+ OK : String
+ USERNAME : String
+ CONNECT : String
+ ERROR_NEW_USER : String
+ ONLINE : String
+ SEND : String
+ SERVER_STARTED : String
+ NO_USER_ONLINE : String
+ SEND_TO_ALL : String
+ LOGGED_IN_AS : String
+ YOU : String
+ DISCONNECT : String
+ UNABLE_TO_CONNECT : String
+ SERVER_ONLINE_USERS_BUTTON : String
+ SERVER_NO_USER : String
10
Neha Mahajan
Java sockets use TCP Protocol for communication. The above line creates a
new Server socket on port 9001. Any port number can be used which is not
reserved for other services.
tempClientThread.start();
When a client writes a message to the output stream, the server processes
the message in the input stream for the client socket. Using the ArrayList
server filters the sockets for recipient name and writes the message to the
receiver’s output stream. Depending on the type of message (whisper or
broadcast) server decides to write messages to all output streams
(broadcast) or only to receiver’s output stream (whisper).
11
Neha Mahajan
If server is closed / stopped, it sends error messages to all users, closes the
server socket and the application terminates.
Java Swing is used to design the server UI. UI components like JButtons,
TextArea, Labels, JFrame etc. are used for designing. Images are used
wherever required.
4. SocketUtil: Creates input and output streams using client socket. Reads
messages from input stream and writes messages to output stream.
12
Neha Mahajan
OnlineUsersListUI
- ChatWindows : ArrayList<ChatWindow> OnlineUserCustomButton
- frame : JFrame :
- parent : WPIChatClient 1..*- usernameText : JLabel
- sendToAll : ChatWindow 1
- onlineUserCount : Integer = 0 «create» + OnlineUserCustomButton(username : String, x : Integer, y : Integer)
- username : String + getUsername() : String
+ OnlineUsersListUI(parent: WPIChatClient)
- initialize() 1
- createSendAllWindow()
+ updateOnlineUsersList(onlineUsers: String, username : String) 1
- showUserLoggedIn(users : String[])
- showUserLoggedOff(users : String[]) ChatWindow
- openChatWindow(user : String)
- recieverUserName : String
+ displayMessageToUser(input : String)
- frame : JFrame
+ sendMessage(message : String)
- parent : OnlineUsersListUI
+ getUsername() : String
- btnSend : JButton
- disconnectFromServer()
- isOnline : Boolean
+ hidePage()
- inputChat : TextArea
- outputChat : TextArea
13
Neha Mahajan
new InputStreamReader(this.echoSocket.getInputStream()));
Create a socket with hostname of the server (hostname = localhost) and port
9001. Create input and output streams.
On the online user’s list UI window, user can select to whisper or broadcast a
message. The online users list is maintained in an Array of Strings. For each
user a button is created and displayed in scrollable list. To chat with a user,
the button with his/her name is clicked. On click of the button, a new chat
window is opened. On click of the broadcast message icon, a separate chat
window is opened.
When user types a message in chat window and clicks send button, message
is written to the output stream of socket. Message contains fields as From, To
and Message.
14
Neha Mahajan
Java Swing is used to design the server UI. UI components like JButtons,
TextArea, Labels, JFrame etc. are used for designing. Images are used
wherever required.
5. ChatWindow: Opens new chat window where user can send and read
message logs in scrollable area.
15
Neha Mahajan
SERVER
Login
«include»
User
Whisper
«extend»
«extend»
«include»
Chat
«extend»
Broadcast
Logout
16
Neha Mahajan
createLoginPage()
MessageSendRecieve
Launch (username,this)
application
USER
createConnection()
sendName(username)
if error show
login page
displayOnlineUserUI
(onlineUsers, username)
17
Neha Mahajan
Unit testing is a software development process in which the smallest testable parts
of an application, called units, are individually and independently scrutinized for
proper operation. Unit testing is often automated but it can also be done manually.
Following table lists down the test cases to check functionality and correctness of
each module of client. For test cases 7- 11 the login page was bypassed locally to test
functionality for online user’s list UI page and chat windows. Hence the test data
was hardcoded to achieve required results.
18
Neha Mahajan
Following table lists down the test cases to check functionality and correctness of
each module of server.
19
Neha Mahajan
Integration testing was done with real client and server application. Few
tests cases are shown in the below table. Detailed test cases and results along
with screenshots are available in the appendix section.
20
Neha Mahajan
4.1 Limitations
4.2 Enhancements
There is always a room for improvements in any software, however good and
efficient it may be. Currently as given in limitation we just deal with text
communication. In future the software can be extended to include services
like
21
Neha Mahajan
5. Summary
The “Chat application” allows multiple users to exchange information from different
locations. This project helped in understanding the client-server model, how sockets
work and what problems can be faced when handling multiple connections.
The report gives the detailed design of the chat application and how each module
was tested for its correctness and functionality. The report also lists down various
enhancements that can be done. The project helped in understanding why testing
the software is important part of development and if not done on time, how it can
affect the entire functionality of the project.
22
Neha Mahajan
6. Appendices
6.1 References
1. https://docs.oracle.com/javase/tutorial/networking/sockets/
2. https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html
3. http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
4. https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html
Test Case 1
Test Description:
To verify login page user interface. Check the alignment of UI
components. Username Label, username input text field,
close/minimize/connect buttons are displayed.
Steps:
Launch the client application.
Expected Result:
Username text field should be visible and editable.
Connect/close/minimize buttons should be visible.
Actual Result:
Login page is displayed with all UI components.
Status: PASS
23
Neha Mahajan
Test Case 2
Test Description:
Username is greater than 8 characters.
Steps:
Launch the client application.
Enter username with more than 8 characters.
Click on connect button.
Expected Result:
Display error popup for maximum number of characters for
username.
Actual Result:
Popup is shown with error message.
Status: PASS
24
Neha Mahajan
Test Case 3
Test Description:
Username is empty
Steps:
Launch the client application.
Do not enter username.
Click on connect button.
Expected Result:
Display error popup for invalid username.
Actual Result:
Popup is shown with error message.
Status: PASS
25
Neha Mahajan
Test Case 4
Test Description:
Username is not unique.
Steps:
Launch the server application and click on start server button.
Launch the client application.
Enter username as “Neha”.
Click on connect button.
Launch another client application.
Enter username again as “Neha”.
Click on connect button.
Expected Result:
If username not unique display error message popup and ask for
new username.
Actual Result:
Popup is shown with error message.
Status: PASS
26
Neha Mahajan
Test Case 5
Test Description:
Username is unique.
Steps:
Launch the server application and click on start server button.
Launch the client application.
Enter unique username as “Neha”. Make sure there is no other client
whose username is “Neha”.
Click on connect button.
Expected Result:
User must be navigated to online user’s list UI page.
Actual Result:
Online user’s list UI page is displayed.
Status: PASS
27
Neha Mahajan
Test Case 6
Test Description:
Check if clients are updated when new user joins.
Steps:
Launch the server application and click on start server button.
Launch the client application.
Enter unique username as “Neha”.
Click on connect button.
Launch the client application.
Enter unique username as “Poonam”.
Click on connect button.
Expected Result:
New user must be displayed to already connected users.
New user must be navigated to online user’s list UI page.
List of online users must be visible on online user’s list UI page of
new user.
Actual Result:
Online user’s list UI page is displayed.
Status: PASS
28
Neha Mahajan
29
Neha Mahajan
Test Case 7
Test Description:
Message send by one client is received by another client (whisper).
Steps:
Launch the server application and click on start server button.
Launch the client application.
Enter unique username as “Neha”.
Click on connect button.
Launch the client application.
Enter unique username as “Poonam”.
Click on connect button.
Online user’s list UI page is visible. Click on “Neha” to open a chat
window.
Type a message in output text field and click on send button.
Expected Result:
Message send must be displayed in the input text area of both sender
and receiver.
If chat window on receiver side is not open, chat window opens and
message is displayed.
Actual Result:
Message is displayed.
Status: PASS
“Poonam” is logged in. Online Users list UI page contains “Neha” as online user.
30
Neha Mahajan
Chat window for “Neha” opens. Message is typed and displayed in the input text are.
Message typed by “Poonam” is displayed in the output text of chat window for “Neha”.
“Neha” type’s message back and clicks on send button.
Messages typed by “Neha”, is displayed in chat window for both “Neha” and
“Poonam”.
31
Neha Mahajan
Test Case 8
Test Description:
Message send by one client is received by all other clients
(broadcast).
Steps:
Launch the server application and click on start server button.
Launch the client application.
Enter unique username as “Neha”.
Click on connect button.
Launch the client application.
Enter unique username as “Poonam”.
Click on connect button.
Launch the client application.
Enter unique username as “Satish”.
Click on connect button.
Let anyone open broadcast chat window by clicking on broadcast
icon on online user’s list UI page.
Type a message in output text field of broadcast chat window and
click on send button.
Expected Result:
Message send by anyone is seen in the broadcast chat window for all
online users.
Actual Result:
Message is displayed in broadcast window for all online users.
Status: PASS
32
Neha Mahajan
33
Neha Mahajan
34
Neha Mahajan
Test Case 9
Test Description:
User clicks send button without typing a message.
Steps:
Launch the server application and click on start server button.
Launch the client application.
Enter unique username as “Neha”.
Click on connect button.
Launch the client application.
Enter unique username as “Poonam”.
Click on connect button.
Click on “Poonam” button in “Neha” online user list UI page.
Click on send button without typing anything in the input text area.
Expected Result:
Error message is shown in popup.
Actual Result:
Error message is displayed.
Status: PASS
35
Neha Mahajan
36
Neha Mahajan
Test Case 10
Test Description:
If user logs off, and chat window is open for that user in another user
application the offline message cannot be sent.
Steps:
Launch the server application and click on start server button.
Launch the client application.
Enter unique username as “Neha”.
Click on connect button.
Launch the client application.
Enter unique username as “Poonam”.
Click on connect button.
Open chat window for “Poonam” from “Neha’s” chat application.
Exchange few messages.
Now disconnect “Poonam” by clicking on log off button in the online
user’s list UI page.
Expected Result:
Send button should not be clickable and user is offline message must
be displayed in the output text area for “Neha’s” application.
“Poonam” must be removed from the online user’s list for “Neha”
application.
Actual Result:
Send button is disabled and offline message is displayed
Status: PASS
37
Neha Mahajan
“Poonam” has logged off. “Neha” is updated and “Poonam” is removed from online user’s list. Send
button is disabled and offline status is shown.
38
Neha Mahajan
Test Case 11
Test Description:
Client disconnects.
Steps:
Launch the server application and click on start server button.
Launch the client application.
Enter unique username as “Neha”.
Click on connect button.
Click on logoff button.
Expected Result:
Client must be removed from server list and login page for the client
is displayed.
Actual Result:
Login page is shown. Client removed from server list.
Status: PASS
39
Neha Mahajan
Test Case 12
Test Description:
Server disconnects.
Steps:
Launch the server application and click on start server button.
Launch the client application.
Enter unique username as “Neha”.
Click on connect button.
Close the server by clicking the close button.
Expected Result:
Error message in a popup must be displayed to client. On click of ok
button client application must terminate.
Actual Result:
Error message is shown in the popup. Clicking on ok buttons
terminates the client application.
Status: PASS
40
Neha Mahajan
41
Neha Mahajan
6.3.1 ChatServer.java
To load the entire project just import the project in the eclipse IDE and run the
ChatServer.java and WPIChatClient.java file. I have attached the zip file of the project on my
wpi. Images are used in the project and hence all folders must be at the same level as given
in the zip file.
import java.awt.EventQueue;
/**
* Main launch point of the server application.
* @author Neha Mahajan.
*/
public class ChatServer {
/**
* Constructor.
* Calls method to draw UI components.
* @param none
* @return none
*/
public ChatServer() {
42
Neha Mahajan
initialize();
}
/**
* Creates the main JFrame and adds all UI components to it.
* Contains function calls for close,minimize,start server and list
online users button.
* Drag functionality for JFrame is implemented in the function.
* @param none
* @return none
*/
private void initialize() {
frame = new JFrame();
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent we) {
try {
if(connectionListener != null){
connectionListener.serverSocketClosed =
true;
connectionListener.closeServerSocket();
}
System.exit(0);
} catch (IOException e) {
}
}
});
frame.setBounds(550, 220, 254, 254);
//frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setUndecorated(true);
frame.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
frame.setShape(new RoundRectangle2D.Double(0, 0,
frame.getWidth(), frame.getHeight(), 20, 20));
}
});
lblStartServer = new
JLabel(StringLiterals.START_SERVER,SwingConstants.CENTER);
lblStartServer.setFont(new Font("Segoe UI Symbol", Font.BOLD,
13));
lblStartServer.setForeground(Color.WHITE);
lblStartServer.setBounds(42, 190, 163, 14);
frame.getContentPane().add(lblStartServer);
43
Neha Mahajan
lblStartServer.setText(StringLiterals.SERVER_STARTED);
startServer();
}
});
btnOk.setBounds(78, 217, 89, 23);
frame.getContentPane().add(btnOk);
listUsersBtn = new
JButton(StringLiterals.SERVER_ONLINE_USERS_BUTTON);
listUsersBtn.setVisible(false);
listUsersBtn.setBorder(null);
listUsersBtn.setBackground(Color.WHITE);
listUsersBtn.setForeground(new Color(162, 10, 35));
listUsersBtn.setFocusPainted(false);
listUsersBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if(serverOnlineUserListUI == null){
serverOnlineUserListUI = new
ServerOnlineUserListUI();
}
serverOnlineUserListUI.updateList(UserSockets);
serverOnlineUserListUI.showPage();
}
});
listUsersBtn.setBounds(58, 217, 129, 23);
frame.getContentPane().add(listUsersBtn);
44
Neha Mahajan
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(closingEven
t);
}
});
closeBtn.setBounds(233, 8, 11, 12);
closeBtn.setBorder(null);
closeBtn.setBorderPainted(false);
closeBtn.setOpaque(false);
closeBtn.setContentAreaFilled(false);
ImageIcon closeImage = new ImageIcon("images\\close.png");
closeBtn.setIcon(closeImage);
frame.getContentPane().add(closeBtn);
frame.setLocation(frame.getLocation().x+mouseEvent.getX()-
pX,frame.getLocation().y+mouseEvent.getY()-pY);
}
});
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent mouseEvent) {
pX=mouseEvent.getX();
pY=mouseEvent.getY();
}
});
panel.setBounds(0, 0, 193, 30);
panel.setOpaque(false);
frame.getContentPane().add(panel);
/**
* The function creates an object of ConnectionListener class.
* ConnectionListener class creates a new server socket.
45
Neha Mahajan
/**
* This function is called when a client disconnects from server.
* It removes the disconnected client thread from the ArrayList.
* @param clientThread contains the reference to disconnected client
thread.
* @return none
*/
public void removeClientThread(ClientThread clientThread) {
this.ClientThreads.remove(clientThread);
}
}
6.3.2 ConnectionListener.java
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
*/
46
Neha Mahajan
/**
* Constructor.
* @return none
*/
this.chatServer = parentChatServer;
this.start();
/**
* On new client connection creates new client thread and adds thread to the ArrayList.
* @param none.
* @return none.
*/
47
Neha Mahajan
try
while(true){
if(serverSocketClosed == true)
break;
tempClientThread.start();
chatServer.ClientThreads.add(tempClientThread);
}finally{
try {
if(!serverSocket.isClosed())
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
/**
48
Neha Mahajan
* @param none.
* @return none.
*/
this.serverSocket.close();
6.3.3 ClientThread.java
import java.io.IOException;
import java.net.Socket;
/**
*/
49
Neha Mahajan
/**
* Constructor.
* Creates a new SocketUtil object with reference to socket object created for the client
* @return none
*/
this.chatServer = parentChatServer;
/**
* @param none
* @return none
*/
try{
while(true){
50
Neha Mahajan
switch(outputMessage[0]){
case StringLiterals.USERNAME:
if(checkIfUsernameExists(outputMessage[1]) ==
true){
SocketUtil.sendMessage(StringLiterals.USER_NOT_ACCEPTED + ":");
} else {
SocketUtil.setUsername(outputMessage[1]);
chatServer.UserSockets.add(SocketUtil);
broadcastOnlineUsers();
break;
case StringLiterals.FROM:
sendMessageToUser(input);
break;
case StringLiterals.DISCONNECT:
this.disconnect = true;
break;
if(this.disconnect)
break;
51
Neha Mahajan
if(this.disconnect)
disconnectClient();
e.printStackTrace();
/**
* @param none
* @return none
*/
SocketUtil.closeSocket();
chatServer.UserSockets.remove(SocketUtil);
try {
broadcastOnlineUsers();
this.chatServer.removeClientThread(this);
} catch (IOException e) {
e.printStackTrace();
52
Neha Mahajan
/**
* Sends the message back to the sender to be displayed in the chat window.
* @return none
*/
SocketUtil.sendMessage(input);
/**
* It checks in the ArrayList of sockets and if username does not exists returns false.
* @return boolean
*/
SocketUtil tempUser;
tempUser = chatServer.UserSockets.get(i);
if(tempUser.getUsername().equals(username))
return true;
return false;
53
Neha Mahajan
/**
* When a new client connects and username is accepted this function is called to
* inform all the other online users about the newly connected clients.
* The function access all the user sockets from the ArrayList and writes
* @param none
* @return none
*/
if(chatServer.serverOnlineUserListUI != null){
chatServer.serverOnlineUserListUI.updateList(chatServer.UserSockets);
SocketUtil tempUser;
tempUser = chatServer.UserSockets.get(i);
tempString += tempUser.getUsername();
tempString += ":";
54
Neha Mahajan
tempUser = chatServer.UserSockets.get(i);
tempUser.sendMessage(tempString);
/**
* @return none
*/
SocketUtil tempToUser;
if(messageArray[3].equals(StringLiterals.SEND_TO_ALL)){
tempToUser = chatServer.UserSockets.get(i);
tempToUser.sendMessage(inputMesage);
} else {
sendMessageToFromUser(inputMesage);
tempToUser = chatServer.UserSockets.get(i);
55
Neha Mahajan
if(tempToUser.getUsername().equals(messageArray[3])){
tempToUser.sendMessage(inputMesage);
break;
6.3.4 SocketUtil.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
*/
56
Neha Mahajan
/**
* Constructor.
* @return none
*/
setSocket(socket);
/**
* @return none
*/
this.socket = socket;
57
Neha Mahajan
/**
* @param none.
* @return socket.
*/
return this.socket;
/**
* @return none.
*/
this.username = username;
/**
* Returns username.
* @param none.
* @return username.
*/
58
Neha Mahajan
return this.username;
/**
* @return none.
*/
this.messageOut.println(message);
this.messageOut.flush();
/**
* @exception IOException
*/
return this.messageIn.readLine();
/**
* @param none.
59
Neha Mahajan
* @return none.
* @exception IOException
*/
try {
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
6.3.5 ServerOnlineUserListUI.java
import java.awt.Frame;
/**
*
* @author Neha Mahajan
*
*/
public class ServerOnlineUserListUI {
/**
* Creates the JFrame and adds all UI components to it.
* Contains function call for minimize button.
* Drag functionality for JFrame is implemented in the function.
* @param none
* @return none
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(550, 220, 258, 374);
frame.setUndecorated(true);
60
Neha Mahajan
frame.setShape(new RoundRectangle2D.Double(0, 0,
frame.getWidth(), frame.getHeight(), 10, 10));
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setLocation(frame.getLocation().x+mouseEvent.getX()-
pX,frame.getLocation().y+mouseEvent.getY()-pY);
}
});
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent mouseEvent) {
pX=mouseEvent.getX();
pY=mouseEvent.getY();
}
});
panel.setBounds(0, 0, 200, 40);
panel.setOpaque(false);
frame.getContentPane().add(panel);
61
Neha Mahajan
lblNewLabel.setForeground(Color.BLACK);
lblNewLabel.setBounds(15, 60, 120, 14);
frame.getContentPane().add(lblNewLabel);
frame.setVisible(true);
}
/**
* Displays the updated list of online users.
* @param userSockets contains the reference to ArrayList of user
sockets created in ChatServer class.
* @return none
*/
public void updateList(ArrayList<SocketUtil> userSockets){
if(userSockets.size() == 0){
usersListTextArea.setText(StringLiterals.SERVER_NO_USER);
}
else{
String temp = "";
for(int i = 0; i < userSockets.size(); i++){
SocketUtil tempToUser = userSockets.get(i);
temp += tempToUser.getUsername() + "\n";
}
usersListTextArea.setText(temp);
}
}
/**
* Hides the JFrame.
* @param none.
* @return none
*/
public void hidePage() {
this.frame.setVisible(false);
}
/**
* Displays the JFrame.
* @param none.
* @return none
*/
public void showPage() {
this.frame.setVisible(true);
62
Neha Mahajan
}
}
6.3.6 StringLiterals.java
/**
* Contains list of all static Strings used in both client and server
classes.
* @author Neha Mahajan
*
*/
public class StringLiterals {
public static final String USER_NOT_ACCEPTED = "User Not Accepted";
public static final String FROM = "From";
public static final String TO = "To";
public static final String ONLINE_USERNAMES = "Online Usernames";
public static final String START_SERVER = "START SERVER";
public static final String OK = "OK";
public static final String USERNAME = "Username";
public static final String CONNECT = "CONNECT";
public static final String ERROR_NEW_USER = "User name already exists.
Please enter a new username";
public static final String ONLINE = "Online";
public static final String SEND = "SEND";
public static final String SERVER_STARTED = "SERVER STARTED";
public static final String NO_USER_ONLINE = "Oops no user is online to
send message";
public static final String SEND_TO_ALL = "Send To All";
public static final String LOGGED_IN_AS = "Logged in as : ";
public static final String YOU = "YOU";
public static final String DISCONNECT = "DISCONNECT";
public static final String UNABLE_TO_CONNECT = "Not able to connect to
server. Please try again later";
public static final String SERVER_ONLINE_USERS_BUTTON = "View Online
Users";
public static final String SERVER_NO_USER = "No user is connected";
public static final String ENTER_VALID_USERNAME = "Please enter a valid
username";
public static final String USERNAME_LENGTH = "Please enter maximum of 8
characters";
public static final String NO_USER_ONLINE_LABEL = "No user is online";
public static final String MESSAGE_EMPTY = "Please enter a message to
send.";
}
6.3.7 WPIChatClient.java
import java.io.IOException;
import javax.swing.JOptionPane;
63
Neha Mahajan
/**
*/
wpiChatClient.createLoginPage();
/**
* @param none
* @return none
*/
64
Neha Mahajan
/**
* @return none
*/
if(this.messageSendRecieve == null)
else {
this.messageSendRecieve.sendName(username);
/**
* @return none
65
Neha Mahajan
*/
login.hideLoginPage();
if(this.onlineUsersListUI == null){
this.onlineUsersListUI.updateOnlineUsersList(OnlineUsers,username);
/**
* @param input contains the input message(String) received from the server(sender).
* @return none
*/
this.onlineUsersListUI.displayMessageToUser(input);
/**
* @param message contains the message(String) typed by the client in the chat window.
* @return none
*/
this.messageSendRecieve.sendMessage(message);
66
Neha Mahajan
/**
* @param none.
* @return none
*/
JOptionPane.showMessageDialog(null, StringLiterals.ERROR_NEW_USER);
login.resetUsernameTextField();
/**
* @param none.
* @return none
*/
this.messageSendRecieve.sendMessage(StringLiterals.DISCONNECT + ":");
/**
* @param none.
67
Neha Mahajan
* @return none
*/
this.messageSendRecieve = null;
this.onlineUsersListUI.hidePage();
this.onlineUsersListUI = null;
this.login.showPage();
6.3.8 Login.java
import javax.swing.BorderFactory;
/**
*
* @author Neha Mahajan
*
*/
public class Login{
/**
* Constructor.
* @param parent contains reference to WPIChatClient object.
* @return none
*/
public Login(WPIChatClient parent) {
this.parent = parent;
initialize();
}
/**
* Creates the main JFrame and adds all UI components to it.
* Contains function calls for close,minimize and connect button.
* Drag functionality for JFrame is implemented in the function.
* @param none
* @return none
*/
private void initialize() {
68
Neha Mahajan
frame.getContentPane().add(usernameTextField);
usernameTextField.setColumns(10);
parent.createClientSocketConnection(usernameTextField.getText());
}
});
btnConnect.setBounds(78, 217, 89, 23);
frame.getContentPane().add(btnConnect);
69
Neha Mahajan
}
});
minimizeBtn.setBounds(205, 5, 20, 20);
minimizeBtn.setBorder(null);
minimizeBtn.setBorderPainted(false);
minimizeBtn.setOpaque(false);
minimizeBtn.setContentAreaFilled(false);
ImageIcon minimizeImage = new ImageIcon("images\\minimize.png");
minimizeBtn.setIcon(minimizeImage);
frame.getContentPane().add(minimizeBtn);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(closingEven
t);
}
});
closeBtn.setBounds(233, 8, 11, 12);
closeBtn.setBorder(null);
closeBtn.setBorderPainted(false);
closeBtn.setOpaque(false);
closeBtn.setContentAreaFilled(false);
ImageIcon closeImage = new ImageIcon("images\\close.png");
closeBtn.setIcon(closeImage);
frame.getContentPane().add(closeBtn);
frame.setLocation(frame.getLocation().x+mouseEvent.getX()-
pX,frame.getLocation().y+mouseEvent.getY()-pY);
}
});
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent mouseEvent) {
pX=mouseEvent.getX();
pY=mouseEvent.getY();
}
});
panel.setBounds(0, 0, 193, 30);
panel.setOpaque(false);
frame.getContentPane().add(panel);
70
Neha Mahajan
frame.setVisible(true);
}
/**
* Hides the JFrame of the Login Page.
* @param none
* @return none
*/
public void hideLoginPage(){
frame.setVisible(false);
}
/**
* Reset the username text field.
* @param none
* @return none
*/
public void resetUsernameTextField() {
usernameTextField.setText("");
}
/**
* Displays the JFrame of the Login Page.
* @param none
* @return none
*/
public void showPage() {
frame.setVisible(true);
}
}
6.3.9 MessageSendRecieve.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JOptionPane;
/**
71
Neha Mahajan
*/
/**
* Constructor.
* @return none
*/
72
Neha Mahajan
this.username = username;
this.parent = parent;
this.createConnection();
/**
* Creates the socket, output and input stream for the socket.
* @param none.
* @return none.
*/
try{
sendName(this.username);
this.start();
}catch (UnknownHostException e) {
JOptionPane.showMessageDialog(null, StringLiterals.UNABLE_TO_CONNECT);
73
Neha Mahajan
System.exit(1);
} catch (IOException e) {
JOptionPane.showMessageDialog(null, StringLiterals.UNABLE_TO_CONNECT);
System.exit(1);
/**
* Calls functions like display message, show error message and display online users list.
* @param none
* @return none
*/
try {
while(true){
if(input == null){
this.disconnect = true;
break;
74
Neha Mahajan
switch(messageArray[0]){
case StringLiterals.USER_NOT_ACCEPTED:
this.parent.showErrorMessage();
break;
case StringLiterals.FROM:
this.parent.displayMessageToUser(input);
break;
default:
this.parent.displayOnlineUserUI(input,
this.username);
if(this.disconnect)
this.disconnect();
} catch (IOException e) {
JOptionPane.showMessageDialog(null,
StringLiterals.UNABLE_TO_CONNECT);
System.exit(1);
/**
75
Neha Mahajan
* @param none.
* @return none.
*/
this.echoSocket.close();
this.parent.showLoginPage();
/**
* @return none.
*/
this.username = username;
sendMessage(messageToBeSent);
/**
* @return none.
*/
76
Neha Mahajan
this.messageOut.println(message);
this.messageOut.flush();
6.3.10 OnlineUsersListUI.java
import javax.swing.ImageIcon;
/**
*
* @author Neha Mahajan
*
*/
public class OnlineUsersListUI {
/**
* Constructor.
* @param parent contains reference to WPIChatClient class.
* @return none
*/
public OnlineUsersListUI(WPIChatClient parent) {
this.parent = parent;
initialize();
}
/**
* Creates the JFrame and adds all UI components to it.
* Contains the functionality for close, minimize and logout button.
* @param none.
* @return none
*/
private void initialize() {
frame = new JFrame();
77
Neha Mahajan
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
try {
disconnectFromServer();
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
});
frame.setBounds(550, 220, 258, 374);
frame.setUndecorated(true);
frame.setShape(new RoundRectangle2D.Double(0, 0,
frame.getWidth(), frame.getHeight(), 10, 10));
frame.getContentPane().setLayout(null);
noUserOnlineLabel = new
JLabel(StringLiterals.NO_USER_ONLINE_LABEL);
noUserOnlineLabel.setBounds(85, 100, 245, 260);
noUserOnlineLabel.setVisible(false);
frame.getContentPane().add(noUserOnlineLabel);
78
Neha Mahajan
logoutBtn.setBorderPainted(false);
logoutBtn.setOpaque(false);
logoutBtn.setContentAreaFilled(false);
ImageIcon logoutImage = new ImageIcon("images\\logout.png");
logoutBtn.setIcon(logoutImage);
frame.getContentPane().add(logoutBtn);
frame.setLocation(frame.getLocation().x+mouseEvent.getX()-
pX,frame.getLocation().y+mouseEvent.getY()-pY);
}
});
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent mouseEvent) {
pX=mouseEvent.getX();
pY=mouseEvent.getY();
}
});
panel.setBounds(0, 0, 200, 45);
panel.setOpaque(false);
frame.getContentPane().add(panel);
79
Neha Mahajan
frame.setVisible(true);
}
/**
* Creates an instance of broadcast chat window and stores it
reference.
* If chat window already exists then just display the chat window.
* @param none.
* @return none
*/
private void createSendAllWindow(){
if(sendToAll == null){
sendToAll = new ChatWindow(StringLiterals.SEND_TO_ALL,
this);
} else{
this.sendToAll.showPage();
}
}
/**
* Updates the UI for displaying online users list.
* @param onlineUsers contains list of all online users received from
server.
* username contains username of the logged in user.
* @return none
*/
public void updateOnlineUsersList(String onlineUsers, String username)
{
String nameText = StringLiterals.LOGGED_IN_AS + username;
usernameText.setText(nameText);
this.username = username;
String[] users = onlineUsers.split(":");
if(this.scrollPanel.getComponentCount() != 0){
this.scrollPanel.removeAll();
}
onlineUserCount = 0;
for(int i = 1; i < users.length; i++){
if(!(users[i].equals(username))){
onlineUserCount++;
OnlineUserCustomButton btnUsers = new
OnlineUserCustomButton(users[i], 0, (onlineUserCount-1) * 36);
btnUsers.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent
mouseEvent){
openChatWindow(((OnlineUserCustomButton)
mouseEvent.getSource()).getUsername());
}
});
this.scrollPanel.add(btnUsers);
80
Neha Mahajan
}
}
this.scrollPanel.setPreferredSize(new
Dimension(225,onlineUserCount * 36 + (onlineUserCount - 1)* 11));
this.scrollPanel.revalidate();
this.scrollPane.revalidate();
this.scrollPane.repaint();
if(onlineUserCount == 0){
noUserOnlineLabel.setVisible(true);
}
else {
noUserOnlineLabel.setVisible(false);
}
showUserLoggedOff(users);
showUserLoggedIn(users);
}
/**
* Show user as logged in if its chat window is open.
* If online users are greater than 1 then enable the broadcast chat
window else disable it.
* @param users contains list of all online users.
* @return none
*/
private void showUserLoggedIn(String[] users) {
for(int j = 0; j < ChatWindows.size(); j++){
if(Arrays.asList(users).contains(ChatWindows.get(j).getUsername())){
ChatWindows.get(j).showLoggedInAgain();
}
}
if(sendToAll != null){
if(onlineUserCount == 0){
sendToAll.disableSendForBroadcast();
} else {
sendToAll.enableSendForBroadcast();
}
}
}
/**
* Show user as logged off if its chat window is open.
* If online users are greater than 1 then enable the broadcast chat
window else disable it.
* @param users contains list of all online users.
* @return none
*/
private void showUserLoggedOff(String[] users) {
for(int j = 0; j < ChatWindows.size(); j++){
if(!Arrays.asList(users).contains(ChatWindows.get(j).getUsername())){
ChatWindows.get(j).showLoggedOutMessage();
}
}
81
Neha Mahajan
if(sendToAll != null){
if(onlineUserCount == 0){
sendToAll.disableSendForBroadcast();
} else {
sendToAll.enableSendForBroadcast();
}
}
}
/**
* Create instances of chat window for each user selected in the online
users list and store there references in ArrayList.
* If chat window already exists then just display the chat window.
* @param user contains name of the recipient user.
* @return none
*/
private void openChatWindow(String user){
/**
* Display the message in the appropriate chat window depending
* upon the sender name received in the message.
* If the sender is the user itself then display message in chat window
for the recipient name.
* If message is broadcast, then display message in broadcast chat
window.
* @param input contains message from the server.
* @return none
*/
public void displayMessageToUser(String input) {
String[] messageArray = input.split(":");
ChatWindow tempUserChatWindow;
Boolean userNotFound = true;
if(messageArray[3].equals(StringLiterals.SEND_TO_ALL)){
createSendAllWindow();
sendToAll.displayMessage(input);
} else {
if(messageArray[1].equals(this.username)){
for(int i = 0; i < ChatWindows.size(); i++){
tempUserChatWindow = ChatWindows.get(i);
82
Neha Mahajan
if(tempUserChatWindow.getUsername().equals(messageArray[3])){
tempUserChatWindow.displayMessage(input);
break;
}
}
} else {
for(int i = 0; i < ChatWindows.size(); i++){
tempUserChatWindow = ChatWindows.get(i);
if(tempUserChatWindow.getUsername().equals(messageArray[1])){
tempUserChatWindow.displayMessage(input);
userNotFound = false;
break;
}
}
if(userNotFound == true){
ChatWindow chatWindow = new
ChatWindow(messageArray[1], this);
ChatWindows.add(chatWindow);
chatWindow.displayMessage(input);
}
}
}
}
/**
* Returns the username of the user.
* @param none.
* @return username
*/
public String getUsername(){
return this.username;
}
/**
* Remove all the references of chat windows including broadcast chat
window.
* Clear the ArrayList of chat windows.
* This function is called when client clicks on log out/disconnect
button.
* @param none.
* @return none.
* @exception IOException
*/
private void disconnectFromServer() throws IOException {
for(int i = 0; i < ChatWindows.size(); i++){
ChatWindow tempUserChatWindow = ChatWindows.get(i);
tempUserChatWindow.hidePage();
tempUserChatWindow = null;
}
83
Neha Mahajan
ChatWindows.clear();
if(sendToAll != null){
sendToAll.hidePage();
sendToAll = null;
}
this.parent.disconnectFromServer();
}
/**
* Hides the JFrame.
* @param none.
* @return none.
*/
public void hidePage(){
this.frame.setVisible(false);
}
}
6.3.11 OnlineUserCustomButton.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*/
84
Neha Mahajan
/**
* Constructor.
* @return none
*/
this.setLayout(null);
this.setPreferredSize(new Dimension(225,36));
this.setLocation(x,y);
this.add(usernameText);
onlineIcon.setIcon(onlineIconImage);
this.add(onlineIcon);
85
Neha Mahajan
bgIcon.setIcon(bgIconImage);
this.add(bgIcon);
/**
* @param none.
* @return username(String)
*/
return this.usernameText.getText();
6.3.12 ChatWindow.java
import javax.swing.ImageIcon;
/**
*
* @author Neha Mahajan
*
*/
public class ChatWindow {
86
Neha Mahajan
/**
* Constructor.
* @param parent contains reference to OnlineUsersListUI object.
* user contains the username(String) of the recipient.
* @return none
*/
public ChatWindow(String user, OnlineUsersListUI parent) {
this.parent = parent;
this.recieverUserName = user;
initialize(user);
}
/**
* Creates the JFrame and adds all UI components to it.
* Contains function calls for close and minimize button.
* Drag functionality for JFrame is implemented in the function.
* @param user contains the username(String) of the recipient.
* @return none
*/
private void initialize(String user) {
frame = new JFrame();
frame.setBounds(550, 220, 258, 374);
frame.setUndecorated(true);
frame.setShape(new RoundRectangle2D.Double(0, 0,
frame.getWidth(), frame.getHeight(), 10, 10));
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().setLayout(null);
87
Neha Mahajan
closeBtn.setContentAreaFilled(false);
ImageIcon closeImage = new ImageIcon("images\\close.png");
closeBtn.setIcon(closeImage);
frame.getContentPane().add(closeBtn);
frame.setLocation(frame.getLocation().x+mouseEvent.getX()-
pX,frame.getLocation().y+mouseEvent.getY()-pY);
}
});
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent mouseEvent) {
pX=mouseEvent.getX();
pY=mouseEvent.getY();
}
});
panel.setBounds(0, 0, 200, 40);
panel.setOpaque(false);
frame.getContentPane().add(panel);
88
Neha Mahajan
input =
input.replaceAll(System.getProperty("line.separator"), " ");
message += input;
parent.sendMessage(message);
}
}
});
frame.getContentPane().add(btnSend);
frame.setVisible(true);
}
/**
* Returns the recipient username.
* @param none.
* @return recieverUserName
*/
public String getUsername(){
return this.recieverUserName;
}
/**
* Displays the message in the output text area of chat window.
* @param input contains the input message(String) from the sender.
* @return none.
*/
public void displayMessage(String input) {
String[] messageArray = input.split(":");
if(messageArray[1].equals(parent.getUsername())){
String messageString = StringLiterals.YOU + " : " +
messageArray[4];
outputChat.append("\n"+messageString);
}else {
String messageString = messageArray[1].toUpperCase() + " :
" + messageArray[4];
outputChat.append("\n"+messageString);
}
this.inputChat.requestFocus();
}
/**
* Displays message that recipient is online in message window if
recipient logs in again.
* Enables the send button and output text.
* @param none.
89
Neha Mahajan
* @return none.
*/
public void showLoggedInAgain(){
if(this.isOnline == false){
this.isOnline = true;
String messageString = this.recieverUserName + " : is
online";
outputChat.append("\n"+messageString);
this.btnSend.setEnabled(true);
this.inputChat.setEditable(true);
this.inputChat.setEnabled(true);
}
}
/**
* Displays message that recipient is offline in message window if
recipient logs off again.
* Disables the send button and output text.
* @param none.
* @return none.
*/
public void showLoggedOutMessage() {
if(this.isOnline == true){
this.isOnline = false;
String messageString = this.recieverUserName + " : is
offline";
outputChat.append("\n"+messageString);
this.btnSend.setEnabled(false);
this.inputChat.setEditable(false);
this.inputChat.setEnabled(false);
}
}
/**
* Hides the JFrame of the chat window.
* @param none.
* @return none.
*/
public void hidePage() {
this.frame.setVisible(false);
}
/**
* Displays the JFrame of the chat window.
* @param none.
* @return none.
*/
public void showPage() {
this.frame.setVisible(true);
}
/**
* Disable send button when no user is online for broadcast window.
* Input chat area is not editable.
* @param none.
* @return none.
*/
90
Neha Mahajan
/**
* Enables send button when user is online for broadcast window.
* Input chat area is editable.
* @param none.
* @return none.
*/
public void enableSendForBroadcast() {
this.btnSend.setEnabled(true);
this.inputChat.setEditable(true);
this.inputChat.setEnabled(true);
}
}
91