Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.*;
import java.io.IOException;

public class ChatWindow extends JFrame implements MessageSender {
public class ChatWindow extends JFrame implements MessageSender{
private final DefaultListModel<Message> listModel;
private JList<Message> list;
private JScrollPane scrollPane;
Expand Down Expand Up @@ -85,6 +82,7 @@ public void keyPressed(KeyEvent e) {
System.exit(-1);
}


setVisible(true);
textField.requestFocus();
}
Expand Down
16 changes: 16 additions & 0 deletions src/ru/geekbrains/classes/lesson7/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.geekbrains.classes.lesson7;

import javax.swing.*;

public class App {
private static ChatWindow chatWindow;

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
chatWindow = new ChatWindow();
}
});
}
}
95 changes: 95 additions & 0 deletions src/ru/geekbrains/classes/lesson7/ChatServer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package ru.geekbrains.classes.lesson7;

import ru.geekbrains.classes.lesson7.auth.AuthService;
import ru.geekbrains.classes.lesson7.auth.AuthServiceImpl;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ChatServer {
private static final String USER_CONNECTED_PATTERN = "/userconn";
private static final String USER_DISCONN_PATTERN = "/userdisconn";
private static final Pattern AUTH_PATTERN = Pattern.compile("^/auth (\\w+) (\\w+)$");

private AuthService authService = new AuthServiceImpl();
private Map<String, ClientHandler> clientHandlerMap = Collections.synchronizedMap(new HashMap<>());

public static void main(String[] args) {
ChatServer chatServer = new ChatServer();
chatServer.start(7777);
}

public void start(int port) {
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server started!");
while (true) {
Socket socket = serverSocket.accept();
DataInputStream inp = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
System.out.println("New client connected!");

try {
String authMessage = inp.readUTF();
Matcher matcher = AUTH_PATTERN.matcher(authMessage);
if (matcher.matches()) {
String username = matcher.group(1);
String password = matcher.group(2);
if (authService.authUser(username, password)) {
clientHandlerMap.put(username, new ClientHandler(username, socket, this));
out.writeUTF("/auth successful");
out.flush();
broadcastUserConnected();
System.out.printf("Authorization for user %s successful%n", username);
} else {
System.out.printf("Authorization for user %s failed%n", username);
out.writeUTF("/auth fails");
out.flush();
socket.close();
}
} else {
System.out.printf("Incorrect authorization message %s%n", authMessage);
out.writeUTF("/auth fails");
out.flush();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}

public void sendMessage(String userTo, String userFrom, String msg) {
ClientHandler userToClientHandler = clientHandlerMap.get(userTo);
if (userToClientHandler != null) {
userToClientHandler.sendMessage(userFrom, msg);
} else {
System.out.printf("User %s not found. Message from %s is lost.%n", userTo, userFrom);
}
}

public List<String> getUserList() {
return new ArrayList<>(clientHandlerMap.keySet());
}

public void unsubscribeClient(ClientHandler clientHandler) {
clientHandlerMap.remove(clientHandler.getUsername());
broadcastUserDisconnected();
}

public void broadcastUserConnected() {
// TODO сообщать о том, что конкретный пользователь подключился
}

public void broadcastUserDisconnected() {
// TODO сообщать о том, что конкретный пользователь отключился
}
}
166 changes: 166 additions & 0 deletions src/ru/geekbrains/classes/lesson7/ChatWindow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package ru.geekbrains.classes.lesson7;

import ru.geekbrains.classes.lesson7.auth.LoginDialog;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;

public class ChatWindow extends JFrame implements MessageSender {
private JTextField textField;
private JButton button;
private JScrollPane scrollPane;
private JList<Message> messageList;
private DefaultListModel<Message> messageListModel;
private JList<String> userList;
private JPanel panel;

private Network network;

public ChatWindow() {
super("Чат");
initWindow();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

messageListModel = new DefaultListModel<>();
messageList = new JList<>(messageListModel);
messageList.setCellRenderer(new MessageCellRenderer());
messageList.setBorder(new TitledBorder("Сообщения"));
scrollPane = new JScrollPane(messageList);

panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(messageList, BorderLayout.SOUTH);
panel.setBackground(messageList.getBackground());
panel.add(scrollPane, BorderLayout.CENTER);

userList = new JList<>();
// TODO добавить класс Model для userList по аналогии с messageListModel
userList.setListData(new String[]{"ivan", "petr", "julia"});
userList.setPreferredSize(new Dimension(100, 0));
add(userList, BorderLayout.WEST);

textField = new JTextField();
textField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
String userTo = userList.getSelectedValue();
String text = textField.getText();
Message msg = new Message(network.getUsername(), userTo, text.trim());
submitMessage(msg);
textField.setText("");
}
}
});

button = new JButton("Отправить");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String userTo = userList.getSelectedValue();
if (userTo == null) {
JOptionPane.showMessageDialog(ChatWindow.this,
"Не указан получатель",
"Отправка сообщения",
JOptionPane.ERROR_MESSAGE);
return;
}
String text = textField.getText();
if (text == null || text.trim().isEmpty()) {
JOptionPane.showMessageDialog(ChatWindow.this,
"Нельзя отправить пустое вообщение",
"Отправка сообщения",
JOptionPane.ERROR_MESSAGE);
return;
}
Message msg = new Message(network.getUsername(), userTo, text.trim());
submitMessage(msg);
textField.setText("");
textField.requestFocus();
}
});
button.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
String userTo = userList.getSelectedValue();
String text = textField.getText();
if (text == null || text.trim().isEmpty()) {
JOptionPane.showMessageDialog(ChatWindow.this,
"Нельзя отправить пустое вообщение",
"Отправка сообщения",
JOptionPane.ERROR_MESSAGE);
return;
}
Message msg = new Message(network.getUsername(), userTo, text.trim());
submitMessage(msg);
textField.setText("");
textField.requestFocus();
network.sendMessageToUser(msg);
}
}
});

