diff --git a/src/com/coder/client/CoderClient.java b/src/com/coder/client/CoderClient.java index f8f216b..26b0b96 100644 --- a/src/com/coder/client/CoderClient.java +++ b/src/com/coder/client/CoderClient.java @@ -1,5 +1,7 @@ package com.coder.client; +import java.io.IOException; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -7,6 +9,8 @@ import javax.swing.JOptionPane; import com.coder.client.LoginDialog.LoginDialogAction; import com.coder.server.CoderServer; +import com.coder.server.message.CoderMessage; +import com.coder.server.message.ProjectListData; import zutil.log.LogUtil; @@ -16,15 +20,13 @@ public class CoderClient extends Thread{ private String url; private int port; private Session session; - private ClientWindow window; - private LoginDialog loginDialog; + private ProjectEditorWindow projectEditorWindow; public CoderClient(String url, int port) { this.url = url; this.port = port; - this.window = new ClientWindow("CoderClient"); - + this.projectEditorWindow = new ProjectEditorWindow("CoderClient"); super.start(); } @@ -32,18 +34,37 @@ public class CoderClient extends Thread{ public void run(){ //save the previously typed user name String username = ""; + //keep track of the number of connection retries to the server + int connectionRetries = 0; while(true){ - //close previou session if applicable + //close previous session if applicable closeCurrentSession(); //setup a new session + if(connectionRetries > 0){ + logger.info("This is reconnection try number: " + connectionRetries); + } this.session = Session.setupConnection(url, port); if(session == null){ 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.setVisible(true); //blocking loginDialog.dispose(); @@ -58,15 +79,35 @@ public class CoderClient extends Thread{ boolean authenticated = session.authenticate(username, password); if(!authenticated){ 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; } + //resister a message listener to the session + session.addCoderMessageReceivedListener(new CoderMessageReceivedListener() { + @Override + public void projectListRspReceived(Map projectListRsp) { + //TODO + } + }); + //start receiving traffic from the server session.start(); - //show the user the main GUI - this.window.setVisible(true); + //add a listener to forward messages from the editor GUI to the server + 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) {} //wait here until the session is closed for some reason @@ -75,12 +116,13 @@ public class CoderClient extends Thread{ } //hide the main GUI - logger.info("The socket was closed. terminating."); - this.window.setVisible(false); + logger.info("The socket was closed."); + this.projectEditorWindow.setVisible(false); Thread.yield(); } + logger.info("The program till now terminate"); closeCurrentSession(); - this.window.dispose(); + this.projectEditorWindow.dispose(); System.exit(0); } diff --git a/src/com/coder/client/CoderMessageReceivedListener.java b/src/com/coder/client/CoderMessageReceivedListener.java index f57f3a8..07bc95c 100644 --- a/src/com/coder/client/CoderMessageReceivedListener.java +++ b/src/com/coder/client/CoderMessageReceivedListener.java @@ -1,7 +1,11 @@ package com.coder.client; +import java.util.Map; + +import com.coder.server.message.ProjectListData; + public interface CoderMessageReceivedListener { - void msgReceived(Class msgClass, Object authenticationChallenge); + void projectListRspReceived(Map projectListRsp); } diff --git a/src/com/coder/client/GUIMessageSentListener.java b/src/com/coder/client/GUIMessageSentListener.java new file mode 100644 index 0000000..8cfed37 --- /dev/null +++ b/src/com/coder/client/GUIMessageSentListener.java @@ -0,0 +1,9 @@ +package com.coder.client; + +import com.coder.server.message.CoderMessage; + +public interface GUIMessageSentListener { + + void sendMessage(CoderMessage msg); + +} diff --git a/src/com/coder/client/LoginDialog.java b/src/com/coder/client/LoginDialog.java index 54c2a1c..a7f0a45 100644 --- a/src/com/coder/client/LoginDialog.java +++ b/src/com/coder/client/LoginDialog.java @@ -20,87 +20,84 @@ import javax.swing.border.LineBorder; public class LoginDialog extends JDialog { private static final long serialVersionUID = 9196349269499229433L; - private JTextField tfUsername; - private JPasswordField pfPassword; - private JLabel lbUsername; - private JLabel lbPassword; - private JButton btnLogin; - private JButton btnCancel; - private LoginDialogAction loginAction = LoginDialogAction.CANCEL; - - public static enum LoginDialogAction{ + public static enum LoginDialogAction{ LOGIN, CANCEL } + private LoginDialogAction loginAction = LoginDialogAction.CANCEL; + private JTextField usernameTextField; + private JPasswordField passwordPasswordField; + private JButton loginButton; + private JButton cancelButton; public LoginDialog(String username, Frame parent) { super(parent, "Login", true); - // - JPanel panel = new JPanel(new GridBagLayout()); - GridBagConstraints cs = new GridBagConstraints(); + + JPanel fieldPanel = new JPanel(new GridBagLayout()); + GridBagConstraints gridBagConstraints = new GridBagConstraints(); - cs.fill = GridBagConstraints.HORIZONTAL; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; - lbUsername = new JLabel("Username: "); - cs.gridx = 0; - cs.gridy = 0; - cs.gridwidth = 1; - panel.add(lbUsername, cs); + JLabel usernameLabel = new JLabel("Username: "); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 1; + fieldPanel.add(usernameLabel, gridBagConstraints); - tfUsername = new JTextField(20); - tfUsername.setText(username); - cs.gridx = 1; - cs.gridy = 0; - cs.gridwidth = 2; - panel.add(tfUsername, cs); + usernameTextField = new JTextField(20); + usernameTextField.setText(username); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 2; + fieldPanel.add(usernameTextField, gridBagConstraints); - lbPassword = new JLabel("Password: "); - cs.gridx = 0; - cs.gridy = 1; - cs.gridwidth = 1; - panel.add(lbPassword, cs); + JLabel passwordLabel = new JLabel("Password: "); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 1; + fieldPanel.add(passwordLabel, gridBagConstraints); - pfPassword = new JPasswordField(20); - cs.gridx = 1; - cs.gridy = 1; - cs.gridwidth = 2; - panel.add(pfPassword, cs); - panel.setBorder(new LineBorder(Color.GRAY)); + passwordPasswordField = new JPasswordField(20); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + fieldPanel.add(passwordPasswordField, gridBagConstraints); + 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(); - bp.add(btnLogin); - bp.add(btnCancel); + JPanel buttonPanel = new JPanel(); + buttonPanel.add(loginButton); + buttonPanel.add(cancelButton); - getContentPane().add(panel, BorderLayout.CENTER); - getContentPane().add(bp, BorderLayout.PAGE_END); + getContentPane().add(fieldPanel, BorderLayout.CENTER); + getContentPane().add(buttonPanel, BorderLayout.PAGE_END); - btnLogin.addActionListener(new ActionListener() { + loginButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { loginAction = LoginDialogAction.LOGIN; dispose(); } }); - btnCancel.addActionListener(new ActionListener() { + cancelButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { loginAction = LoginDialogAction.CANCEL; dispose(); } }); - tfUsername.addKeyListener(new KeyListener(){ + usernameTextField.addKeyListener(new KeyListener(){ @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_ENTER){ - btnLogin.doClick(); + loginButton.doClick(); }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 public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_ENTER){ - btnLogin.doClick(); + loginButton.doClick(); }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() if(username.isEmpty() == false){ - pfPassword.requestFocusInWindow(); + passwordPasswordField.requestFocusInWindow(); } setResizable(false); @@ -151,11 +148,11 @@ public class LoginDialog extends JDialog { } public String getUsername() { - return tfUsername.getText().trim(); + return usernameTextField.getText().trim(); } public char[] getPassword() { - return pfPassword.getPassword(); + return passwordPasswordField.getPassword(); } public LoginDialogAction getAction() { diff --git a/src/com/coder/client/ClientWindow.java b/src/com/coder/client/ProjectEditorWindow.java similarity index 81% rename from src/com/coder/client/ClientWindow.java rename to src/com/coder/client/ProjectEditorWindow.java index 5bf397a..011486f 100644 --- a/src/com/coder/client/ClientWindow.java +++ b/src/com/coder/client/ProjectEditorWindow.java @@ -1,6 +1,7 @@ package com.coder.client; import java.awt.Dimension; +import java.util.HashSet; import java.util.logging.Logger; import javax.swing.JButton; @@ -15,9 +16,11 @@ import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeSelectionModel; +import com.coder.server.message.CoderMessage; + import zutil.log.LogUtil; -public class ClientWindow extends JFrame implements TreeSelectionListener { +public class ProjectEditorWindow extends JFrame implements TreeSelectionListener { private static final long serialVersionUID = -5486192344225335322L; public static final Logger logger = LogUtil.getLogger(); @@ -26,8 +29,9 @@ public class ClientWindow extends JFrame implements TreeSelectionListener { private JTextArea codingArea; private JButton compileButton; private JButton runButton; + private HashSet GUIMessageSentListeners; - public ClientWindow(String title){ + public ProjectEditorWindow(String title){ super(title); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 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 + + } + } diff --git a/src/com/coder/client/Session.java b/src/com/coder/client/Session.java index 735d589..d25cef8 100644 --- a/src/com/coder/client/Session.java +++ b/src/com/coder/client/Session.java @@ -5,6 +5,7 @@ import java.io.BufferedOutputStream; import java.io.IOException; import java.lang.reflect.Field; import java.net.Socket; +import java.net.SocketException; import java.net.UnknownHostException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -76,7 +77,7 @@ public class Session extends Thread { close(); return; } - while(true){ + while(isConnected()){ CoderMessage msg; try { msg = in.readGenericObject(); @@ -160,6 +161,7 @@ public class Session extends Thread { logger.log(Level.INFO, "Received AuthenticationChallenge"); // Setting up encryption + /* logger.info("Setting up encryption"); String hashedPassword = Hasher.PBKDF2(clearTextPassword, username, 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); ///////////// ENCRYPTED CONNECTION ////////////////////// - + */ + //Send AuthenticationRsp CoderMessage authRsp = new CoderMessage(); authRsp.AuthenticationRsp = new AuthenticationRspMsg(); @@ -206,17 +209,9 @@ public class Session extends Thread { } private void handleMessage(CoderMessage msg){ - for(Field field : CoderMessage.class.getDeclaredFields()){ - Object obj = null; - try { - 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); - } + if(msg.ProjectListRsp != null){ + for(CoderMessageReceivedListener listener : messageReceivedlisteners){ + listener.projectListRspReceived(msg.ProjectListRsp); } } }