Added a listener for incoming traffic from the server to the application

This commit is contained in:
Daniel Collin 2015-10-13 08:13:23 +00:00
parent b08e459843
commit e7f012dc5f
6 changed files with 148 additions and 82 deletions

View file

@ -1,5 +1,7 @@
package com.coder.client; package com.coder.client;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -7,6 +9,8 @@ import javax.swing.JOptionPane;
import com.coder.client.LoginDialog.LoginDialogAction; import com.coder.client.LoginDialog.LoginDialogAction;
import com.coder.server.CoderServer; import com.coder.server.CoderServer;
import com.coder.server.message.CoderMessage;
import com.coder.server.message.ProjectListData;
import zutil.log.LogUtil; import zutil.log.LogUtil;
@ -16,15 +20,13 @@ public class CoderClient extends Thread{
private String url; private String url;
private int port; private int port;
private Session session; private Session session;
private ClientWindow window; private ProjectEditorWindow projectEditorWindow;
private LoginDialog loginDialog;
public CoderClient(String url, int port) { public CoderClient(String url, int port) {
this.url = url; this.url = url;
this.port = port; this.port = port;
this.window = new ClientWindow("CoderClient"); this.projectEditorWindow = new ProjectEditorWindow("CoderClient");
super.start(); super.start();
} }
@ -32,18 +34,37 @@ public class CoderClient extends Thread{
public void run(){ public void run(){
//save the previously typed user name //save the previously typed user name
String username = ""; String username = "";
//keep track of the number of connection retries to the server
int connectionRetries = 0;
while(true){ while(true){
//close previou session if applicable //close previous session if applicable
closeCurrentSession(); closeCurrentSession();
//setup a new session //setup a new session
if(connectionRetries > 0){
logger.info("This is reconnection try number: " + connectionRetries);
}
this.session = Session.setupConnection(url, port); this.session = Session.setupConnection(url, port);
if(session == null){ if(session == null){
logger.info("Could not setup a connection to " + url + ":" + port); logger.info("Could not setup a connection to " + url + ":" + port);
continue; connectionRetries++;
if(connectionRetries > 5){
//stop trying to connect
logger.severe("Was not able to conenct to the remote host.");
break;
}else{
//wait for awhile and try to connect one more
logger.info("Will retry to connect once more in 2 seconds.");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
continue;
}
} }
//ask for username and passwor din a dialog window //ask for username and password in a dialog window
LoginDialog loginDialog = new LoginDialog(username, null); LoginDialog loginDialog = new LoginDialog(username, null);
loginDialog.setVisible(true); //blocking loginDialog.setVisible(true); //blocking
loginDialog.dispose(); loginDialog.dispose();
@ -58,15 +79,35 @@ public class CoderClient extends Thread{
boolean authenticated = session.authenticate(username, password); boolean authenticated = session.authenticate(username, password);
if(!authenticated){ if(!authenticated){
JOptionPane.showMessageDialog(null, "Wrong username or password", "Authentication Failed", JOptionPane.INFORMATION_MESSAGE); JOptionPane.showMessageDialog(null, "Wrong username or password", "Authentication Failed", JOptionPane.INFORMATION_MESSAGE);
System.out.println("Authentication failed"); logger.info("Authentication failed: wrong username or password");
continue; continue;
} }
//resister a message listener to the session
session.addCoderMessageReceivedListener(new CoderMessageReceivedListener() {
@Override
public void projectListRspReceived(Map<String, ProjectListData> projectListRsp) {
//TODO
}
});
//start receiving traffic from the server //start receiving traffic from the server
session.start(); session.start();
//show the user the main GUI //add a listener to forward messages from the editor GUI to the server
this.window.setVisible(true); this.projectEditorWindow.addMessageSentListener(new GUIMessageSentListener(){
@Override
public void sendMessage(CoderMessage msg) {
try {
session.send(msg);
} catch (IOException e) {
logger.log(Level.SEVERE, "could not forward message from editor to the server", e);
}
}
});
//show the user the editor GUI
this.projectEditorWindow.setVisible(true);
try {Thread.sleep(1000);} catch (InterruptedException e) {} try {Thread.sleep(1000);} catch (InterruptedException e) {}
//wait here until the session is closed for some reason //wait here until the session is closed for some reason
@ -75,12 +116,13 @@ public class CoderClient extends Thread{
} }
//hide the main GUI //hide the main GUI
logger.info("The socket was closed. terminating."); logger.info("The socket was closed.");
this.window.setVisible(false); this.projectEditorWindow.setVisible(false);
Thread.yield(); Thread.yield();
} }
logger.info("The program till now terminate");
closeCurrentSession(); closeCurrentSession();
this.window.dispose(); this.projectEditorWindow.dispose();
System.exit(0); System.exit(0);
} }

View file

@ -1,7 +1,11 @@
package com.coder.client; package com.coder.client;
import java.util.Map;
import com.coder.server.message.ProjectListData;
public interface CoderMessageReceivedListener { public interface CoderMessageReceivedListener {
void msgReceived(Class msgClass, Object authenticationChallenge); void projectListRspReceived(Map<String, ProjectListData> projectListRsp);
} }

View file

@ -0,0 +1,9 @@
package com.coder.client;
import com.coder.server.message.CoderMessage;
public interface GUIMessageSentListener {
void sendMessage(CoderMessage msg);
}

View file

@ -20,87 +20,84 @@ import javax.swing.border.LineBorder;
public class LoginDialog extends JDialog { public class LoginDialog extends JDialog {
private static final long serialVersionUID = 9196349269499229433L; private static final long serialVersionUID = 9196349269499229433L;
private JTextField tfUsername; public static enum LoginDialogAction{
private JPasswordField pfPassword;
private JLabel lbUsername;
private JLabel lbPassword;
private JButton btnLogin;
private JButton btnCancel;
private LoginDialogAction loginAction = LoginDialogAction.CANCEL;
public static enum LoginDialogAction{
LOGIN, LOGIN,
CANCEL CANCEL
} }
private LoginDialogAction loginAction = LoginDialogAction.CANCEL;
private JTextField usernameTextField;
private JPasswordField passwordPasswordField;
private JButton loginButton;
private JButton cancelButton;
public LoginDialog(String username, Frame parent) { public LoginDialog(String username, Frame parent) {
super(parent, "Login", true); super(parent, "Login", true);
//
JPanel panel = new JPanel(new GridBagLayout()); JPanel fieldPanel = new JPanel(new GridBagLayout());
GridBagConstraints cs = new GridBagConstraints(); GridBagConstraints gridBagConstraints = new GridBagConstraints();
cs.fill = GridBagConstraints.HORIZONTAL; gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
lbUsername = new JLabel("Username: "); JLabel usernameLabel = new JLabel("Username: ");
cs.gridx = 0; gridBagConstraints.gridx = 0;
cs.gridy = 0; gridBagConstraints.gridy = 0;
cs.gridwidth = 1; gridBagConstraints.gridwidth = 1;
panel.add(lbUsername, cs); fieldPanel.add(usernameLabel, gridBagConstraints);
tfUsername = new JTextField(20); usernameTextField = new JTextField(20);
tfUsername.setText(username); usernameTextField.setText(username);
cs.gridx = 1; gridBagConstraints.gridx = 1;
cs.gridy = 0; gridBagConstraints.gridy = 0;
cs.gridwidth = 2; gridBagConstraints.gridwidth = 2;
panel.add(tfUsername, cs); fieldPanel.add(usernameTextField, gridBagConstraints);
lbPassword = new JLabel("Password: "); JLabel passwordLabel = new JLabel("Password: ");
cs.gridx = 0; gridBagConstraints.gridx = 0;
cs.gridy = 1; gridBagConstraints.gridy = 1;
cs.gridwidth = 1; gridBagConstraints.gridwidth = 1;
panel.add(lbPassword, cs); fieldPanel.add(passwordLabel, gridBagConstraints);
pfPassword = new JPasswordField(20); passwordPasswordField = new JPasswordField(20);
cs.gridx = 1; gridBagConstraints.gridx = 1;
cs.gridy = 1; gridBagConstraints.gridy = 1;
cs.gridwidth = 2; gridBagConstraints.gridwidth = 2;
panel.add(pfPassword, cs); fieldPanel.add(passwordPasswordField, gridBagConstraints);
panel.setBorder(new LineBorder(Color.GRAY)); fieldPanel.setBorder(new LineBorder(Color.GRAY));
btnLogin = new JButton("Login"); loginButton = new JButton("Login");
btnCancel = new JButton("Cancel"); cancelButton = new JButton("Cancel");
JPanel bp = new JPanel(); JPanel buttonPanel = new JPanel();
bp.add(btnLogin); buttonPanel.add(loginButton);
bp.add(btnCancel); buttonPanel.add(cancelButton);
getContentPane().add(panel, BorderLayout.CENTER); getContentPane().add(fieldPanel, BorderLayout.CENTER);
getContentPane().add(bp, BorderLayout.PAGE_END); getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
btnLogin.addActionListener(new ActionListener() { loginButton.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
loginAction = LoginDialogAction.LOGIN; loginAction = LoginDialogAction.LOGIN;
dispose(); dispose();
} }
}); });
btnCancel.addActionListener(new ActionListener() { cancelButton.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
loginAction = LoginDialogAction.CANCEL; loginAction = LoginDialogAction.CANCEL;
dispose(); dispose();
} }
}); });
tfUsername.addKeyListener(new KeyListener(){ usernameTextField.addKeyListener(new KeyListener(){
@Override @Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){ if(e.getKeyCode() == KeyEvent.VK_ENTER){
btnLogin.doClick(); loginButton.doClick();
}else if(e.getKeyCode() == KeyEvent.VK_ESCAPE){ }else if(e.getKeyCode() == KeyEvent.VK_ESCAPE){
btnCancel.doClick(); cancelButton.doClick();
} }
} }
@ -115,14 +112,14 @@ public class LoginDialog extends JDialog {
} }
}); });
pfPassword.addKeyListener(new KeyListener(){ passwordPasswordField.addKeyListener(new KeyListener(){
@Override @Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){ if(e.getKeyCode() == KeyEvent.VK_ENTER){
btnLogin.doClick(); loginButton.doClick();
}else if(e.getKeyCode() == KeyEvent.VK_ESCAPE){ }else if(e.getKeyCode() == KeyEvent.VK_ESCAPE){
btnCancel.doClick(); cancelButton.doClick();
} }
} }
@ -143,7 +140,7 @@ public class LoginDialog extends JDialog {
//move focus to the password field if already a username has been defined. must be done after pack() //move focus to the password field if already a username has been defined. must be done after pack()
if(username.isEmpty() == false){ if(username.isEmpty() == false){
pfPassword.requestFocusInWindow(); passwordPasswordField.requestFocusInWindow();
} }
setResizable(false); setResizable(false);
@ -151,11 +148,11 @@ public class LoginDialog extends JDialog {
} }
public String getUsername() { public String getUsername() {
return tfUsername.getText().trim(); return usernameTextField.getText().trim();
} }
public char[] getPassword() { public char[] getPassword() {
return pfPassword.getPassword(); return passwordPasswordField.getPassword();
} }
public LoginDialogAction getAction() { public LoginDialogAction getAction() {

View file

@ -1,6 +1,7 @@
package com.coder.client; package com.coder.client;
import java.awt.Dimension; import java.awt.Dimension;
import java.util.HashSet;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.swing.JButton; import javax.swing.JButton;
@ -15,9 +16,11 @@ import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel; import javax.swing.tree.TreeSelectionModel;
import com.coder.server.message.CoderMessage;
import zutil.log.LogUtil; import zutil.log.LogUtil;
public class ClientWindow extends JFrame implements TreeSelectionListener { public class ProjectEditorWindow extends JFrame implements TreeSelectionListener {
private static final long serialVersionUID = -5486192344225335322L; private static final long serialVersionUID = -5486192344225335322L;
public static final Logger logger = LogUtil.getLogger(); public static final Logger logger = LogUtil.getLogger();
@ -26,8 +29,9 @@ public class ClientWindow extends JFrame implements TreeSelectionListener {
private JTextArea codingArea; private JTextArea codingArea;
private JButton compileButton; private JButton compileButton;
private JButton runButton; private JButton runButton;
private HashSet<GUIMessageSentListener> GUIMessageSentListeners;
public ClientWindow(String title){ public ProjectEditorWindow(String title){
super(title); super(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension minimumSize = new Dimension(500,300); Dimension minimumSize = new Dimension(500,300);
@ -84,4 +88,19 @@ public class ClientWindow extends JFrame implements TreeSelectionListener {
} }
} }
public void addMessageSentListener(GUIMessageSentListener listener) {
this.GUIMessageSentListeners.add(listener);
}
private void sendMessage(CoderMessage msg){
for(GUIMessageSentListener listener : GUIMessageSentListeners){
listener.sendMessage(msg);
}
}
public void setProjectName(String projectName) {
// TODO Auto-generated method stub
}
} }

View file

@ -5,6 +5,7 @@ import java.io.BufferedOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.net.Socket; import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -76,7 +77,7 @@ public class Session extends Thread {
close(); close();
return; return;
} }
while(true){ while(isConnected()){
CoderMessage msg; CoderMessage msg;
try { try {
msg = in.readGenericObject(); msg = in.readGenericObject();
@ -160,6 +161,7 @@ public class Session extends Thread {
logger.log(Level.INFO, "Received AuthenticationChallenge"); logger.log(Level.INFO, "Received AuthenticationChallenge");
// Setting up encryption // Setting up encryption
/*
logger.info("Setting up encryption"); logger.info("Setting up encryption");
String hashedPassword = Hasher.PBKDF2(clearTextPassword, username, AUTH_HASH_ITERATIONS); String hashedPassword = Hasher.PBKDF2(clearTextPassword, username, AUTH_HASH_ITERATIONS);
String key = Hasher.PBKDF2(hashedPassword, msg.AuthenticationChallenge.salt, AUTH_HASH_ITERATIONS); String key = Hasher.PBKDF2(hashedPassword, msg.AuthenticationChallenge.salt, AUTH_HASH_ITERATIONS);
@ -177,7 +179,8 @@ public class Session extends Thread {
out.enableMetaData(false); out.enableMetaData(false);
///////////// ENCRYPTED CONNECTION ////////////////////// ///////////// ENCRYPTED CONNECTION //////////////////////
*/
//Send AuthenticationRsp //Send AuthenticationRsp
CoderMessage authRsp = new CoderMessage(); CoderMessage authRsp = new CoderMessage();
authRsp.AuthenticationRsp = new AuthenticationRspMsg(); authRsp.AuthenticationRsp = new AuthenticationRspMsg();
@ -206,17 +209,9 @@ public class Session extends Thread {
} }
private void handleMessage(CoderMessage msg){ private void handleMessage(CoderMessage msg){
for(Field field : CoderMessage.class.getDeclaredFields()){ if(msg.ProjectListRsp != null){
Object obj = null; for(CoderMessageReceivedListener listener : messageReceivedlisteners){
try { listener.projectListRspReceived(msg.ProjectListRsp);
obj = field.get(msg);
} catch (IllegalArgumentException | IllegalAccessException e) {
logger.warning("CoderMessage field " + field.getName() + " was skipped");
}
if(obj != null){
for(CoderMessageReceivedListener listener : messageReceivedlisteners){
listener.msgReceived(field.getClass(), obj);
}
} }
} }
} }