Box row = Box.createHorizontalBox();
row.add(Box.createHorizontalGlue());
row.add(textField);
row.add(Box.createHorizontalGlue());
row.add(button);
row.add(Box.createHorizontalGlue());

panel.add(row);

add(scrollPane, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);

addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if (network != null) {
network.close();
}
super.windowClosing(e);
}
});

setVisible(true);
textField.requestFocus();

try {
network = new Network("localhost", 7777, this);
} catch (IOException e) {
e.printStackTrace();
}

LoginDialog loginDialog = new LoginDialog(this, network);
loginDialog.setVisible(true);

if (!loginDialog.isConnected()) {
System.exit(0);
}
}

@Override
public void submitMessage(Message msg) {
messageListModel.add(messageListModel.size(), msg);
messageList.ensureIndexIsVisible(messageListModel.size() - 1);
}

private void initWindow() {
// JFrame.setDefaultLookAndFeelDecorated(true);
int height = (int) getDimension().getHeight();
int width = (int) getDimension().getWidth();
// setSize(width / 2, height / 2);
setSize(350, 500);
setLocation(width / 2 - getWidth() / 2, height / 2 - getHeight() / 2);
}

private Dimension getDimension() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension dimension = new Dimension(toolkit.getScreenSize());
return dimension;
}
}
70 changes: 70 additions & 0 deletions src/ru/geekbrains/classes/lesson7/ClientHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package ru.geekbrains.classes.lesson7;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ClientHandler {
private static final Pattern MESSAGE_PATTERN = Pattern.compile("^/w (\\w+) (.+)", Pattern.MULTILINE);
private static final String MESSAGE_SEND_PATTERN = "/w %s %s";

private final Thread handleThread;
private final DataInputStream inputStream;
private final DataOutputStream outputStream;
private final ChatServer server;
private final String username;
private final Socket socket;

public ClientHandler(String username, Socket socket, ChatServer server) throws IOException {
this.username = username;
this.socket = socket;
this.server = server;
this.inputStream = new DataInputStream(socket.getInputStream());
this.outputStream = new DataOutputStream(socket.getOutputStream());

this.handleThread = new Thread(new Runnable() {
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
String msg = inputStream.readUTF();
System.out.printf("Message from user %s: %s%n", username, msg);

Matcher matcher = MESSAGE_PATTERN.matcher(msg);
if (matcher.matches()) {
String userTo = matcher.group(1);
String message = matcher.group(2);
server.sendMessage(userTo, username, message);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.printf("Client %s disconnected%n", username);
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
server.unsubscribeClient(ClientHandler.this);
}
}
});
handleThread.start();
}

public void sendMessage(String userTo, String message){
try {
outputStream.writeUTF(String.format(MESSAGE_SEND_PATTERN, userTo, message));
} catch (IOException e) {
e.printStackTrace();
}
}

public String getUsername() {
return username;
}
}
Loading