From f962c66066c352c8fe2ab38ac59d9762918e2bc6 Mon Sep 17 00:00:00 2001 From: Maksim Date: Fri, 22 Mar 2019 20:05:17 +1000 Subject: [PATCH 1/4] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20=D0=BB=D0=BE=D0=B3=D0=B3=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=81=20=D0=BF=D0=BE=D0=BC=D0=BE=D1=89=D1=8C?= =?UTF-8?q?=D1=8E=20log4j2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/log4j2.xml | 23 +++ src/logging_testing_6/ChatServer.java | 130 +++++++++++++++ src/logging_testing_6/ClientHandler.java | 77 +++++++++ src/logging_testing_6/auth/AuthService.java | 6 + .../auth/AuthServiceImpl.java | 13 ++ src/logging_testing_6/dbconn/JdbcExample.java | 44 +++++ src/logging_testing_6/gui/App.java | 17 ++ src/logging_testing_6/gui/AuthException.java | 4 + src/logging_testing_6/gui/LoginDialog.java | 107 ++++++++++++ src/logging_testing_6/gui/MainWindow.java | 155 ++++++++++++++++++ src/logging_testing_6/gui/Message.java | 37 +++++ .../gui/MessageCellRenderer.java | 32 ++++ src/logging_testing_6/gui/MessageSender.java | 16 ++ src/logging_testing_6/gui/Network.java | 108 ++++++++++++ .../DialogWindow.java | 55 +++++++ .../history/HistoryKeeper.java | 84 ++++++++++ 16 files changed, 908 insertions(+) create mode 100644 resources/log4j2.xml create mode 100644 src/logging_testing_6/ChatServer.java create mode 100644 src/logging_testing_6/ClientHandler.java create mode 100644 src/logging_testing_6/auth/AuthService.java create mode 100644 src/logging_testing_6/auth/AuthServiceImpl.java create mode 100644 src/logging_testing_6/dbconn/JdbcExample.java create mode 100644 src/logging_testing_6/gui/App.java create mode 100644 src/logging_testing_6/gui/AuthException.java create mode 100644 src/logging_testing_6/gui/LoginDialog.java create mode 100644 src/logging_testing_6/gui/MainWindow.java create mode 100644 src/logging_testing_6/gui/Message.java create mode 100644 src/logging_testing_6/gui/MessageCellRenderer.java create mode 100644 src/logging_testing_6/gui/MessageSender.java create mode 100644 src/logging_testing_6/gui/Network.java create mode 100644 src/logging_testing_6/gui/elements_for_changing_name/DialogWindow.java create mode 100644 src/logging_testing_6/history/HistoryKeeper.java diff --git a/resources/log4j2.xml b/resources/log4j2.xml new file mode 100644 index 0000000..ea50218 --- /dev/null +++ b/resources/log4j2.xml @@ -0,0 +1,23 @@ + + + + logs + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/logging_testing_6/ChatServer.java b/src/logging_testing_6/ChatServer.java new file mode 100644 index 0000000..c1d203b --- /dev/null +++ b/src/logging_testing_6/ChatServer.java @@ -0,0 +1,130 @@ +package logging_testing_6; + + +import logging_testing_6.auth.AuthService; +import logging_testing_6.auth.AuthServiceImpl; +import logging_testing_6.gui.Message; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; + +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.concurrent.ExecutorService; +import java.util.concurrent.Executors; +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 = "/userdissconn"; + private static final Pattern AUTH_PATTERN = Pattern.compile("^/auth (\\w+) (\\w+)$"); + + private AuthService authService = new AuthServiceImpl(); + + private Map clientHandlerMap = Collections.synchronizedMap(new HashMap<>()); + private ExecutorService executorService; + + // private static final Logger logger = LoggerFactory.getLogger(ChatServer.class); + private static final Logger log = LogManager.getLogger(ChatServer.class); + + public static void main(String[] args) { + ChatServer chatServer = new ChatServer(); + chatServer.start(7777); + } + + public void start(int port) { + executorService = Executors.newCachedThreadPool(); + try (ServerSocket serverSocket = new ServerSocket(port)) { + log.info("Server started!"); + while (true) { + Socket socket = serverSocket.accept(); + DataInputStream inp = new DataInputStream(socket.getInputStream()); + DataOutputStream out = new DataOutputStream(socket.getOutputStream()); + log.info("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(); + + log.info("Authorization for user {} %s successful", username); + } else { + log.info("Authorization for user {} failed", username); + out.writeUTF("/auth fails"); + out.flush(); + socket.close(); + } + } else { + log.info("Incorrect authorization message {}", authMessage); + out.writeUTF("/auth fails"); + out.flush(); + socket.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } finally { +// authService.close(); + executorService.shutdown(); + } + } + + public void sendMessage(String userTo, String userFrom, String msg) throws IOException { + ClientHandler userToClientHandler = clientHandlerMap.get(userTo); + if (userToClientHandler != null) { + userToClientHandler.sendMessage(userFrom, msg); + } else { + log.debug("User {} not found. Message from {} is lost.", userTo, userFrom); + } + } + + public ExecutorService getExecutorService() { + return executorService; + } + + public void sendMessage(Message message) throws IOException { + String userTo = message.getUserTo(); + String userFrom = message.getUserFrom(); + String msg = message.getText(); + ClientHandler userToClientHandler = clientHandlerMap.get(userTo); + if (userToClientHandler != null) { + userToClientHandler.sendMessage(userFrom, msg); + } else { + log.debug("User {} not found. Message from {} is lost.", userTo, userFrom); + } + } + + public List getUserList() { + return new ArrayList<>(clientHandlerMap.keySet()); + } + + public void unsubscribeClient(ClientHandler clientHandler) { + clientHandlerMap.remove(clientHandler.getUsername()); + broadcastUserDisconnected(); + } + + public void broadcastUserConnected() { + // TODO сообщать о том, что конкретный пользователь подключился + } + + public void broadcastUserDisconnected() { + // TODO сообщать о том, что конкретный пользователь отключился + } +} diff --git a/src/logging_testing_6/ClientHandler.java b/src/logging_testing_6/ClientHandler.java new file mode 100644 index 0000000..7f466dc --- /dev/null +++ b/src/logging_testing_6/ClientHandler.java @@ -0,0 +1,77 @@ +package logging_testing_6; + +import logging_testing_6.gui.Message; +import logging_testing_6.history.HistoryKeeper; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +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 static final Logger log = LogManager.getLogger(ClientHandler.class); + + +// private final Thread handleThread; + private final DataInputStream inp; + private final DataOutputStream out; + 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.inp = new DataInputStream(socket.getInputStream()); + this.out = new DataOutputStream(socket.getOutputStream()); + + server.getExecutorService().submit(() -> { + try { + while (!Thread.currentThread().isInterrupted()) { + String msg = inp.readUTF(); + log.info("Message from user {}: {}", username, msg); + + Matcher matcher = MESSAGE_PATTERN.matcher(msg); + if (matcher.matches()) { + String userTo = matcher.group(1); + String messageText = matcher.group(2); + Message message = new Message(username, userTo, messageText); + server.sendMessage(message); + + // Добавляем сообщения в файл истории отправителя + HistoryKeeper.saveMassageToHistoryFrom(message); + // Добавляем сообщения в файл истории получателя + HistoryKeeper.saveMassageToHistoryTo(message); + } + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + log.info("Client {} disconnected", username); + try { + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + server.unsubscribeClient(ClientHandler.this); + } + }); + } + + public void sendMessage(String userTo, String msg) throws IOException { + out.writeUTF(String.format(MESSAGE_SEND_PATTERN, userTo, msg)); + } + + public String getUsername() { + return username; + } +} diff --git a/src/logging_testing_6/auth/AuthService.java b/src/logging_testing_6/auth/AuthService.java new file mode 100644 index 0000000..8a47ee4 --- /dev/null +++ b/src/logging_testing_6/auth/AuthService.java @@ -0,0 +1,6 @@ +package logging_testing_6.auth; + +public interface AuthService { + + boolean authUser(String username, String password); +} diff --git a/src/logging_testing_6/auth/AuthServiceImpl.java b/src/logging_testing_6/auth/AuthServiceImpl.java new file mode 100644 index 0000000..03794ba --- /dev/null +++ b/src/logging_testing_6/auth/AuthServiceImpl.java @@ -0,0 +1,13 @@ +package logging_testing_6.auth; + +import logging_testing_6.dbconn.JdbcExample; + +public class AuthServiceImpl implements AuthService { + + @Override + public boolean authUser(String username, String password) { + String pwd = JdbcExample.readFromDB(username); + + return pwd != null && pwd.equals(password); + } +} diff --git a/src/logging_testing_6/dbconn/JdbcExample.java b/src/logging_testing_6/dbconn/JdbcExample.java new file mode 100644 index 0000000..05268f9 --- /dev/null +++ b/src/logging_testing_6/dbconn/JdbcExample.java @@ -0,0 +1,44 @@ +package logging_testing_6.dbconn; + +import java.sql.*; + +public class JdbcExample { + private static final String URL = "jdbc:sqlite:database.db"; + + static { + try { + Class.forName("org.sqlite.JDBC"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + public static String readFromDB(String clientName) { + String password = null; + try (Connection connection = DriverManager.getConnection(URL)) { + PreparedStatement preparedStatement = connection.prepareStatement("SELECT u.name, p.password FROM users u INNER JOIN passwords p on u.id = p.id WHERE u.name = ?"); + preparedStatement.setString(1, clientName); + ResultSet resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { +// String name = resultSet.getString("name"); + password = resultSet.getString("password"); + } + } catch (SQLException e) { + e.printStackTrace(); + } + System.out.println("returned password: " + password); + return password; + } + + public static void changeNick(String oldName, String newName) { + try (Connection connection = DriverManager.getConnection(URL)) { + PreparedStatement preparedStatement = connection.prepareStatement("UPDATE users SET name = ? WHERE name = ?;"); + preparedStatement.setString(1, newName); + preparedStatement.setString(2, oldName); + preparedStatement.executeUpdate(); + System.out.println("Name " + oldName + " changed to: " + newName); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/src/logging_testing_6/gui/App.java b/src/logging_testing_6/gui/App.java new file mode 100644 index 0000000..2027773 --- /dev/null +++ b/src/logging_testing_6/gui/App.java @@ -0,0 +1,17 @@ +package logging_testing_6.gui; + +import javax.swing.*; + +public class App { + + private static MainWindow mainWindow; + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + mainWindow = new MainWindow(); + } + }); + } +} diff --git a/src/logging_testing_6/gui/AuthException.java b/src/logging_testing_6/gui/AuthException.java new file mode 100644 index 0000000..974d389 --- /dev/null +++ b/src/logging_testing_6/gui/AuthException.java @@ -0,0 +1,4 @@ +package logging_testing_6.gui; + +public class AuthException extends RuntimeException { +} diff --git a/src/logging_testing_6/gui/LoginDialog.java b/src/logging_testing_6/gui/LoginDialog.java new file mode 100644 index 0000000..1f107ce --- /dev/null +++ b/src/logging_testing_6/gui/LoginDialog.java @@ -0,0 +1,107 @@ +package logging_testing_6.gui; + +import javax.swing.*; +import javax.swing.border.LineBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; + + +public class LoginDialog extends JDialog { + + private JTextField tfUsername; + private JPasswordField pfPassword; + private JLabel lbUsername; + private JLabel lbPassword; + private JButton btnLogin; + private JButton btnCancel; + + private final Network network; + + private boolean connected; + + public LoginDialog(Frame parent, Network network) { + super(parent, "Login", true); + + this.network = network; + this.connected = false; + + JPanel panel = new JPanel(new GridBagLayout()); + GridBagConstraints cs = new GridBagConstraints(); + + cs.fill = GridBagConstraints.HORIZONTAL; + + lbUsername = new JLabel("Username: "); + cs.gridx = 0; + cs.gridy = 0; + cs.gridwidth = 1; + panel.add(lbUsername, cs); + + tfUsername = new JTextField(20); + cs.gridx = 1; + cs.gridy = 0; + cs.gridwidth = 2; + panel.add(tfUsername, cs); + + lbPassword = new JLabel("Password: "); + cs.gridx = 0; + cs.gridy = 1; + cs.gridwidth = 1; + panel.add(lbPassword, cs); + + pfPassword = new JPasswordField(20); + cs.gridx = 1; + cs.gridy = 1; + cs.gridwidth = 2; + panel.add(pfPassword, cs); + panel.setBorder(new LineBorder(Color.GRAY)); + + btnLogin = new JButton("Login"); + btnCancel = new JButton("Cancel"); + + JPanel bp = new JPanel(); + bp.add(btnLogin); + btnLogin.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + network.authorize(tfUsername.getText(), String.valueOf(pfPassword.getPassword())); + connected = true; + } catch (AuthException ex) { + JOptionPane.showMessageDialog(LoginDialog.this, + "Ошибка авторизации", + "Авторизация", + JOptionPane.ERROR_MESSAGE); + return; + } catch (IOException ex) { + JOptionPane.showMessageDialog(LoginDialog.this, + "Ошибка сети", + "Авторизация", + JOptionPane.ERROR_MESSAGE); + return; + } + dispose(); + } + }); + + bp.add(btnCancel); + btnCancel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + + getContentPane().add(panel, BorderLayout.CENTER); + getContentPane().add(bp, BorderLayout.PAGE_END); + + pack(); + setResizable(false); + setLocationRelativeTo(parent); + } + + public boolean isConnected() { + return connected; + } +} diff --git a/src/logging_testing_6/gui/MainWindow.java b/src/logging_testing_6/gui/MainWindow.java new file mode 100644 index 0000000..bd08833 --- /dev/null +++ b/src/logging_testing_6/gui/MainWindow.java @@ -0,0 +1,155 @@ +package logging_testing_6.gui; + +import logging_testing_6.gui.elements_for_changing_name.DialogWindow; +import logging_testing_6.history.HistoryKeeper; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.List; + +public class MainWindow extends JFrame implements MessageSender { + + private JTextField textField; + private JButton button; + private JScrollPane scrollPane; + private JList messageList; + private DefaultListModel messageListModel; + private JList userList; + private JPanel panel; + + private Network network; + + public MainWindow() { + setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + setBounds(200, 200, 500, 500); + + // Добавим контекстное меню + JPopupMenu popupMenu = createPopupMenu(); + ((JComponent) getContentPane()).setComponentPopupMenu(popupMenu); + + setLayout(new BorderLayout()); + + messageListModel = new DefaultListModel<>(); + messageList = new JList<>(messageListModel); + messageList.setCellRenderer(new MessageCellRenderer()); + + panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.add(messageList, BorderLayout.SOUTH); + panel.setBackground(messageList.getBackground()); + scrollPane = new JScrollPane(panel); + scrollPane.setInheritsPopupMenu(true); // Добавим контекстное меню + 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); + userList.setInheritsPopupMenu(true); // Добавим контекстное меню + + textField = new JTextField(); + button = new JButton("Отправить"); + button.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + String userTo = userList.getSelectedValue(); + if (userTo == null) { + JOptionPane.showMessageDialog(MainWindow.this, + "Не указан получатель", + "Отправка сообщения", + JOptionPane.ERROR_MESSAGE); + return; + } + + String text = textField.getText(); + if (text == null || text.trim().isEmpty()) { + JOptionPane.showMessageDialog(MainWindow.this, + "Нельзя отправить пустое сообщение", + "Отправка сообщения", + JOptionPane.ERROR_MESSAGE); + return; + } + + Message msg = new Message(network.getUsername(), userTo, text.trim()); + submitMessage(msg); + textField.setText(null); + textField.requestFocus(); + + network.sendMessageToUser(msg); + } + }); + + this.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent evt) { + messageList.ensureIndexIsVisible(messageListModel.size() - 1); + } + }); + + panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.add(button, BorderLayout.EAST); + panel.add(textField, 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); + + network = new Network("localhost", 7777, this); + + LoginDialog loginDialog = new LoginDialog(this, network); + loginDialog.setVisible(true); + + if (!loginDialog.isConnected()) { + System.exit(0); + } + + setTitle("Сетевой чат. Пользователь " + network.getUsername()); + + List listMessages = HistoryKeeper.getHistory(network.getUsername() + ".txt", 10); + for (Message message : listMessages) { + messageListModel.addElement(message); + } + } + + @Override + public void submitMessage(Message msg) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + messageListModel.add(messageListModel.size(), msg); + messageList.ensureIndexIsVisible(messageListModel.size() - 1); + } + }); + } + + private JPopupMenu createPopupMenu() { + JPopupMenu popupMenu = new JPopupMenu(); + JMenuItem changeNameItem = new JMenuItem("Сменить ник"); + changeNameItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + DialogWindow dialogWindow = new DialogWindow(getNetwork()); + } + }); + popupMenu.add(changeNameItem); + return popupMenu; + } + + public Network getNetwork() { + return network; + } +} diff --git a/src/logging_testing_6/gui/Message.java b/src/logging_testing_6/gui/Message.java new file mode 100644 index 0000000..aa77eb9 --- /dev/null +++ b/src/logging_testing_6/gui/Message.java @@ -0,0 +1,37 @@ +package logging_testing_6.gui; + +import java.time.LocalDate; + +public class Message { + + private String userFrom; + + private String userTo; + + private String text; + + private LocalDate date; + + public Message(String userFrom, String userTo, String text) { + this.userFrom = userFrom; + this.userTo = userTo; + this.text = text; + this.date = LocalDate.now(); + } + + public String getUserFrom() { + return userFrom; + } + + public String getUserTo() { + return userTo; + } + + public String getText() { + return text; + } + + public LocalDate getDate() { + return date; + } +} diff --git a/src/logging_testing_6/gui/MessageCellRenderer.java b/src/logging_testing_6/gui/MessageCellRenderer.java new file mode 100644 index 0000000..171be89 --- /dev/null +++ b/src/logging_testing_6/gui/MessageCellRenderer.java @@ -0,0 +1,32 @@ +package logging_testing_6.gui; + +import javax.swing.*; +import java.awt.*; + +public class MessageCellRenderer extends JPanel implements ListCellRenderer { + + private JLabel userName; + + private JLabel message; + + public MessageCellRenderer() { + super(); + setLayout(new BorderLayout()); + userName = new JLabel(); + Font f = userName.getFont(); + userName.setFont(f.deriveFont(f.getStyle() | Font.BOLD)); + message = new JLabel(); + add(userName, BorderLayout.NORTH); + add(message, BorderLayout.SOUTH); + } + + @Override + public Component getListCellRendererComponent(JList list, Message value, + int index, boolean isSelected, boolean cellHasFocus) { + setBackground(list.getBackground()); + userName.setOpaque(true); + userName.setText(value.getUserFrom()); + message.setText(value.getText()); + return this; + } +} diff --git a/src/logging_testing_6/gui/MessageSender.java b/src/logging_testing_6/gui/MessageSender.java new file mode 100644 index 0000000..4c85248 --- /dev/null +++ b/src/logging_testing_6/gui/MessageSender.java @@ -0,0 +1,16 @@ +package logging_testing_6.gui; + +/** + * Интерфейс для взаимодействия класса сети {@link Network} + * с пользовательским интерфейсом на + */ +public interface MessageSender { + + /** + * Метод вызывается классом сети при получении нового сообщения + * @param msg новое сообщение + */ + void submitMessage(Message msg); + + // TODO добавить метод для оповещения о новом пользователе +} diff --git a/src/logging_testing_6/gui/Network.java b/src/logging_testing_6/gui/Network.java new file mode 100644 index 0000000..e1f300f --- /dev/null +++ b/src/logging_testing_6/gui/Network.java @@ -0,0 +1,108 @@ +package logging_testing_6.gui; + +import java.io.Closeable; +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 Network implements Closeable { + + private static final String AUTH_PATTERN = "/auth %s %s"; + private static final String MESSAGE_SEND_PATTERN = "/w %s %s"; + private static final String USER_LIST_PATTERN = "/userlist"; + private static final Pattern MESSAGE_PATTERN = Pattern.compile("^/w (\\w+) (.+)", Pattern.MULTILINE); + + private Socket socket; + private DataOutputStream out; + private DataInputStream in; + private final MessageSender messageSender; + private final Thread receiver; + + private String username; + private final String hostName; + private final int port; + + public Network(String hostName, int port, MessageSender messageSender) { + this.hostName = hostName; + this.port = port; + this.messageSender = messageSender; + + this.receiver = createReceiverThread(); + } + + private Thread createReceiverThread() { + return new Thread(new Runnable() { + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + try { + String text = in.readUTF(); + + System.out.println("New message " + text); + Matcher matcher = MESSAGE_PATTERN.matcher(text); + if (matcher.matches()) { + Message msg = new Message(matcher.group(1), username, + matcher.group(2)); + messageSender.submitMessage(msg); + } else if (text.startsWith(USER_LIST_PATTERN)) { + // TODO обновить список подключенных пользователей + } + } catch (IOException e) { + e.printStackTrace(); + } + } + System.out.printf("Network connection is closed for user %s%n", username); + } + }); + } + + public void sendMessageToUser(Message message) { + sendMessage(String.format(MESSAGE_SEND_PATTERN, message.getUserTo(), message.getText())); + } + + private void sendMessage(String msg) { + try { + out.writeUTF(msg); + out.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void authorize(String username, String password) throws IOException { + socket = new Socket(hostName, port); + out = new DataOutputStream(socket.getOutputStream()); + in = new DataInputStream(socket.getInputStream()); + + out.writeUTF(String.format(AUTH_PATTERN, username, password)); + String response = in.readUTF(); + if (response.equals("/auth successful")) { + this.username = username; + receiver.start(); + } else { + throw new AuthException(); + } + } + + public String getUsername() { + return username; + } + + @Override + public void close() { + try { + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + receiver.interrupt(); + try { + receiver.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/src/logging_testing_6/gui/elements_for_changing_name/DialogWindow.java b/src/logging_testing_6/gui/elements_for_changing_name/DialogWindow.java new file mode 100644 index 0000000..ec076b6 --- /dev/null +++ b/src/logging_testing_6/gui/elements_for_changing_name/DialogWindow.java @@ -0,0 +1,55 @@ +package logging_testing_6.gui.elements_for_changing_name; + +import logging_testing_6.dbconn.JdbcExample; +import logging_testing_6.gui.Network; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class DialogWindow extends JFrame { + private final Network network; + + public DialogWindow(Network network) { + super("Введите новое имени пользователя"); + this.network = network; + setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + JTextField tf = new JTextField("Введите новое имя пользователя"); + + JButton bOK = new JButton("OK"); + bOK.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String currentUserName = network.getUsername(); + String newUserName = tf.getText(); + JdbcExample.changeNick(currentUserName, newUserName); + dispose(); + } + }); + + JButton bCancel = new JButton("Отмена"); + bCancel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + + JPanel textPanel = new JPanel(); + JPanel buttonPanel = new JPanel(); + buttonPanel.add(bCancel); + buttonPanel.add(bOK); + + textPanel.add(tf); + + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayout(2, 1, 5, 10)); + mainPanel.add(textPanel); + mainPanel.add(buttonPanel); + getContentPane().add(mainPanel); + pack(); + setVisible(true); + } +} diff --git a/src/logging_testing_6/history/HistoryKeeper.java b/src/logging_testing_6/history/HistoryKeeper.java new file mode 100644 index 0000000..6132712 --- /dev/null +++ b/src/logging_testing_6/history/HistoryKeeper.java @@ -0,0 +1,84 @@ +package logging_testing_6.history; + +import logging_testing_6.gui.Message; + +import java.io.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class HistoryKeeper { + private static final String HISTORY_DIR = "history"; + + public static void saveMassageToHistoryFrom(Message message) { + String userName = message.getUserFrom(); + String messageText = message.getText(); + String fileName = userName + ".txt"; + File file = new File(HISTORY_DIR, fileName); + try (BufferedWriter out = new BufferedWriter(new FileWriter(file, true)) +// BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) + ) { + String str = userName + ": " + messageText + "\r\n"; + out.write(str); + out.flush(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void saveMassageToHistoryTo(Message message) { + String userName = message.getUserTo(); + String messageText = message.getText(); + String fileName = userName + ".txt"; + File file = new File(HISTORY_DIR, fileName); + try (BufferedWriter out = new BufferedWriter(new FileWriter(file, true))) { +// String str = userName + ": " + messageText + "\r\n"; + String str = message.getUserFrom() + ": " + messageText + "\r\n"; + out.write(str); + out.flush(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static List getHistory(String fileName, int numberOfRows) { + List textMessageList = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + File file = new File(HISTORY_DIR, fileName); + try { + RandomAccessFile raf = new RandomAccessFile(file, "r"); + for (long pointer = file.length() - 1; pointer >= 0 && textMessageList.size() < numberOfRows; pointer--) { + raf.seek(pointer); + char aChar = (char) raf.read(); + if (aChar != '\n') { + sb.append(aChar); + } else if (sb.length() > 1) { + textMessageList.add(sb.reverse().toString()); + sb.delete(0, sb.length()); + } + } + if (sb.length() > 1) { + textMessageList.add(sb.reverse().toString()); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + List messageList = textMessageList.stream() + .map(record -> { + String userFrom = record.substring(0, record.indexOf(" ") - 1); + String textMessage = record.substring(record.indexOf(" ") - 1); + return new Message(userFrom, null, textMessage); + }).collect(Collectors.toList()); + + Collections.reverse(messageList); + return messageList; + } +} From b68cfc995c0c8694d9ec4ecd6c9eb8a134457644 Mon Sep 17 00:00:00 2001 From: Maksim Date: Sat, 23 Mar 2019 18:15:31 +1000 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=D1=8B?= =?UTF-8?q?=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=20=D0=B7=D0=B0=D0=B4?= =?UTF-8?q?=D0=B0=D1=87=D0=B5=201=20(=D0=BF=D0=BE=20=D0=BC=D0=B0=D1=82?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D0=B0=D0=BB=D0=B0=D0=B0=D0=BC=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=B1=D0=BE=D1=80=D0=B0=20=D0=94=D0=97)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test_ex/TestEx.java | 33 +++++++++++++++ tests/tests/TestExJU4TestCase.java | 37 +++++++++++++++++ tests/tests/TestExJU5TestCase.java | 66 ++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 src/test_ex/TestEx.java create mode 100644 tests/tests/TestExJU4TestCase.java create mode 100644 tests/tests/TestExJU5TestCase.java diff --git a/src/test_ex/TestEx.java b/src/test_ex/TestEx.java new file mode 100644 index 0000000..9bfa2eb --- /dev/null +++ b/src/test_ex/TestEx.java @@ -0,0 +1,33 @@ +package test_ex; + +import java.util.Arrays; + +public class TestEx { + + public int[] task1(int[] data) { + for (int i = data.length - 1; i >= 0; i--) { + if (data[i] == 4) { + return Arrays.copyOfRange(data, i + 1, data.length); + } + } + throw new RuntimeException("Invalid array"); + } + + /*public boolean task2(int[] data) { + boolean contains1 = false; + boolean contains2 = false; + + for (int i = 0; i < data.length; i++) { + switch (data[i]) { + case 1: + contains1 = true; + break; + case 4: + contains2 = true; + break; + default: + + } + } + }*/ +} \ No newline at end of file diff --git a/tests/tests/TestExJU4TestCase.java b/tests/tests/TestExJU4TestCase.java new file mode 100644 index 0000000..f3ecd0b --- /dev/null +++ b/tests/tests/TestExJU4TestCase.java @@ -0,0 +1,37 @@ +package tests; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import test_ex.TestEx; + +public class TestExJU4TestCase { + private TestEx dz; + + @Before + public void prepare() { + dz = new TestEx(); + } + + @Test(expected = RuntimeException.class) + public void test_task1_empty_array() { + dz.task1(new int[0]); + } + + @Test(expected = RuntimeException.class) + public void test_task1_without_4() { + dz.task1(new int[]{1, 2, 3}); + } + + @Test + public void test_task1_where_4_is_not_last() { + int[] data = {1, 2, 3, 4, 5, 6, 7}; + Assert.assertArrayEquals(new int[]{5, 6, 7,}, dz.task1(data)); + } + + @Test + public void test_task1_with_some_4() { + int[] data = {1, 4, 3, 4, 5, 6, 4}; + Assert.assertArrayEquals(new int[]{}, dz.task1(data)); + } +} \ No newline at end of file diff --git a/tests/tests/TestExJU5TestCase.java b/tests/tests/TestExJU5TestCase.java new file mode 100644 index 0000000..4735507 --- /dev/null +++ b/tests/tests/TestExJU5TestCase.java @@ -0,0 +1,66 @@ +package tests; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import test_ex.TestEx; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +class TestExJU5TestCase { + private TestEx dz; + + @BeforeEach + public void prepare() { + dz = new TestEx(); + } + + @Test + void test_task1_empty_array() { + Assertions.assertThrows(RuntimeException.class, () -> { + dz.task1(new int[0]); + }); + } + + @Test + public void test_tsak1_without_4() { + Assertions.assertThrows(RuntimeException.class, () -> dz.task1(new int[]{1, 2, 3})); + } + + @Test + public void test_task1_where_4_is_not_last() { + int[] data = {1, 2, 3, 4, 5, 6, 7}; + Assertions.assertArrayEquals(new int[]{5, 6, 7}, dz.task1(data)); + } + + @Test + public void test_task1_whith_some_4() { + int[] data = {1, 4, 3, 4, 5, 6, 4}; + Assertions.assertArrayEquals(new int[]{}, dz.task1(data)); + } + + @ParameterizedTest + @MethodSource("params") + public void test_task1_whith_params(int[] data, int[] result) { + Assertions.assertArrayEquals(result, dz.task1(data)); + } + + private static Stream params() { + return Stream.of( + Arguments.of( + new int[]{1, 3, 4}, + new int[]{}), + Arguments.of( + new int[]{1, 4, 3, 4}, + new int[]{}), + Arguments.of( + new int[]{1, 4, 3, 5}, + new int[]{3, 5}) + ); + } +} \ No newline at end of file From 515c1352073f19c0cddded6b819653a4c5ee612b Mon Sep 17 00:00:00 2001 From: Maksim Date: Sat, 23 Mar 2019 19:34:41 +1000 Subject: [PATCH 3/4] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=D1=8B?= =?UTF-8?q?=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=20=D0=B7=D0=B0=D0=B4?= =?UTF-8?q?=D0=B0=D1=87=D0=B5=202=20(=D0=BF=D0=BE=20=D0=BC=D0=B0=D1=82?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D0=B0=D0=BB=D0=B0=D0=B0=D0=BC=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=B1=D0=BE=D1=80=D0=B0=20=D0=94=D0=97)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test_ex/TestEx.java | 9 +-- src/test_ex/calculator/Calculator.java | 36 ++++++++++ src/test_ex/calculator/ICalc.java | 9 +++ src/test_ex/calculator/NumberProvader.java | 5 ++ .../calculator/NumberProviderImpl.java | 13 ++++ tests/test_ex/calculator/CalculatorTest4.java | 69 +++++++++++++++++++ tests/tests/Task2TestJU4.java | 47 +++++++++++++ 7 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 src/test_ex/calculator/Calculator.java create mode 100644 src/test_ex/calculator/ICalc.java create mode 100644 src/test_ex/calculator/NumberProvader.java create mode 100644 src/test_ex/calculator/NumberProviderImpl.java create mode 100644 tests/test_ex/calculator/CalculatorTest4.java create mode 100644 tests/tests/Task2TestJU4.java diff --git a/src/test_ex/TestEx.java b/src/test_ex/TestEx.java index 9bfa2eb..0268ca5 100644 --- a/src/test_ex/TestEx.java +++ b/src/test_ex/TestEx.java @@ -13,7 +13,7 @@ public int[] task1(int[] data) { throw new RuntimeException("Invalid array"); } - /*public boolean task2(int[] data) { + public boolean task2(int[] data) { boolean contains1 = false; boolean contains2 = false; @@ -25,9 +25,10 @@ public int[] task1(int[] data) { case 4: contains2 = true; break; - default: - + default: + return false; } } - }*/ + return contains1 && contains2; + } } \ No newline at end of file diff --git a/src/test_ex/calculator/Calculator.java b/src/test_ex/calculator/Calculator.java new file mode 100644 index 0000000..a5e344e --- /dev/null +++ b/src/test_ex/calculator/Calculator.java @@ -0,0 +1,36 @@ +package test_ex.calculator; + +public class Calculator implements ICalc { + NumberProvader numberProvader; + + public Calculator(NumberProvader numberProvader) { + this.numberProvader = numberProvader; + } + + @Override + public int add(int a, int b) { + return a + b; + } + + @Override + public int sub(int a, int b) { + return a - b; + } + + @Override + public int mul(int a, int b) { + return a * b; + } + + @Override + public int div(int a, int b) { + return a / b; + } + + @Override + public int sumFromProvider() { + int a = numberProvader.getNumber(); + int b = numberProvader.getNumber(); + return add(a, b); + } +} diff --git a/src/test_ex/calculator/ICalc.java b/src/test_ex/calculator/ICalc.java new file mode 100644 index 0000000..f678a1f --- /dev/null +++ b/src/test_ex/calculator/ICalc.java @@ -0,0 +1,9 @@ +package test_ex.calculator; + +public interface ICalc { + int add(int a, int b); + int sub(int a, int b); + int mul(int a, int b); + int div(int a, int b); + int sumFromProvider(); +} diff --git a/src/test_ex/calculator/NumberProvader.java b/src/test_ex/calculator/NumberProvader.java new file mode 100644 index 0000000..b6c4103 --- /dev/null +++ b/src/test_ex/calculator/NumberProvader.java @@ -0,0 +1,5 @@ +package test_ex.calculator; + +public interface NumberProvader { + int getNumber(); +} diff --git a/src/test_ex/calculator/NumberProviderImpl.java b/src/test_ex/calculator/NumberProviderImpl.java new file mode 100644 index 0000000..9be7720 --- /dev/null +++ b/src/test_ex/calculator/NumberProviderImpl.java @@ -0,0 +1,13 @@ +package test_ex.calculator; + +import java.util.Scanner; + +public class NumberProviderImpl implements NumberProvader{ + + @Override + public int getNumber() { + try (Scanner scanner = new Scanner(System.in)){ + return scanner.nextInt(); + } + } +} diff --git a/tests/test_ex/calculator/CalculatorTest4.java b/tests/test_ex/calculator/CalculatorTest4.java new file mode 100644 index 0000000..c1f92b9 --- /dev/null +++ b/tests/test_ex/calculator/CalculatorTest4.java @@ -0,0 +1,69 @@ +package test_ex.calculator; + +import org.hamcrest.core.Is; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +public class CalculatorTest4 { + private ICalc calc; + private NumberProvader numberProvader; + + @Before + public void setUp() { + numberProvader = Mockito.mock(NumberProvader.class); + calc = new Calculator(numberProvader); + } + + @After + public void tearDown() { + calc = null; + } + + @Test + public void test_sum() { + int result = calc.add(2, 2); + Assert.assertEquals(4, result); + } + + @Test + public void test_sum1() { + int result = calc.add(5, 10); + Assert.assertEquals(15, result); + } + + @Test + public void test_sub() { + Assert.assertThat(calc.sub(5, 12), Is.is(-7)); + } + + @Test + public void test_mul() { + Assert.assertThat(calc.mul(2, 3), Is.is(6)); + } + + @Test(timeout = 100L) + public void test_div() { + Assert.assertThat(calc.div(6, 3), Is.is(2)); + } + + @Test + public void test_div1() { + Assert.assertThat(calc.div(0, 3), Is.is(0)); + } + + @Test(expected = ArithmeticException.class) + public void test_div2() { + Assert.assertThat(calc.div(3, 0), Is.is(0)); + } + + @Test + public void testMock() { + Mockito.when(numberProvader.getNumber()) + .thenReturn(2, 6); + int result = calc.sumFromProvider(); + Assert.assertEquals(8, result); + } +} \ No newline at end of file diff --git a/tests/tests/Task2TestJU4.java b/tests/tests/Task2TestJU4.java new file mode 100644 index 0000000..a93b1a7 --- /dev/null +++ b/tests/tests/Task2TestJU4.java @@ -0,0 +1,47 @@ +package tests; + +import org.hamcrest.core.Is; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import test_ex.TestEx; + +public class Task2TestJU4 { + private TestEx dz; + + @Before + public void prepare() { + dz = new TestEx(); + } + + @Test + public void test_task2_empty_array() { + Assert.assertThat(dz.task2(new int[]{}), Is.is(false)); + } + + @Test + public void test_task2_only_1_and_4() { + Assert.assertThat(dz.task2(new int[]{1, 4, 4, 1}), Is.is(true)); + } + + @Test + public void test_task2_1_and_4_and_others() { + Assert.assertThat(dz.task2(new int[]{1, 4, 3, 1}), Is.is(false)); + } + + @Test + public void test_task2_without_1_and_4() { + Assert.assertThat(dz.task2(new int[]{2, 3}), Is.is(false)); + } + + @Test + public void test_task2_only_1() { + Assert.assertThat(dz.task2(new int[]{1, 1, 1}), Is.is(false)); + } + + @Test + public void test_task2_only_4() { +// Assert.assertThat(dz.task2(new int[]{4, 4, 4}), Is.is(false)); + Assert.assertFalse(String.valueOf(dz.task2(new int[]{4, 4, 4})), false); + } +} From 35f055d9372926b4b1a3d2de18ab40a379c60c13 Mon Sep 17 00:00:00 2001 From: mskmrv Date: Mon, 25 Mar 2019 16:52:07 +1000 Subject: [PATCH 4/4] =?UTF-8?q?=D0=A1=D0=BD=D0=B0=D1=87=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=20=D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D1=8F=D0=B5=D1=82=D1=81?= =?UTF-8?q?=D1=8F=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20=D1=81=20=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D0=BE=D1=82=D0=B0=D1=86=D0=B8=D0=B5=D0=B9=20@BeforeSuite?= =?UTF-8?q?,=20=D0=B7=D0=B0=D1=82=D0=B5=D0=BC=20=D0=B2=D1=8B=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D0=BD=D1=8F=D1=8E=D1=82=D1=81=D1=8F=20=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D0=BE=D0=B4=D1=8B=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D0=BA=D0=B0=D0=BA=20@Test,=20=D0=B7=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BC=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20=D1=81=20?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D0=BE=D1=82=D0=B0=D1=86=D0=B8=D0=B5=D0=B9=20?= =?UTF-8?q?@AfterSuite.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lesson7/TestEx.java | 34 +++++ .../classes_for_tests/TestExJU4TestCase.java | 41 ++++++ src/lesson7/test_framework/TestManager.java | 138 ++++++++++++++++++ .../my_annotations/AfterSuite.java | 11 ++ .../my_annotations/BeforeSuite.java | 11 ++ .../test_framework/my_annotations/Test.java | 12 ++ 6 files changed, 247 insertions(+) create mode 100644 src/lesson7/TestEx.java create mode 100644 src/lesson7/classes_for_tests/TestExJU4TestCase.java create mode 100644 src/lesson7/test_framework/TestManager.java create mode 100644 src/lesson7/test_framework/my_annotations/AfterSuite.java create mode 100644 src/lesson7/test_framework/my_annotations/BeforeSuite.java create mode 100644 src/lesson7/test_framework/my_annotations/Test.java diff --git a/src/lesson7/TestEx.java b/src/lesson7/TestEx.java new file mode 100644 index 0000000..ba4eb30 --- /dev/null +++ b/src/lesson7/TestEx.java @@ -0,0 +1,34 @@ +package lesson7; + +import java.util.Arrays; + +public class TestEx { + + public int[] task1(int[] data) { + for (int i = data.length - 1; i >= 0; i--) { + if (data[i] == 4) { + return Arrays.copyOfRange(data, i + 1, data.length); + } + } + throw new RuntimeException("Invalid array"); + } + + public boolean task2(int[] data) { + boolean contains1 = false; + boolean contains2 = false; + + for (int i = 0; i < data.length; i++) { + switch (data[i]) { + case 1: + contains1 = true; + break; + case 4: + contains2 = true; + break; + default: + return false; + } + } + return contains1 && contains2; + } +} \ No newline at end of file diff --git a/src/lesson7/classes_for_tests/TestExJU4TestCase.java b/src/lesson7/classes_for_tests/TestExJU4TestCase.java new file mode 100644 index 0000000..a3db4f0 --- /dev/null +++ b/src/lesson7/classes_for_tests/TestExJU4TestCase.java @@ -0,0 +1,41 @@ +package lesson7.classes_for_tests; + +import lesson7.test_framework.my_annotations.AfterSuite; +import lesson7.test_framework.my_annotations.BeforeSuite; +import lesson7.test_framework.my_annotations.Test; +import test_ex.TestEx; + +public class TestExJU4TestCase { + private TestEx dz; + + @BeforeSuite + public void prepare() { + dz = new TestEx(); + System.out.println("Выполняется метод @BeforeSuite prepare()"); + } + + @AfterSuite + public void finish() { + dz = null; + System.out.println("Выполняется метод @AfterSuite finish()"); + } + + /*@BeforeSuite // Получим RuntimeException + public void prepare2() { + dz = new TestEx(); + }*/ + + @Test + public void test_task1_where_4_is_not_last() { +// int[] data = {1, 2, 3, 4, 5, 6, 7}; +// Assert.assertArrayEquals(new int[]{5, 6, 7,}, dz.task1(data)); + System.out.println("Что-то выполняется в тестовом методе test_task1_where_4_is_not_last()"); + } + + @Test + public void test_task1_with_some_4() { +// int[] data = {1, 4, 3, 4, 5, 6, 4}; +// Assert.assertArrayEquals(new int[]{}, dz.task1(data)); + System.out.println("Что-то выполняется в тестовом методе test_task1_with_some_4()"); + } +} \ No newline at end of file diff --git a/src/lesson7/test_framework/TestManager.java b/src/lesson7/test_framework/TestManager.java new file mode 100644 index 0000000..df0440b --- /dev/null +++ b/src/lesson7/test_framework/TestManager.java @@ -0,0 +1,138 @@ +package lesson7.test_framework; + +import lesson7.TestEx; +import lesson7.classes_for_tests.TestExJU4TestCase; +import lesson7.test_framework.my_annotations.AfterSuite; +import lesson7.test_framework.my_annotations.BeforeSuite; +import lesson7.test_framework.my_annotations.Test; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class TestManager { + public static void main(String[] args) { + Class clazz = TestExJU4TestCase.class; + start(clazz); + } + + public static void start(Class clazz) { + doIt(clazz); + } + + public static void start(String className) { + Class clazz = null; + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + doIt(clazz); + } + + private static void doIt(Class clazz) { + Method[] methods = clazz.getDeclaredMethods(); + checkAnnotations(methods); + Annotation[] annotations = clazz.getAnnotations(); + for (Annotation annotation : annotations) { + System.out.println(annotation); + } + + startMethodWithBeforeSuiteAnnotation(clazz, methods); + startMethodWithTestAnnotation(clazz, methods); + startMethodWithAfterSuiteAnnotation(clazz, methods); + } + + private static void checkAnnotations(Method[] methods) { + int beforeCount = 0; + int afterCount = 0; + for (Method method : methods) { +// BeforeSuite annotation = method.getAnnotation(BeforeSuite.class); + Annotation[] annotations = method.getAnnotations(); + for (Annotation annotation : annotations) { +// System.out.println("method " + method + " annotation: " + annotation); + if (annotation instanceof BeforeSuite) { + beforeCount++; + } + if (annotation instanceof AfterSuite) { + afterCount++; + } + } + if (beforeCount > 1 || afterCount > 1) { + throw new RuntimeException(); + } + } + } + + private static void startMethodWithAfterSuiteAnnotation(Class clazz, Method[] methods) { + + + for (Method method : methods) { + AfterSuite asAnnotaion = method.getAnnotation(AfterSuite.class); + if (asAnnotaion != null) { + try { +// Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); + Constructor defaultConstructor = clazz.getDeclaredConstructor(); + TestExJU4TestCase testClass = defaultConstructor.newInstance(); + method.invoke(testClass); +// method.invoke(clazz.newInstance()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } + } + + private static void startMethodWithTestAnnotation(Class clazz, Method[] methods) { + for (Method method : methods) { + Test testAnnotaion = method.getAnnotation(Test.class); + if (testAnnotaion != null) { + try { +// Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); + Constructor defaultConstructor = clazz.getDeclaredConstructor(); + TestExJU4TestCase testClass = defaultConstructor.newInstance(); + method.invoke(testClass); +// method.invoke(clazz.newInstance()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } + } + + private static void startMethodWithBeforeSuiteAnnotation(Class clazz, Method[] methods) { + for (Method method : methods) { + BeforeSuite bsAnnotaion = method.getAnnotation(BeforeSuite.class); + if (bsAnnotaion != null) { + try { +// Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); + Constructor defaultConstructor = clazz.getDeclaredConstructor(); + TestExJU4TestCase testClass = defaultConstructor.newInstance(); + method.invoke(testClass); +// method.invoke(clazz.newInstance()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/src/lesson7/test_framework/my_annotations/AfterSuite.java b/src/lesson7/test_framework/my_annotations/AfterSuite.java new file mode 100644 index 0000000..738c785 --- /dev/null +++ b/src/lesson7/test_framework/my_annotations/AfterSuite.java @@ -0,0 +1,11 @@ +package lesson7.test_framework.my_annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface AfterSuite { +} diff --git a/src/lesson7/test_framework/my_annotations/BeforeSuite.java b/src/lesson7/test_framework/my_annotations/BeforeSuite.java new file mode 100644 index 0000000..f2f27de --- /dev/null +++ b/src/lesson7/test_framework/my_annotations/BeforeSuite.java @@ -0,0 +1,11 @@ +package lesson7.test_framework.my_annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface BeforeSuite { +} diff --git a/src/lesson7/test_framework/my_annotations/Test.java b/src/lesson7/test_framework/my_annotations/Test.java new file mode 100644 index 0000000..f7fb63b --- /dev/null +++ b/src/lesson7/test_framework/my_annotations/Test.java @@ -0,0 +1,12 @@ +package lesson7.test_framework.my_annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Test { + +}