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
+}