diff --git a/.gitignore b/.gitignore index 8a1baec..c0707ae 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,3 @@ *.jar *.war *.ear - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* diff --git a/ChatApp.iml b/ChatApp.iml new file mode 100644 index 0000000..e97e481 --- /dev/null +++ b/ChatApp.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ChatApp.txt b/ChatApp.txt new file mode 100644 index 0000000..b4d907b Binary files /dev/null and b/ChatApp.txt differ diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000..4e6378a --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: ChatWindow + diff --git a/src/BusyCommand.java b/src/BusyCommand.java new file mode 100644 index 0000000..8084a43 --- /dev/null +++ b/src/BusyCommand.java @@ -0,0 +1,30 @@ + +public class BusyCommand extends Command { + private String nick; + + public BusyCommand(CommandTypes type, String nick) { + super(type); + this.nick = nick; + } + + public String intoString() { + String s = "User " + this.nick +" is busy at that moment" + "\n"; + return s; + } + + public CommandTypes getType() { + return commandTypes; + } + + public void setType(CommandTypes type) { + this.commandTypes = type; + } + + public String getNick() { + return nick; + } + + public void setNick(String nick) { + this.nick = nick; + } +} diff --git a/src/CallListener.java b/src/CallListener.java new file mode 100644 index 0000000..3ab388d --- /dev/null +++ b/src/CallListener.java @@ -0,0 +1,29 @@ +import java.io.*; +import java.net.*; + +public class CallListener { + private Boolean isBusy; + private ServerSocket serverSocket; + + public CallListener(){ + setStatus(false); + } + + public Connection getConnection() throws IOException{ + if (StatusBusy()){ + return null; + }else{ + serverSocket = new ServerSocket(Protocol.PORT); + return new Connection(serverSocket.accept()); + } + } + + + public Boolean StatusBusy(){ + return isBusy; + } + + public void setStatus(Boolean statusBusy){ + this.isBusy = statusBusy; + } +} \ No newline at end of file diff --git a/src/CallListenerThread.java b/src/CallListenerThread.java new file mode 100644 index 0000000..b9d0372 --- /dev/null +++ b/src/CallListenerThread.java @@ -0,0 +1,72 @@ +import java.io.*; +import java.util.*; +import java.net.*; + +public class CallListenerThread extends Observable implements Runnable { + private Socket socket; + private ServerSocket serverSocket; + private volatile boolean disconnected; + private Connection connection; + private boolean isBusy; + private CallListener callListener; + + public CallListenerThread(){ + + } + + public void start() { + this.disconnected = false; + Thread t = new Thread(this); + t.start(); + } + + public boolean isDisconnected() { + return disconnected; + } + + public void stop() { + disconnected = true; + } + + public Connection getConnection(){ + if(socket!=null){ + try { + return new Connection(socket); + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } + + @Override + public void run(){ + try { + serverSocket = new ServerSocket(Protocol.PORT); + while (true){ + socket = serverSocket.accept(); + //IncomingConnection incomingConnection = new IncomingConnection(); + //if(Protocol.statusBusy == true){ + connection = new Connection(socket); + if (connection.getSocket()!=null) { + CommandListenerThread clt = new CommandListenerThread(connection); + clt.addObserver(ChatWindow.observer); + clt.start(); + connection.sendNickHello(Protocol.localNick); + } + //} + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void setDisconnected(boolean b){ + this.disconnected = b; + } + + public void setBusy(Boolean isBusy){ + this.isBusy = isBusy; + callListener.setStatus(isBusy); + } +} \ No newline at end of file diff --git a/src/Caller.java b/src/Caller.java new file mode 100644 index 0000000..f348702 --- /dev/null +++ b/src/Caller.java @@ -0,0 +1,19 @@ +import java.net.*; +import java.io.*; + +public class Caller { + private Socket s; + + public Caller() throws IOException{ + s = new Socket(Protocol.IP,Protocol.PORT); + } + + public Connection call() throws IOException { + try { + Class.forName("com.mysql.jdbc.Driver"); + } catch (ClassNotFoundException e) {} + Connection c = new Connection(s); + c.sendNickHello(Protocol.localNick); + return c; + } +} diff --git a/src/ChatWindow.java b/src/ChatWindow.java new file mode 100644 index 0000000..52c926e --- /dev/null +++ b/src/ChatWindow.java @@ -0,0 +1,440 @@ +import javax.swing.*; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.util.Observable; +import java.util.Observer; +import java.util.LinkedList; +import java.text.SimpleDateFormat; + +public class ChatWindow extends JFrame implements Observer { + private CallListenerThread callt; + private CommandListenerThread comt; + public static Observer observer; + private Connection connection; + + final JPanel panel = new JPanel(); + final JPanel field1 = new JPanel(); + final JPanel field2 = new JPanel(); + final JPanel field3 = new JPanel(); + final JPanel messages = new JPanel();// new + final JPanel friendsfield = new JPanel();// new + final JPanel bigfield = new JPanel();// new + final JPanel fieldmess = new JPanel(); + final JPanel field = new JPanel(); + final JPanel messArea = new JPanel(); + final JButton apply = new JButton("Apply"); + final JButton connect = new JButton("Connect"); + final JButton disconnect = new JButton("Disconnect"); + final JButton sendb = new JButton("Send"); + + final JLabel locallogin = new JLabel("local login"); + final JLabel remotelogin = new JLabel("remote login"); + final JLabel txt3 = new JLabel("remote addr"); + + final JTextField text1 = new JTextField(); + final JTextField text2 = new JTextField(); + final JTextField text3 = new JTextField(); + final JTextArea textmess = new JTextArea(); + final JTextArea mess = new JTextArea(); + + final JLabel txtfriends = new JLabel("Your friends:");// new + + public ChatWindow() throws IOException { + observer = this; + this.setSize(650, 500); + this.setTitle("This is CHAT "); + ImageIcon image = new ImageIcon("F:\\chaticon.jpg"); + this.setIconImage(image.getImage()); + callt = new CallListenerThread(); + callt.start(); + + // import contacts to linked list "listfriends" + LinkedList listfriends = new LinkedList();// linked list of + // friends + DefaultListModel listModel = new DefaultListModel();// list of + // nicks of + // friends + // for form + Protocol.serverConnection + .setServerAddress("jdbc:mysql://files.litvinov.in.ua/chatapp_server?characterEncoding=utf-8&useUnicode=true"); + Protocol.serverConnection.connect(); + if (Protocol.serverConnection.isConnected() == false) { + mess.append("[System] Could not connect to the server" + "\n"); + } else { + mess.append("[System] You connected to the server" + "\n"); + } + + Protocol.serverConnection.setLocalNick(Protocol.localNick); + Protocol.serverConnection.goOnline(); + + JList list = new JList(listModel); + Friend fr = new Friend("masha", "10.1.1.4"); + Friend fr1 = new Friend("unnamed", "5555"); + listfriends.add(fr); + listfriends.add(fr1); + listModel.addElement(fr.getNick()); + listModel.addElement(fr1.getNick()); + + list.setMaximumSize(new Dimension(150, 2500)); + list.setPreferredSize(new Dimension(150, 2500)); + list.setLayoutOrientation(JList.VERTICAL); + + JButton addButton = new JButton("Add"); + addButton.setFocusable(false); + addButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Friend newfr = new Friend(Protocol.remoteNick, Protocol.IP); + listfriends.add(newfr); + + listModel.addElement(newfr.getNick()); + int index = listModel.size() - 1; + list.setSelectedIndex(index); + list.ensureIndexIsVisible(index); + } + }); + + JButton connectButton = new JButton("Connect"); + connectButton.setFocusable(false); + connectButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int index = list.getSelectedIndex(); + for (int i = 0; i <= listfriends.size(); i++) { + if (listfriends.get(i).getNick() == listModel + .getElementAt(index)) { + String Ip = listfriends.get(i).getIp();// ip for + // connection + break; + } + } + text2.setText(listModel.getElementAt(index)); + // need connect to Ip + text3.setText(listfriends.get(index).getIp()); + + } + }); + + final JButton removeButton = new JButton("Remove"); + removeButton.setFocusable(false); + removeButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int index = list.getSelectedIndex(); + for (int i = 0; i <= listfriends.size(); i++) { + if (listfriends.get(i).getNick() == listModel + .getElementAt(index)) { + listfriends.remove(i);// remove from list of friends + break; + } + } + listModel.remove(list.getSelectedIndex());// remove from list of + // nicks + } + }); + + removeButton.setMaximumSize(new Dimension(100, 25)); + addButton.setMaximumSize(new Dimension(100, 25)); + connectButton.setMaximumSize(new Dimension(100, 25)); + + friendsfield.setLayout(new BoxLayout(friendsfield, BoxLayout.Y_AXIS)); + bigfield.setLayout(new BoxLayout(bigfield, BoxLayout.X_AXIS)); + messages.setLayout(new BoxLayout(messages, BoxLayout.Y_AXIS)); + messArea.setLayout(new BoxLayout(messArea, BoxLayout.X_AXIS)); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + field.setLayout(new BoxLayout(field, BoxLayout.X_AXIS)); + fieldmess.setLayout(new BoxLayout(fieldmess, BoxLayout.X_AXIS)); + field1.setLayout(new BoxLayout(field1, BoxLayout.Y_AXIS)); + field2.setLayout(new BoxLayout(field2, BoxLayout.Y_AXIS)); + field3.setLayout(new BoxLayout(field3, BoxLayout.Y_AXIS)); + txtfriends.setAlignmentX(JComponent.CENTER_ALIGNMENT); + txtfriends.setAlignmentY(JComponent.BOTTOM_ALIGNMENT); + list.setAlignmentY(JComponent.TOP_ALIGNMENT); + connectButton.setAlignmentY(JComponent.BOTTOM_ALIGNMENT); + addButton.setAlignmentY(JComponent.BOTTOM_ALIGNMENT); + removeButton.setAlignmentY(JComponent.BOTTOM_ALIGNMENT); + connectButton.setAlignmentX(JComponent.CENTER_ALIGNMENT); + addButton.setAlignmentX(JComponent.CENTER_ALIGNMENT); + removeButton.setAlignmentX(JComponent.CENTER_ALIGNMENT); + textmess.setLineWrap(true); + mess.setCaretPosition(0); + mess.setLineWrap(true); + mess.setEditable(false); + + textmess.setMaximumSize(new Dimension(1500, 50)); + textmess.setPreferredSize(new Dimension(70, 50)); + text1.setMaximumSize(new Dimension(100, 25)); + text2.setMaximumSize(new Dimension(100, 25)); + text3.setMaximumSize(new Dimension(100, 25)); + text2.setEnabled(false); + + apply.setPreferredSize(new Dimension(100, 25)); + apply.setMaximumSize(new Dimension(100, 25)); + connect.setPreferredSize(new Dimension(100, 25)); + connect.setMaximumSize(new Dimension(100, 25)); + disconnect.setPreferredSize(new Dimension(100, 25)); + disconnect.setMaximumSize(new Dimension(100, 25)); + sendb.setMaximumSize(new Dimension(70, 50)); + sendb.setPreferredSize(new Dimension(70, 50)); + disconnect.setEnabled(false); + + + apply.setAlignmentX(JComponent.CENTER_ALIGNMENT); + text1.setAlignmentX(JComponent.CENTER_ALIGNMENT); + locallogin.setAlignmentX(JComponent.CENTER_ALIGNMENT); + + connect.setAlignmentX(JComponent.CENTER_ALIGNMENT); + text2.setAlignmentX(JComponent.CENTER_ALIGNMENT); + remotelogin.setAlignmentX(JComponent.CENTER_ALIGNMENT); + + disconnect.setAlignmentX(JComponent.CENTER_ALIGNMENT); + text3.setAlignmentX(JComponent.CENTER_ALIGNMENT); + txt3.setAlignmentX(JComponent.CENTER_ALIGNMENT); + + field1.add(locallogin); + field2.add(txt3); + field3.add(remotelogin); + field1.add(text1); + field2.add(text3); + field3.add(text2); + field1.add(apply); + field2.add(connect); + field3.add(disconnect); + messArea.add(textmess); + messArea.add(sendb); + + friendsfield.setBackground(new Color(220, 243, 246)); + bigfield.setBackground(new Color(220, 243, 246)); + panel.setBackground(new Color(220, 243, 246)); + field1.setBackground(new Color(220, 243, 246)); + field2.setBackground(new Color(220, 243, 246)); + field3.setBackground(new Color(220, 243, 246)); + messArea.setBackground(new Color(220, 243, 246)); + mess.setBackground(new Color(237, 245, 246)); + + connectButton.setBackground(new Color(116, 199, 209)); + addButton.setBackground(new Color(116, 199, 209)); + removeButton.setBackground(new Color(116, 199, 209)); + apply.setBackground(new Color(116, 199, 209)); + connect.setBackground(new Color(116, 199, 209)); + disconnect.setBackground(new Color(116, 199, 209)); + sendb.setBackground(new Color(116, 199, 209)); + + class SendAction implements ActionListener { + private String message; + + public void actionPerformed(ActionEvent event) { + message = textmess.getText(); + long currentTimeMillis = System.currentTimeMillis(); + + try { + if (connection != null) { + if (comt != null) { + String time = new SimpleDateFormat("HH:mm:ss") + .format(currentTimeMillis); + mess.append(Protocol.localNick + " (" + time + "):" + "\n" + + " " + message + "\n"); + comt.getConnection().sendMessage(message); + } else { + String time = new SimpleDateFormat("HH:mm:ss") + .format(currentTimeMillis); + mess.append(Protocol.localNick + " (" + time + "):" + "\n" + + " " + message + "\n"); + callt.getConnection().sendMessage(message); + } + } + }catch(IOException e){ + e.printStackTrace(); + } + + textmess.setText(""); + } + } + + class ApplyAction implements ActionListener { + public void actionPerformed(ActionEvent event) { + Protocol.localNick = text1.getText(); + Protocol.serverConnection.setLocalNick(Protocol.localNick); + mess.append("[System] Nickname changed to: " + + Protocol.localNick + "\n"); + apply.setEnabled(false); + } + } + + class ConnectAction implements ActionListener { + public void actionPerformed(ActionEvent event) { + mess.setText(""); + Protocol.IP = text3.getText(); + connect.setEnabled(false); + disconnect.setEnabled(true); + textmess.setEnabled(true); + try { + Caller caller = new Caller(); + connection = caller.call(); + if (connection != null) { + comt = new CommandListenerThread(connection); + comt.addObserver(ChatWindow.this); + mess.append("Connected to " + Protocol.IP + "\n"); + comt.start(); + + } else { + mess.append("IP: " + Protocol.IP + " inaccessible" + "\n"); + connect.setEnabled(true); + disconnect.setEnabled(false); + sendb.setEnabled(false); + apply.setEnabled(true); + } + text2.setText(Protocol.remoteNick); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + class DisconnectAction implements ActionListener { + public void actionPerformed(ActionEvent event) { + if (comt != null) { + try { + comt.getConnection().disconnect(); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + comt.stop(); + comt = null; + sendb.setEnabled(false); + disconnect.setEnabled(false); + connect.setEnabled(true); + apply.setEnabled(true); + text2.setEnabled(false); + mess.append("-> Disconnected\n"); + } + } + + SendAction send = new SendAction(); + sendb.addActionListener(send); + ApplyAction applyact = new ApplyAction(); + apply.addActionListener(applyact); + ConnectAction connectact = new ConnectAction(); + connect.addActionListener(connectact); + DisconnectAction disconnectact = new DisconnectAction(); + disconnect.addActionListener(disconnectact); + + friendsfield.add(txtfriends); + friendsfield.add(list); + friendsfield.add(connectButton); + friendsfield.add(addButton); + friendsfield.add(removeButton); + fieldmess.add(mess); + final JScrollPane scrollPane = new JScrollPane(mess); + fieldmess.add(scrollPane); + + scrollPane + .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + field.add(field1); + field.add(field2); + field.add(field3); + panel.add(field); + messages.add(fieldmess); + messages.add(messArea); + bigfield.add(messages); + bigfield.add(friendsfield); + panel.add(bigfield); + + this.add(panel); + this.setVisible(true); + this.setLocationRelativeTo(null); + this.setDefaultCloseOperation(EXIT_ON_CLOSE); + } + + public static void main(String[] args) { + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + new ChatWindow(); + } catch (IOException e) { + } + } + }); + } + + @Override + public void update(Observable o, Object arg) { + + NickCommand c; + MessageCommand mescom; + Command com; + + sendb.setEnabled(true); + connect.setEnabled(false); + if (arg instanceof NickCommand) { + c = (NickCommand) arg; + Protocol.remoteNick = c.getNick(); + mess.append(c.intoString() + "\n"); + } + if (arg instanceof MessageCommand) { + mescom = (MessageCommand) arg; + + long currentTimeMillis = System.currentTimeMillis(); + String time = new SimpleDateFormat("HH:mm:ss") + .format(currentTimeMillis); + mess.append(Protocol.remoteNick + " (" + time + "):" + "\n" + " " + + mescom.getMessagetext() + "\n"); + } + if (arg instanceof Command) { + com = (Command) arg; + if (com.getType() == Command.CommandTypes.accept) { + connect.setEnabled(false); + disconnect.setEnabled(true); + sendb.setEnabled(true); + apply.setEnabled(false); + } + if (com.getType() == Command.CommandTypes.reject) { + mess.append("It seems like " + Protocol.remoteNick + " doesn't want to talk to you :c" + "\n"); + connect.setEnabled(true); + disconnect.setEnabled(false); + sendb.setEnabled(false); + apply.setEnabled(true); + } + if (com.getType() == Command.CommandTypes.disconnect) { + mess.append("Looks like we lost him :c" + "\n"); + connect.setEnabled(true); + disconnect.setEnabled(false); + sendb.setEnabled(false); + apply.setEnabled(true); + } + if (com.getType() == Command.CommandTypes.busy) { + mess.append(com.toString()); + connect.setEnabled(true); + disconnect.setEnabled(false); + sendb.setEnabled(false); + apply.setEnabled(true); + } + } + } +} + +class Friend { + public String nick; + public String ip; + + public Friend(String n, String i) { + this.nick = n; + this.ip = i; + } + + void set(String n, String i) { + this.nick = n; + this.ip = i; + } + + String getNick() { + return nick; + } + + String getIp() { + return ip; + } +} diff --git a/src/Command.java b/src/Command.java new file mode 100644 index 0000000..72436c6 --- /dev/null +++ b/src/Command.java @@ -0,0 +1,32 @@ + +public class Command { + protected CommandTypes commandTypes; + + public Command(CommandTypes commandTypes) { + this.commandTypes = commandTypes; + } + + public enum CommandTypes { + disconnect, + accept, + reject, + nickname, + message, + busy + } + public static Command createCommand(String s){ + if(s.contains("Accepted")) return new Command(CommandTypes.accept); + if(s.contains("Rejected")) return new Command(CommandTypes.reject); + if(s.contains("ChatApp 2015")) { + if (s.contains("Busy")) return new BusyCommand(CommandTypes.busy, s.replaceAll("ChatApp 2015 user ", "")); + else return new NickCommand(CommandTypes.nickname, s.replaceAll("ChatApp 2015 user ", "")); + } + if(s.contains("Disconnect")) return new Command(CommandTypes.disconnect); + if(s.contains("Message")) return new MessageCommand(CommandTypes.message,s); + else return null; + } + + public CommandTypes getType(){ + return commandTypes; + } +} diff --git a/src/CommandListenerThread.java b/src/CommandListenerThread.java new file mode 100644 index 0000000..85d726a --- /dev/null +++ b/src/CommandListenerThread.java @@ -0,0 +1,50 @@ +import java.util.*; +import java.io.*; + +public class CommandListenerThread extends Observable implements Runnable { + private Connection connection; + private volatile Command lastCommand; + private volatile boolean disconnected; + + public void start() { + this.disconnected = false; + Thread t = new Thread(this); + t.start(); + } + + public boolean isDisconnected() { + return disconnected; + } + + public void stop() { + disconnected = true; + } + + public Connection getConnection(){ + return this.connection; + } + + public CommandListenerThread(Connection connection) { + this.connection = connection; + } + + public Command getLastCommand() { + return lastCommand; + } + + @Override + public void run() { + this.addObserver(ChatWindow.observer); + while (!isDisconnected()) { + synchronized (this) { + try { + this.lastCommand = connection.recieve(); + setChanged(); + this.notifyObservers(lastCommand); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/src/Connection.java b/src/Connection.java new file mode 100644 index 0000000..334a975 --- /dev/null +++ b/src/Connection.java @@ -0,0 +1,63 @@ +import java.net.*; +import java.io.*; + +public class Connection{ + private Socket socket; + private OutputStream out; + private DataOutputStream sout; + private BufferedReader reader; + + public Connection(Socket s) throws IOException{ + this.socket = s; + out = socket.getOutputStream(); + sout = new DataOutputStream(socket.getOutputStream()); + reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); + } + + public void sendMessage(String message) throws IOException{ + sout.write(new StringBuilder("Message: \n").append(message).append("\n").toString().getBytes()); + sout.flush(); + } + + public void disconnect() throws IOException{ + sout.write(new StringBuilder("Disconnect\n").toString().getBytes()); + out.close(); + reader.close(); + socket.close(); + } + + public void sendNickHello(String nick) throws IOException { + sout.write(new StringBuilder("ChatApp 2015 user "+nick+"\n").toString().getBytes()); + sout.flush(); + } + + public void sendNickBusy(String nick) throws IOException { + if(socket.isConnected()){ + sout.write(new StringBuilder("ChatApp 2015 user ").append(nick).append(" busy\n").toString().getBytes()); + sout.flush(); + } + } + + public void accept() throws IOException{ + sout.write(new StringBuilder("Accepted\n").toString().getBytes()); + sout.flush(); + } + + public void reject() throws IOException { + sout.write(new StringBuilder("Rejected\n").toString().getBytes()); + sout.flush(); + } + + public Command recieve() throws IOException { + String s = reader.readLine(); + if(s.contains("Message")){ + s+=reader.readLine(); + } + Command command = Command.createCommand(s); + return command; + } + + public Socket getSocket(){ + return socket; + } +} diff --git a/src/IncomingConnection.java b/src/IncomingConnection.java new file mode 100644 index 0000000..79e46e3 --- /dev/null +++ b/src/IncomingConnection.java @@ -0,0 +1,63 @@ +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class IncomingConnection extends JFrame { + + public IncomingConnection() { + this.setSize(380, 150); + this.setTitle("Incoming call"); + ImageIcon image = new ImageIcon("F:\\chaticon.jpg"); + this.setIconImage(image.getImage()); + final JFrame frame= new JFrame(); + final JPanel jPanel = new JPanel(); + jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.Y_AXIS)); + final JPanel pan1 = new JPanel(); + final JPanel pan2 = new JPanel(); + final JLabel jLabel = new JLabel("User "+ Protocol.remoteNick +" wants to chat"); + final JButton acceptb = new JButton("Accept"); + final JButton declineb = new JButton("Decline"); + + acceptb.addActionListener(new ActionListener(){ + + @Override + public void actionPerformed(ActionEvent e){ + Protocol.statusBusy = true; + frame.dispose(); + } + }); + + declineb.addActionListener(new ActionListener(){ + + @Override + public void actionPerformed(ActionEvent e){ + Protocol.statusBusy = false; + frame.dispose(); + } + }); + + declineb.setPreferredSize(new Dimension(100, 25)); + acceptb.setPreferredSize(new Dimension(100, 25)); + + declineb.setBackground(new Color(116, 199, 209)); + acceptb.setBackground(new Color(116, 199, 209)); + pan1.setBackground(new Color(220, 243, 246)); + pan2.setBackground(new Color(220, 243, 246)); + pan1.add(jLabel); + pan2.add(acceptb); + pan2.add(declineb); + + jPanel.add(pan1); + jPanel.add(pan2); + frame.add(jPanel); + frame.pack(); + //this.add(jPanel); + //this.setLocationRelativeTo(null); + frame.setLocationRelativeTo(null); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + //this.setVisible(true); + frame.setVisible(true); + } + + +} diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..ec3e025 --- /dev/null +++ b/src/Main.java @@ -0,0 +1,23 @@ +import java.io.*; +import java.net.Socket; +import java.util.*; +public class Main { + public static void main(String[] args) throws IOException { + /*Socket s = new Socket("files.litvinov.in.ua",28411); + Connection c = new Connection(s,"azazaza"); + //Scanner in = new Scanner(System.in); + String string; + //while (true){ + c.sendNickHello("azazazaz"); + System.out.println(c.testRecieve()); + //c.accept(); + System.out.println(c.testRecieve()); + c.reject(); + System.out.println(c.testRecieve()); + //string = in.nextLine(); + c.disconnect(); + //c.sendMessage(string); + //System.out.println(c.testRecieve()); + //}*/ + } +} diff --git a/src/MessageCommand.java b/src/MessageCommand.java new file mode 100644 index 0000000..7698375 --- /dev/null +++ b/src/MessageCommand.java @@ -0,0 +1,21 @@ + +public class MessageCommand extends Command { + protected String messagetext; + + public MessageCommand(CommandTypes type) { + super(type); + } + + public MessageCommand(CommandTypes type, String messagetext) { + super(type); + this.messagetext = messagetext ; + } + + public String getMessagetext() { + return messagetext; + } + + public void setMessagetext(String messagetext) { + this.messagetext = messagetext; + } +} diff --git a/src/NickCommand.java b/src/NickCommand.java new file mode 100644 index 0000000..84a7cbc --- /dev/null +++ b/src/NickCommand.java @@ -0,0 +1,23 @@ + +public class NickCommand extends Command{ + protected String nick; + + public NickCommand(CommandTypes ctp) { + super(ctp); + } + + public NickCommand(CommandTypes ctp, String nick) { + super(ctp); + String[] s1 = nick.split(" "); + this.nick = s1[3]; + } + + public String intoString() { + String s = "ChatApp 2015 user " + this.nick + "\n"; + return s; + } + + public String getNick(){ + return nick; + } +} diff --git a/src/Protocol.java b/src/Protocol.java new file mode 100644 index 0000000..e292f34 --- /dev/null +++ b/src/Protocol.java @@ -0,0 +1,8 @@ +public class Protocol { + public static final int PORT =28411; + public static String localNick = "default"; + public static String remoteNick; + public static String IP; + public static boolean statusBusy = false; + public static ServerConnection serverConnection = new ServerConnection(); +} diff --git a/src/ServerConnection.java b/src/ServerConnection.java new file mode 100644 index 0000000..452c2ff --- /dev/null +++ b/src/ServerConnection.java @@ -0,0 +1,243 @@ +import java.sql.Connection; +import java.sql.*; +import java.util.*; + +public class ServerConnection { + + private String serverAddress; + private String localNick; + + private Connection con; + private Statement st; + + public ServerConnection(){ + + } + + public ServerConnection(String address){ + this(address, null); + } + + public ServerConnection(String address, String nick){ + if(nick!=null) + setLocalNick(nick); + if(address!=null){ + setServerAddress(address); + connect(); + }// if + } + + public void connect(){ + if(isConnected()) + return; + assert(serverAddress != null && !serverAddress.trim().isEmpty()); + try { + con = DriverManager.getConnection(serverAddress,"guest","guest"); + st = con.createStatement(); + } catch (SQLException e) { + // TODO throw real error + e.printStackTrace(); + }// catch + } + + public void disconnect(){ + if(st!=null){ + try { + st.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + st = null; + } + if(con!=null){ + try { + con.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + con=null; + }// if + } + + public boolean isConnected(){ + return st != null; + } + + public String getServerAddress() { + return serverAddress; + } + + public void setServerAddress(String serverAddress) { + if(serverAddress.equals(this.serverAddress)) + return; + boolean connected = isConnected(); + if(connected){ + goOffline(); + disconnect(); + } + this.serverAddress = serverAddress; + if(connected) + connect(); + } + + public String getLocalNick() { + return localNick; + } + + public void setLocalNick(String newNick) { + assert newNick!=null; + newNick = safe(newNick); + if(newNick.equals(this.localNick)) + return; + + boolean online = false; + if(isConnected()){ + online = isNickOnline(localNick); + if(online) + goOffline(); + } + + this.localNick = newNick; + if(online) + goOnline(); + } + + public void goOnline(){ + goOnline(28411); + } + + public void goOnline(int port){ + assert localNick != null; + assert isConnected(); + String q = "INSERT INTO user (nick, ip, online, port) values ('"+localNick+"', SUBSTRING_INDEX(USER(),'@',-1), 1,'"+port+"');"; + try { + st.executeUpdate(q); + } catch (SQLException e) { + boolean nick_collision=true; + try{ + if(getIpForNick(localNick)!=null){ // if nick collision + q = "UPDATE user set ip=SUBSTRING_INDEX(USER(),'@',-1), online=1, port="+port+" WHERE nick='"+localNick+"';"; + nick_collision = true; + } + else{ // if address collision + q = "UPDATE user set nick='"+localNick+"', online=1 WHERE ip=SUBSTRING_INDEX(USER(),'@',-1) AND port="+port+";"; + nick_collision = false; + } + st.executeUpdate(q); + }catch(SQLException e2){ + try { + if(nick_collision) + st.execute("DELETE FROM user WHERE ip=SUBSTRING_INDEX(USER(),'@',-1) AND port="+port+";"); + else + st.execute("DELETE FROM user WHERE nick='"+localNick+"';"); + st.execute(q); + } catch (SQLException e3) { + e2.printStackTrace(); + }// catch3 + }// catch2 + }// catch + }// goOnline + + public void goOffline(){ + assert localNick != null; + assert isConnected(); + try { + st.execute("INSERT INTO user (nick, ip, online) values ('"+localNick+"', SUBSTRING_INDEX(USER(),'@',-1), 0) ON DUPLICATE KEY UPDATE ip=VALUES(ip), online=VALUES(online);"); + } catch (SQLException e) { + e.printStackTrace(); + }// catch + } + + public String getIpForNick(String nick){ + assert isConnected(); + assert nick!=null; + nick = safe(nick); + ResultSet rs; + try { + rs = st.executeQuery("SELECT ip FROM user WHERE nick='"+nick+"'"); + if(!rs.next()) + return null; + return rs.getString(1); + } catch (SQLException e) { + e.printStackTrace(); + }// catch + return null; + } + + public int getPortForNick(String nick){ + assert isConnected(); + assert nick!=null; + nick = safe(nick); + ResultSet rs; + try { + rs = st.executeQuery("SELECT port FROM user WHERE nick='"+nick+"'"); + if(!rs.next()) + return 0; + return rs.getInt(1); + } catch (SQLException e) { + e.printStackTrace(); + }// catch + return 0; + } + + public boolean isNickOnline(String nick){ + if(nick==null) + return false; + + assert isConnected(); + nick = safe(nick); + ResultSet rs; + try { + rs = st.executeQuery("SELECT online FROM user WHERE nick='"+nick+"'"); + if(!rs.next()) + return false; + return rs.getBoolean(1); + } catch (SQLException e) { + e.printStackTrace(); + }// catch + return false; + } + + public String[] getAllNicks(){ + assert isConnected(); + ResultSet rs; + List res = new ArrayList(); + try { + rs = st.executeQuery("SELECT nick FROM user;"); + while(rs.next()){ + String nick = rs.getString(1); + res.add(nick); + }// while + } catch (SQLException e) { + e.printStackTrace(); + }// catch + return res.toArray(new String[0]); + } + + private static String safe(String s){ + return s.replaceAll("['\";]", "").replaceAll("\\s", ""); + } + + public static void main(String[] args) { + String nick1 = "latin&кириллица"; + String nick2 = "another"; + + ServerConnection c = new ServerConnection(); + c.setServerAddress("jdbc:mysql://files.litvinov.in.ua/chatapp_server?characterEncoding=utf-8&useUnicode=true"); + c.connect(); + assert c.isConnected(); + c.setLocalNick(nick1); + System.out.println("Before: " + c.isNickOnline(nick1)); + c.goOnline(); + System.out.println("After: " + c.isNickOnline(nick1)); + c.goOffline(); + System.out.println("After offline: " + c.isNickOnline(nick1)); + + System.out.println("Another nick: " + c.isNickOnline(nick2)); + System.out.println("My ip: " + c.getIpForNick(nick1)); + System.out.println("Other ip: " + c.getIpForNick(nick2)); + + System.out.println("My port: " + c.getPortForNick(nick1)); + System.out.println("Other port: " + c.getPortForNick(nick2)); + }// main +}