Change userId base session to dependent

This commit is contained in:
lethanhdat committed 2024-12-30 16:20:45 -06:00
1 parent 645c6ed70f
commit 97769cf0a2
36 files changed
+1377 -144

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/libs/libs.iml" filepath="$PROJECT_DIR$/libs/libs.iml" />
</modules>
</component>
</project>
View File
Whitespace-only changes.
+5
View File
@@ -99,5 +99,10 @@
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.47.1.0</version>
</dependency>
</dependencies>
</project>
BIN
View File
Binary file not shown.
@@ -1,5 +1,6 @@
package BsK.client.network.handler;
import BsK.client.ui.handler.UIHandler;
import BsK.common.packet.Packet;
import BsK.common.packet.PacketSerializer;
@@ -14,35 +15,84 @@ import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Text;
@Slf4j
public class ClientHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
public static ChannelHandlerContext ctx;
public static TextWebSocketFrame frame;
public static final ClientHandler INSTANCE = new ClientHandler();
private static final Map<Class<?>, List<ResponseListener<?>>> listeners = new HashMap<>();
public static <T> void addResponseListener(Class<T> responseType, ResponseListener<T> listener) {
listeners.computeIfAbsent(responseType, k -> new ArrayList<>()).add(listener);
}
public static <T> void removeResponseListener(Class<T> responseType, ResponseListener<T> listener) {
var listenerList = listeners.get(responseType);
if (listenerList != null) {
listenerList.remove(listener);
}
}
// @Override
// protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
// log.debug("Received message: {}", frame.text());
// var packet = PacketSerializer.GSON.fromJson(frame.text(), Packet.class);
// switch (packet) {
// case HandshakeCompleteResponse handshakeCompleteResponse -> {
// log.info("Handshake complete");
// this.ctx = ctx;
// this.frame = frame;
// }
// case ErrorResponse response -> {
// log.error("Received error response: {}", response.getError());
// switch (response.getError()) {
// case USER_ALREADY_EXISTS -> log.error("User already exists");
// default -> log.error("Received error response: {}", response.getError());
// }
// }
// case null, default -> log.warn("Unknown message: {}", frame.text());
// }
// }
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
log.debug("Received message: {}", frame.text());
var packet = PacketSerializer.GSON.fromJson(frame.text(), Packet.class);
switch (packet) {
case HandshakeCompleteResponse handshakeCompleteResponse -> {
if (packet != null) {
// Handle HandshakeCompleteResponse to initialize ctx and frame
if (packet instanceof HandshakeCompleteResponse handshakeResponse) {
log.info("Handshake complete");
this.ctx = ctx;
// var login = new LoginRequest("user", "user");
// NetworkUtil.sendPacket(ctx.channel(), login);
ClientHandler.ctx = ctx;
ClientHandler.frame = frame;
return; // No further processing needed for handshake response
}
case ErrorResponse response -> {
log.error("Received error response: {}", response.getError());
switch (response.getError()) {
case USER_ALREADY_EXISTS -> log.error("User already exists");
default -> log.error("Received error response: {}", response.getError());
// Process other packets
List<ResponseListener<?>> responseListeners = listeners.get(packet.getClass());
if (responseListeners != null) {
for (ResponseListener<?> listener : responseListeners) {
notifyListener(listener, packet);
}
} else {
log.warn("No listeners registered for response type: {}", packet.getClass().getName());
}
case LoginSuccessResponse loginSuccessResponse -> log.info("Received login success response");
case null, default -> log.warn("Unknown message: {}", frame.text());
} else {
log.warn("Unknown or null packet received: {}", frame.text());
}
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
@@ -60,4 +110,14 @@ public class ClientHandler extends SimpleChannelInboundHandler<TextWebSocketFram
System.exit(0);
}
}
@SuppressWarnings("unchecked")
private <T> void notifyListener(ResponseListener<?> listener, T response) {
try {
((ResponseListener<T>) listener).onResponse(response);
} catch (ClassCastException e) {
log.error("Listener type mismatch for response: {}", response.getClass(), e);
}
}
}
@@ -0,0 +1,5 @@
package BsK.client.network.handler;
public interface ResponseListener<T> {
void onResponse(T response);
}
@@ -0,0 +1,218 @@
package BsK.client.ui.component.CheckUpPage;
import BsK.client.ui.component.MainFrame;
import BsK.client.ui.component.common.RoundedButtonUI;
import BsK.client.ui.component.common.RoundedPanel;
import javax.swing.*;
import java.awt.*;
public class CheckUpPage extends JPanel {
private boolean debugMode = false; // Enable debug mode
public CheckUpPage(MainFrame mainFrame) {
setLayout(new BorderLayout());
// Sidebar panel
JPanel sidebar = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
Color color1 = new Color(63, 81, 181);
Color color2 = new Color(33, 150, 243);
GradientPaint gp = new GradientPaint(0, 0, color1, 0, height, color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, width, height);
if (debugMode) {
drawBoundingBox(g2d, this);
}
}
};
sidebar.setBackground(new Color(63, 81, 181));
sidebar.setLayout(new GridLayout(15, 1));
sidebar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
String[] sidebarItems = {"Thống kê","Thăm khám", "Dữ liệu bệnh nhân", "Kho", "Người dùng", "Thông tin"};
String[] destination = {"DashboardPage","CheckUpPage", "PatientDataPage", "InventoryPage", "UserPage", "InfoPage"};
for(int i = 0; i < sidebarItems.length; i++) {
String item = sidebarItems[i];
String dest = destination[i];
JLabel label = new JLabel(item);
label.setForeground(Color.WHITE);
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // Change cursor to hand
label.setFont(new Font("Arial", Font.BOLD, 14));
// Add a mouse listener to handle click events
label.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseClicked(java.awt.event.MouseEvent e) {
// Handle the click event
mainFrame.showPage(dest);
// JOptionPane.showMessageDialog(null, item + " clicked!");
}
@Override
public void mouseEntered(java.awt.event.MouseEvent e) {
label.setForeground(new Color(200, 230, 255)); // Highlight on hover
}
@Override
public void mouseExited(java.awt.event.MouseEvent e) {
label.setForeground(Color.WHITE); // Restore original color
}
});
sidebar.add(label);
}
// Make the sidebar scrollable
JScrollPane sidebarScrollPane = new JScrollPane(sidebar);
sidebarScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
sidebarScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
sidebarScrollPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
sidebarScrollPane.getViewport().setOpaque(false);
sidebarScrollPane.setOpaque(false);
// Topbar panel
JPanel topbar = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (debugMode) {
drawBoundingBox((Graphics2D) g, this);
}
}
};
topbar.setLayout(new BorderLayout());
topbar.setBackground(Color.WHITE);
topbar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JLabel title = new JLabel("Check Up");
title.setFont(new Font("Arial", Font.BOLD, 18));
topbar.add(title, BorderLayout.WEST);
JLabel userInfo = new JLabel("User Name (Admin)");
userInfo.setHorizontalAlignment(SwingConstants.RIGHT);
topbar.add(userInfo, BorderLayout.EAST);
// Main content panel
JPanel mainContent = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (debugMode) {
drawBoundingBox((Graphics2D) g, this);
}
}
};
mainContent.setLayout(new BorderLayout());
mainContent.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
// Data table inside a RoundedPanel
RoundedPanel dataTable1 = new RoundedPanel(20, Color.WHITE, false) {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (debugMode) {
drawBoundingBox((Graphics2D) g, this);
}
}
};
RoundedPanel dataTable2 = new RoundedPanel(20, Color.WHITE, false) {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (debugMode) {
drawBoundingBox((Graphics2D) g, this);
}
}
};
JLabel titleText1 = new JLabel();
titleText1.setText("Check Up Queue 1");
titleText1.setFont(new Font("Arial", Font.BOLD, 16));
titleText1.setBackground(Color.WHITE);
titleText1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Padding
JLabel titleText2 = new JLabel();
titleText2.setText("Check Up Queue 2");
titleText2.setFont(new Font("Arial", Font.BOLD, 16));
titleText2.setBackground(Color.WHITE);
titleText2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Padding
dataTable1.setLayout(new BorderLayout());
dataTable1.add(titleText1, BorderLayout.NORTH);
dataTable1.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 10)); // Adjust padding for better appearance
dataTable2.setLayout(new BorderLayout());
dataTable2.add(titleText2, BorderLayout.NORTH);
dataTable2.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 10)); // Adjust padding for better appearance
String[] columns = {"Name", "Gender", "Course"};
String[][] data = {
{"John", "Male", "Java"},
{"Dara", "Male", "C++"},
{"Bora", "Male", "C#"},
};
JTable table1 = new JTable(data, columns);
JScrollPane tableScroll1 = new JScrollPane(table1);
tableScroll1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Inner padding
dataTable1.add(tableScroll1, BorderLayout.CENTER);
JTable table2 = new JTable(data, columns);
JScrollPane tableScroll2 = new JScrollPane(table2);
tableScroll2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Inner padding
dataTable2.add(tableScroll2, BorderLayout.CENTER);
UIManager.getDefaults().put("SplitPane.border", BorderFactory.createEmptyBorder()); // Remove border
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, dataTable1, dataTable2);
splitPane.setResizeWeight(0.5); // Split
// Add the split pane to the main content
mainContent.add(splitPane, BorderLayout.CENTER);
// Notice board
JPanel noticeBoard = new RoundedPanel(20, Color.WHITE, false) {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (debugMode) {
drawBoundingBox((Graphics2D) g, this);
}
}
};
noticeBoard.setLayout(new BorderLayout());
noticeBoard.setBorder(BorderFactory.createTitledBorder("Notice Board"));
noticeBoard.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JTextArea noticeText = new JTextArea("04/10/2021\nHidemode Now\n\n03/10/2021\nFurther Reading\n");
noticeText.setEditable(false);
noticeBoard.add(new JScrollPane(noticeText), BorderLayout.CENTER);
//mainContent.add(noticeBoard, BorderLayout.EAST);
// Adding panels to the frame
add(sidebarScrollPane, BorderLayout.WEST);
add(topbar, BorderLayout.NORTH);
add(mainContent, BorderLayout.CENTER);
}
private void drawBoundingBox(Graphics2D g2d, JComponent component) {
g2d.setColor(Color.RED);
g2d.setStroke(new BasicStroke(2));
g2d.drawRect(0, 0, component.getWidth() - 1, component.getHeight() - 1);
}
public static void main(String[] args) {
// JFrame frame = new JFrame("Dashboard");
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame.setSize(800, 600);
// frame.add(new CheckUpPage();
// frame.setVisible(true);
}
}
@@ -0,0 +1,179 @@
package BsK.client.ui.component.DashboardPage;
import BsK.client.ui.component.MainFrame;
import BsK.client.ui.component.common.RoundedButtonUI;
import BsK.client.ui.component.common.RoundedPanel;
import javax.swing.*;
import java.awt.*;
public class DashboardPage extends JPanel {
public DashboardPage(MainFrame mainFrame) {
setLayout(new BorderLayout());
// Sidebar panel
JPanel sidebar = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
Color color1 = new Color(63, 81, 181);
Color color2 = new Color(33, 150, 243);
GradientPaint gp = new GradientPaint(0, 0, color1, 0, height, color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, width, height);
}
};
sidebar.setBackground(new Color(63, 81, 181));
sidebar.setLayout(new GridLayout(15, 1));
sidebar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
String[] sidebarItems = {"Thống kê","Thăm khám", "Dữ liệu bệnh nhân", "Kho", "Người dùng", "Thông tin"};
String[] destination = {"DashboardPage","CheckUpPage", "PatientDataPage", "InventoryPage", "UserPage", "InfoPage"};
for(int i = 0; i < sidebarItems.length; i++) {
String item = sidebarItems[i];
String dest = destination[i];
JLabel label = new JLabel(item);
label.setForeground(Color.WHITE);
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // Change cursor to hand
label.setFont(new Font("Arial", Font.BOLD, 14));
// Add a mouse listener to handle click events
label.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseClicked(java.awt.event.MouseEvent e) {
// Handle the click event
mainFrame.showPage(dest);
// JOptionPane.showMessageDialog(null, item + " clicked!");
}
@Override
public void mouseEntered(java.awt.event.MouseEvent e) {
label.setForeground(new Color(200, 230, 255)); // Highlight on hover
}
@Override
public void mouseExited(java.awt.event.MouseEvent e) {
label.setForeground(Color.WHITE); // Restore original color
}
});
sidebar.add(label);
}
// Make the sidebar scrollable
JScrollPane sidebarScrollPane = new JScrollPane(sidebar);
sidebarScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
sidebarScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
sidebarScrollPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
sidebarScrollPane.getViewport().setOpaque(false);
sidebarScrollPane.setOpaque(false);
// Topbar panel
JPanel topbar = new JPanel();
topbar.setLayout(new BorderLayout());
topbar.setBackground(Color.WHITE);
topbar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JLabel title = new JLabel("Dashboard / Home");
title.setFont(new Font("Arial", Font.BOLD, 18));
topbar.add(title, BorderLayout.WEST);
JLabel userInfo = new JLabel("User Name (Admin)");
userInfo.setHorizontalAlignment(SwingConstants.RIGHT);
topbar.add(userInfo, BorderLayout.EAST);
// Main content panel
JPanel mainContent = new JPanel();
mainContent.setLayout(new BorderLayout());
mainContent.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
// Top cards
JPanel topCards = new JPanel();
topCards.setLayout(new GridLayout(1, 4, 20, 20));
String[] cardTitles = {"Add Check", "Income", "Expense", "Other Income"};
Color[] cardColors = {Color.PINK, Color.CYAN, Color.ORANGE, Color.GREEN};
for (int i = 0; i < cardTitles.length; i++) {
JPanel card = new RoundedPanel(20, cardColors[i], true);
card.setBackground(cardColors[i]);
card.setLayout(new BorderLayout());
card.setBorder(BorderFactory.createEmptyBorder(30, 20, 30, 20));
JLabel cardTitle = new JLabel(cardTitles[i]);
cardTitle.setForeground(Color.WHITE);
cardTitle.setHorizontalAlignment(SwingConstants.CENTER);
card.add(cardTitle, BorderLayout.NORTH);
JLabel cardValue = new JLabel("Value", SwingConstants.CENTER);
cardValue.setForeground(Color.WHITE);
cardValue.setFont(new Font("Arial", Font.BOLD, 16));
card.add(cardValue, BorderLayout.CENTER);
topCards.add(card);
}
mainContent.add(topCards, BorderLayout.NORTH);
// Wrapper panel for spacing
JPanel wrapperPanel = new JPanel();
wrapperPanel.setLayout(new BorderLayout());
wrapperPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); // Add spacing above
wrapperPanel.setOpaque(false); // Ensure transparency for background compatibility
// Data table inside a RoundedPanel
RoundedPanel dataTable = new RoundedPanel(20, Color.WHITE, false);
dataTable.setLayout(new BorderLayout());
dataTable.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // Adjust padding for better appearance
String[] columns = {"Name", "Gender", "Course", "Fees", "Action"};
String[][] data = {
{"John", "Male", "Java", "$300", "Edit/Delete"},
{"Dara", "Male", "C++", "$300", "Edit/Delete"},
{"Bora", "Male", "C#", "$300", "Edit/Delete"},
};
JTable table = new JTable(data, columns);
JScrollPane tableScroll = new JScrollPane(table);
tableScroll.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Inner padding
dataTable.add(tableScroll, BorderLayout.CENTER);
// Add RoundedPanel to the wrapper panel
wrapperPanel.add(dataTable, BorderLayout.CENTER);
// Add the wrapper panel to the main content
mainContent.add(wrapperPanel, BorderLayout.CENTER);
// Notice board
JPanel noticeBoard = new RoundedPanel(20, Color.WHITE, false);
noticeBoard.setLayout(new BorderLayout());
noticeBoard.setBorder(BorderFactory.createTitledBorder("Notice Board"));
noticeBoard.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JTextArea noticeText = new JTextArea("04/10/2021\nHidemode Now\n\n03/10/2021\nFurther Reading\n");
noticeText.setEditable(false);
noticeBoard.add(new JScrollPane(noticeText), BorderLayout.CENTER);
//mainContent.add(noticeBoard, BorderLayout.EAST);
// Adding panels to the frame
add(sidebarScrollPane, BorderLayout.WEST);
add(topbar, BorderLayout.NORTH);
add(mainContent, BorderLayout.CENTER);
}
public static void main(String[] args) {
// JFrame frame = new JFrame("Dashboard");
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame.setSize(800, 600);
// frame.add(new DashboardPage());
// frame.setVisible(true);
}
}
@@ -0,0 +1,175 @@
package BsK.client.ui.component.DashboardPage;
import BsK.client.ui.component.common.RoundedPanel;
import javax.swing.*;
import java.awt.*;
public class SchoolUI {
public static void main(String[] args) {
// Create the main frame
JFrame frame = new JFrame("School UI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1200, 800);
// Main layout
frame.setLayout(new BorderLayout());
// Sidebar panel
JPanel sidebar = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
Color color1 = new Color(63, 81, 181);
Color color2 = new Color(33, 150, 243);
GradientPaint gp = new GradientPaint(0, 0, color1, 0, height, color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, width, height);
}
};
sidebar.setBackground(new Color(63, 81, 181));
sidebar.setLayout(new GridLayout(15, 1));
sidebar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
String[] sidebarItems = {"Dashboard", "Charts", "Report", "Message", "Staff", "Student", "Library", "Holiday", "Calendar", "Chat App", "Contact", "File Manager", "Our Centres", "Gallery"};
for (String item : sidebarItems) {
JLabel label = new JLabel(item);
label.setForeground(Color.WHITE);
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // Change cursor to hand
label.setFont(new Font("Arial", Font.BOLD, 14));
// Add a mouse listener to handle click events
label.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseClicked(java.awt.event.MouseEvent e) {
// Handle the click event
System.out.println(item + " clicked!");
JOptionPane.showMessageDialog(null, item + " clicked!");
}
@Override
public void mouseEntered(java.awt.event.MouseEvent e) {
label.setForeground(new Color(200, 230, 255)); // Highlight on hover
}
@Override
public void mouseExited(java.awt.event.MouseEvent e) {
label.setForeground(Color.WHITE); // Restore original color
}
});
sidebar.add(label);
}
// Make the sidebar scrollable
JScrollPane sidebarScrollPane = new JScrollPane(sidebar);
sidebarScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
sidebarScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
sidebarScrollPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
sidebarScrollPane.getViewport().setOpaque(false);
sidebarScrollPane.setOpaque(false);
// Topbar panel
JPanel topbar = new JPanel();
topbar.setLayout(new BorderLayout());
topbar.setBackground(Color.WHITE);
topbar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JLabel title = new JLabel("Dashboard / Home");
title.setFont(new Font("Arial", Font.BOLD, 18));
topbar.add(title, BorderLayout.WEST);
JLabel userInfo = new JLabel("User Name (Admin)");
userInfo.setHorizontalAlignment(SwingConstants.RIGHT);
topbar.add(userInfo, BorderLayout.EAST);
// Main content panel
JPanel mainContent = new JPanel();
mainContent.setLayout(new BorderLayout());
mainContent.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
// Top cards
JPanel topCards = new JPanel();
topCards.setLayout(new GridLayout(1, 4, 20, 20));
String[] cardTitles = {"New Student", "Income", "Expense", "Other Income"};
Color[] cardColors = {Color.PINK, Color.CYAN, Color.ORANGE, Color.GREEN};
for (int i = 0; i < cardTitles.length; i++) {
JPanel card = new RoundedPanel(20, cardColors[i], true);
card.setBackground(cardColors[i]);
card.setLayout(new BorderLayout());
card.setBorder(BorderFactory.createEmptyBorder(30, 20, 30, 20));
JLabel cardTitle = new JLabel(cardTitles[i]);
cardTitle.setForeground(Color.WHITE);
cardTitle.setHorizontalAlignment(SwingConstants.CENTER);
card.add(cardTitle, BorderLayout.NORTH);
JLabel cardValue = new JLabel("Value", SwingConstants.CENTER);
cardValue.setForeground(Color.WHITE);
cardValue.setFont(new Font("Arial", Font.BOLD, 16));
card.add(cardValue, BorderLayout.CENTER);
topCards.add(card);
}
mainContent.add(topCards, BorderLayout.NORTH);
// Wrapper panel for spacing
JPanel wrapperPanel = new JPanel();
wrapperPanel.setLayout(new BorderLayout());
wrapperPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); // Add spacing above
wrapperPanel.setOpaque(false); // Ensure transparency for background compatibility
// Data table inside a RoundedPanel
RoundedPanel dataTable = new RoundedPanel(20, Color.WHITE, false);
dataTable.setLayout(new BorderLayout());
dataTable.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // Adjust padding for better appearance
String[] columns = {"Name", "Gender", "Course", "Fees", "Action"};
String[][] data = {
{"John", "Male", "Java", "$300", "Edit/Delete"},
{"Dara", "Male", "C++", "$300", "Edit/Delete"},
{"Bora", "Male", "C#", "$300", "Edit/Delete"},
};
JTable table = new JTable(data, columns);
JScrollPane tableScroll = new JScrollPane(table);
tableScroll.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Inner padding
dataTable.add(tableScroll, BorderLayout.CENTER);
// Add RoundedPanel to the wrapper panel
wrapperPanel.add(dataTable, BorderLayout.CENTER);
// Add the wrapper panel to the main content
mainContent.add(wrapperPanel, BorderLayout.CENTER);
// Notice board
JPanel noticeBoard = new RoundedPanel(20, Color.WHITE, false);
noticeBoard.setLayout(new BorderLayout());
noticeBoard.setBorder(BorderFactory.createTitledBorder("Notice Board"));
noticeBoard.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JTextArea noticeText = new JTextArea("04/10/2021\nHidemode Now\n\n03/10/2021\nFurther Reading\n");
noticeText.setEditable(false);
noticeBoard.add(new JScrollPane(noticeText), BorderLayout.CENTER);
//mainContent.add(noticeBoard, BorderLayout.EAST);
// Adding panels to the frame
frame.add(sidebarScrollPane, BorderLayout.WEST);
frame.add(topbar, BorderLayout.NORTH);
frame.add(mainContent, BorderLayout.CENTER);
frame.setVisible(true);
}
}
@@ -0,0 +1,134 @@
package BsK.client.ui.component.LandingPage;
import BsK.client.ui.component.MainFrame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class LandingPage extends JPanel {
public LandingPage(MainFrame mainFrame) {
setLayout(new BorderLayout());
// Left and middle panel with background image and tint
JPanel leftMiddlePanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
ImageIcon icon = new ImageIcon("/Users/lethanhdat/Documents/GitHub/ldS_BsK/src/main/java/BsK/client/ui/image/landingpagebg.jpeg");
Image image = icon.getImage();
g2d.drawImage(image, 0, 0, getWidth(), getHeight(), this);
Color tint = new Color(0, 0, 0, 100); // Black tint with transparency
g2d.setColor(tint);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
};
leftMiddlePanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.gridx = 0;
gbc.gridy = 0;
JLabel titleLabel = new JLabel("BSK");
titleLabel.setForeground(Color.WHITE);
titleLabel.setFont(new Font("Arial", Font.BOLD, 50));
leftMiddlePanel.add(titleLabel, gbc);
gbc.gridy++;
JLabel authorLabel = new JLabel("by lds217 and miti99");
authorLabel.setForeground(Color.WHITE);
authorLabel.setFont(new Font("Arial", Font.PLAIN, 12));
leftMiddlePanel.add(authorLabel, gbc);
// Right panel with blue gradient and buttons
JPanel rightPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
Color color1 = new Color(0, 0, 255);
Color color2 = new Color(173, 216, 230);
GradientPaint gp = new GradientPaint(0, 0, color1, width, height, color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, width, height);
}
};
rightPanel.setLayout(new GridBagLayout());
rightPanel.setPreferredSize(new Dimension(300, getHeight())); // Set preferred size for the right panel
gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.gridx = 0;
gbc.gridy = 0;
JButton loginButton = new RoundedButton("Login");
JButton registerButton = new RoundedButton("Register");
// Set the same preferred size for both buttons
Dimension buttonSize = new Dimension(150, 40);
loginButton.setPreferredSize(buttonSize);
registerButton.setPreferredSize(buttonSize);
rightPanel.add(loginButton, gbc);
gbc.gridy++;
rightPanel.add(registerButton, gbc);
add(leftMiddlePanel, BorderLayout.CENTER);
add(rightPanel, BorderLayout.EAST);
// Action listeners for buttons
loginButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mainFrame.showPage("LoginPage");
}
});
registerButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mainFrame.showPage("RegisterPage");
}
});
}
// Custom button class with rounded edges and stroke
private static class RoundedButton extends JButton {
public RoundedButton(String text) {
super(text);
setContentAreaFilled(false);
setFocusPainted(false);
setOpaque(false);
setBorderPainted(false); // Ensure the border is not painted
}
@Override
protected void paintComponent(Graphics g) {
// Do not call super.paintComponent(g) to avoid painting the background
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(getBackground());
g2.fillRoundRect(0, 0, getWidth(), getHeight(), 30, 30);
g2.dispose();
super.paintComponent(g); // Call super to paint the text
}
@Override
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.setStroke(new BasicStroke(2));
g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 30, 30);
g2.dispose();
}
@Override
public Insets getInsets() {
return new Insets(10, 20, 10, 20);
}
}
}
@@ -0,0 +1,122 @@
package BsK.client.ui.component.LoginPage;
import BsK.client.network.handler.ClientHandler;
import BsK.client.ui.component.MainFrame;
import BsK.common.packet.Packet;
import BsK.common.packet.PacketSerializer;
import BsK.common.packet.req.LoginRequest;
import BsK.common.packet.res.ErrorResponse;
import BsK.common.packet.res.LoginSuccessResponse;
import BsK.common.util.network.NetworkUtil;
import lombok.extern.slf4j.Slf4j;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@Slf4j
public class LoginPage extends JPanel {
public LoginPage(MainFrame mainFrame) {
setLayout(new BorderLayout());
// Panel with background image and tint
JPanel backgroundPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
ImageIcon icon = new ImageIcon("src/main/java/BsK/client/ui/image/landingpagebg.jpeg");
Image image = icon.getImage();
g2d.drawImage(image, 0, 0, getWidth(), getHeight(), this);
Color tint = new Color(0, 0, 0, 100); // Black tint with transparency
g2d.setColor(tint);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
};
backgroundPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2; // Span across two columns
JLabel promptLabel = new JLabel("Please enter your details:");
promptLabel.setForeground(Color.WHITE);
promptLabel.setFont(new Font("Arial", Font.BOLD, 20));
backgroundPanel.add(promptLabel, gbc);
gbc.gridwidth = 1; // Reset to default
gbc.gridy++;
JLabel usernameLabel = new JLabel("Enter Username:");
usernameLabel.setForeground(Color.WHITE);
backgroundPanel.add(usernameLabel, gbc);
gbc.gridx = 1;
JTextField loginField = new JTextField(20);
backgroundPanel.add(loginField, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel passwordLabel = new JLabel("Enter Password:");
passwordLabel.setForeground(Color.WHITE);
backgroundPanel.add(passwordLabel, gbc);
gbc.gridx = 1;
JPasswordField passwordField = new JPasswordField(20);
backgroundPanel.add(passwordField, gbc);
gbc.gridy++;
JButton loginButton = new JButton("Login");
loginButton.addActionListener(e -> {
char[] passwordChars = passwordField.getPassword();
String password = new String(passwordChars);
String username = loginField.getText();
var loginRequest = new LoginRequest(username, password);
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), loginRequest);
});
// Register listeners for login-related responses
ClientHandler.addResponseListener(LoginSuccessResponse.class, response -> {
log.info("Login successful, UserId: {}, Role: {}", response.getUserId(), response.getRole());
SwingUtilities.invokeLater(() -> mainFrame.showPage("DashboardPage"));
});
ClientHandler.addResponseListener(ErrorResponse.class, response -> {
log.error("Login error: {}", response.getError());
SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(this,
"Login failed: " + response.getError(), "Error", JOptionPane.ERROR_MESSAGE));
});
backgroundPanel.add(loginButton, gbc);
add(backgroundPanel, BorderLayout.CENTER);
JButton backButton = new JButton("Back");
backButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mainFrame.showPage("LandingPage");
}
});
add(backButton, BorderLayout.SOUTH);
}
@Override
public void removeNotify() {
super.removeNotify();
// Remove listeners to avoid memory leaks
ClientHandler.removeResponseListener(LoginSuccessResponse.class, this::handleLoginSuccess);
ClientHandler.removeResponseListener(ErrorResponse.class, this::handleErrorResponse);
}
private void handleLoginSuccess(LoginSuccessResponse response) {
log.info("Login successful, UserId: {}, Role: {}", response.getUserId(), response.getRole());
}
private void handleErrorResponse(ErrorResponse response) {
log.error("Error response: {}", response.getError());
}
}
@@ -0,0 +1,44 @@
package BsK.client.ui.component;
import BsK.client.ui.component.CheckUpPage.CheckUpPage;
import BsK.client.ui.component.DashboardPage.DashboardPage;
import BsK.client.ui.component.LandingPage.LandingPage;
import BsK.client.ui.component.LoginPage.LoginPage;
import BsK.client.ui.component.RegisterPage.RegisterPage;
import javax.swing.*;
import java.awt.*;
public class MainFrame extends JFrame {
private CardLayout cardLayout;
private JPanel mainPanel;
public MainFrame() {
setTitle("BSK");
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);
// Add pages to the main panel
mainPanel.add(new LandingPage(this), "LandingPage");
mainPanel.add(new LoginPage(this), "LoginPage");
mainPanel.add(new RegisterPage(this), "RegisterPage");
mainPanel.add(new DashboardPage(this), "DashboardPage");
mainPanel.add(new CheckUpPage(this), "CheckUpPage");
add(mainPanel);
}
public void showPage(String pageName) {
cardLayout.show(mainPanel, pageName);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new MainFrame().setVisible(true);
});
}
}
@@ -0,0 +1,116 @@
package BsK.client.ui.component.RegisterPage;
import BsK.client.ui.component.MainFrame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class RegisterPage extends JPanel {
public RegisterPage(MainFrame mainFrame) {
setLayout(new BorderLayout());
// Panel with background image and tint
JPanel backgroundPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
ImageIcon icon = new ImageIcon("src/main/java/BsK/client/ui/image/landingpagebg.jpeg");
Image image = icon.getImage();
g2d.drawImage(image, 0, 0, getWidth(), getHeight(), this);
Color tint = new Color(0, 0, 0, 100); // Black tint with transparency
g2d.setColor(tint);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
};
backgroundPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
JLabel promptLabel = new JLabel("Please enter your details:");
promptLabel.setForeground(Color.WHITE);
promptLabel.setFont(new Font("Arial", Font.BOLD, 20));
gbc.gridwidth = 2;
backgroundPanel.add(promptLabel, gbc);
gbc.gridwidth = 1;
gbc.gridy++;
JLabel usernameLabel = new JLabel("Username:");
usernameLabel.setForeground(Color.WHITE);
backgroundPanel.add(usernameLabel, gbc);
gbc.gridx = 1;
JTextField usernameField = new JTextField(20);
backgroundPanel.add(usernameField, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel nameLabel = new JLabel("Name:");
nameLabel.setForeground(Color.WHITE);
backgroundPanel.add(nameLabel, gbc);
gbc.gridx = 1;
JTextField nameField = new JTextField(20);
backgroundPanel.add(nameField, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel passwordLabel = new JLabel("Password:");
passwordLabel.setForeground(Color.WHITE);
backgroundPanel.add(passwordLabel, gbc);
gbc.gridx = 1;
JPasswordField passwordField = new JPasswordField(20);
backgroundPanel.add(passwordField, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel rePasswordLabel = new JLabel("Re-enter your password:");
rePasswordLabel.setForeground(Color.WHITE);
backgroundPanel.add(rePasswordLabel, gbc);
gbc.gridx = 1;
JPasswordField rePasswordField = new JPasswordField(20);
backgroundPanel.add(rePasswordField, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel roleLabel = new JLabel("Role:");
roleLabel.setForeground(Color.WHITE);
backgroundPanel.add(roleLabel, gbc);
gbc.gridx = 1;
String[] roles = {"user", "admin", "doctor", "nurse"};
JComboBox<String> roleComboBox = new JComboBox<>(roles);
backgroundPanel.add(roleComboBox, gbc);
gbc.gridy++;
JButton loginButton = new JButton("Register");
loginButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mainFrame.showPage("LandingPage");
}
});
backgroundPanel.add(loginButton, gbc);
add(backgroundPanel, BorderLayout.CENTER);
// Back button to return to the landing page
JButton backButton = new JButton("Back");
backButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mainFrame.showPage("LandingPage");
}
});
add(backButton, BorderLayout.SOUTH);
}
public static void main(String[] args) {
System.out.println("Working Directory = " + System.getProperty("user.dir"));
}
}
@@ -0,0 +1,39 @@
package BsK.client.ui.component.common;
import javax.swing.*;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.*;
public class RoundedButtonUI extends BasicButtonUI {
private final int cornerRadius;
public RoundedButtonUI(int cornerRadius) {
this.cornerRadius = cornerRadius;
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
JButton button = (JButton) c;
button.setOpaque(false);
button.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
}
@Override
public void paint(Graphics g, JComponent c) {
JButton button = (JButton) c;
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int width = button.getWidth();
int height = button.getHeight();
g2.setColor(button.getBackground());
g2.fillRoundRect(0, 0, width, height, cornerRadius, cornerRadius);
g2.setColor(button.getForeground());
g2.setFont(button.getFont());
FontMetrics fm = g2.getFontMetrics();
int stringWidth = fm.stringWidth(button.getText());
int stringHeight = fm.getAscent();
g2.drawString(button.getText(), (width - stringWidth) / 2, (height + stringHeight) / 2 - 2);
g2.dispose();
}
}
@@ -0,0 +1,43 @@
package BsK.client.ui.component.common;
import javax.swing.*;
import java.awt.*;
public class RoundedPanel extends JPanel {
private int cornerRadius;
private Color fillColor;
private boolean gradient;
public RoundedPanel(int radius, Color fillColor, boolean gradient) {
super();
this.cornerRadius = radius;
this.fillColor = fillColor;
this.gradient = gradient;
setOpaque(false); // Ensures background is transparent outside the rounded area
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
Graphics2D graphics = (Graphics2D) g;
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Create a gradient paint from white to the fillColor
GradientPaint gradientColor = new GradientPaint(
-100, -100, Color.WHITE, width, height, fillColor
);
// Apply the gradient as the fill paint
if(gradient)
graphics.setPaint(gradientColor);
else
graphics.setColor(fillColor);
graphics.fillRoundRect(0, 0, width, height, cornerRadius, cornerRadius);
// Draw the rounded border
// graphics.setColor(getForeground());
// graphics.drawRoundRect(0, 0, width - 1, height - 1, cornerRadius, cornerRadius);
}
}
@@ -1,6 +1,7 @@
package BsK.client.ui.handler;
import BsK.client.network.handler.ClientHandler;
import BsK.client.ui.component.MainFrame;
import BsK.common.packet.Packet;
import BsK.common.packet.req.LoginRequest;
import BsK.common.packet.res.HandshakeCompleteResponse;
@@ -31,35 +32,9 @@ public class UIHandler {
}
public void showUI() {
JTextField usernameField = new JTextField();
JPasswordField passwordField = new JPasswordField();
Object[] message = {
"Username:", usernameField,
"Password:", passwordField
};
int option = JOptionPane.showConfirmDialog(null, message, "Login", JOptionPane.OK_CANCEL_OPTION);
if (option == JOptionPane.OK_OPTION) {
String username = usernameField.getText();
String password = new String(passwordField.getPassword());
System.out.println("Username: " + username);
System.out.println("Password: " + password);
var login = new LoginRequest(username, password);
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), login);
} else {
System.out.println("Login canceled");
}
SwingUtilities.invokeLater(() -> {
new MainFrame().setVisible(true);
});
}
// public void onClickButtonLogin() {
// if (!readyToLogin) {
// // TODO: hiển thị lỗi "Chưa kết nối tới server"
// return;
// }
// var username = "username"; // Đọc từ đâu đó
// var password = "password"; // Đọc từ đâu đó
//
// NetworkUtil.sendPacket(ctx.channel(), login);
// NetworkUtil.sendPacket(loginRequest);
// }
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

@@ -8,6 +8,7 @@ import java.time.LocalDateTime;
@AllArgsConstructor
@Data
public class LoginRequest implements Packet {
String username;
String password;
@@ -10,7 +10,11 @@ public class ErrorResponse implements Packet {
Error error;
public enum Error {
public String getError() {
return error.toString();
}
public enum Error {
SUCCESS,
UNKNOWN,
USERNAME_NOT_FOUND,
+61 -35
View File
@@ -17,48 +17,74 @@ import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import java.net.InetSocketAddress;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Server {
private static final int PORT = 1999;
static Connection connection;
public static void main(String[] args) throws InterruptedException {
EventLoopGroup parentGroup =
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
EventLoopGroup childGroup =
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
try {
ServerBootstrap bootstrap =
new ServerBootstrap()
.group(parentGroup, childGroup)
.channel(
Epoll.isAvailable()
? EpollServerSocketChannel.class
: NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(PORT))
.childHandler(
new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new IdleStateHandler(60 * 30, 0, 0, TimeUnit.SECONDS))
.addLast(new HttpServerCodec())
.addLast(new ChunkedWriteHandler())
.addLast(new HttpObjectAggregator(8192))
.addLast("ws", new WebSocketServerProtocolHandler("/"))
.addLast(new ServerHandler());
}
});
static {
try {
connection = DriverManager.getConnection("jdbc:sqlite:src/main/resources/database/BSK.db");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
ChannelFuture f = bootstrap.bind().sync();
public static Statement statement;
log.info("Server started on port {}", PORT);
f.channel().closeFuture().sync();
} finally {
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
static {
try {
statement = connection.createStatement();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Server() throws SQLException {
}
public static void main(String[] args) throws InterruptedException, SQLException {
EventLoopGroup parentGroup =
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
EventLoopGroup childGroup =
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
try {
ServerBootstrap bootstrap =
new ServerBootstrap()
.group(parentGroup, childGroup)
.channel(
Epoll.isAvailable()
? EpollServerSocketChannel.class
: NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(PORT))
.childHandler(
new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new IdleStateHandler(60 * 30, 0, 0, TimeUnit.SECONDS))
.addLast(new HttpServerCodec())
.addLast(new ChunkedWriteHandler())
.addLast(new HttpObjectAggregator(8192))
.addLast("ws", new WebSocketServerProtocolHandler("/"))
.addLast(new ServerHandler());
}
});
ChannelFuture f = bootstrap.bind().sync();
log.info("Server started on port {}", PORT);
f.channel().closeFuture().sync();
} finally {
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
}
}
}
@@ -1,26 +1,50 @@
package BsK.server.network.entity;
import BsK.server.network.manager.SessionManager;
import io.netty.channel.Channel;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.sql.ResultSet;
import java.sql.SQLException;
import static BsK.server.Server.statement;
@Slf4j
@Data
public class User {
int id;
int userId;
Channel channel;
Role role = Role.GUEST;
Role role;
public User(int id, Channel channel) {
this.id = id;
int sessionId;
public User(Channel channel, int sessionId) {
this.channel = channel;
this.sessionId = sessionId;
Role role = Role.GUEST;
}
public void authenticate(String username, String password) {
if (username.equals("admin") && password.equals("admin")) {
role = Role.ADMIN;
} else if (username.equals("user") && password.equals("user")) {
role = Role.USER;
}
try {
ResultSet rs = statement.executeQuery("select * from User where user_name = '" + username + "' and password = '" + password + "'");
if (!rs.isBeforeFirst()) {
System.out.println("No data found in the User table.");
} else {
while(rs.next())
{
log.info(rs.getString("name") + " logged in");
role = Role.valueOf(rs.getString("role_name"));
userId = rs.getInt("user_id");
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public boolean isAuthenticated() {
@@ -13,7 +13,7 @@ import BsK.common.packet.res.LoginSuccessResponse;
import BsK.common.util.network.NetworkUtil;
import BsK.server.database.entity.Patient;
import BsK.server.database.entity.Patient.Sex;
import BsK.server.network.manager.UserManager;
import BsK.server.network.manager.SessionManager;
import BsK.server.network.util.UserUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
@@ -32,17 +32,19 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
log.debug("Received message: {}", frame.text());
Packet packet = PacketSerializer.GSON.fromJson(frame.text(), Packet.class);
if (packet instanceof LoginRequest loginRequest) {
log.debug(
"Received login request: {}, {}", loginRequest.getUsername(), loginRequest.getPassword());
var user = UserManager.getUserByChannel(ctx.channel());
var user = SessionManager.getUserByChannel(ctx.channel().id().asLongText());
user.authenticate(loginRequest.getUsername(), loginRequest.getPassword());
if (user.isAuthenticated()) {
log.info("User {} authenticated, role {}", user.getId(), user.getRole());
UserUtil.sendPacket(user.getId(), new LoginSuccessResponse(user.getId(), user.getRole()));
UserUtil.sendPacket(user.getSessionId(), new LoginSuccessResponse(user.getUserId(), user.getRole()));
log.info("Send response to client User {} authenticated, role {}", user.getUserId(), user.getRole());
} else {
log.info("User {} failed to authenticate", user.getId());
log.info("User {} failed to authenticate", user.getUserId());
}
} else if (packet instanceof RegisterRequest registerRequest) {
log.debug(
@@ -57,19 +59,20 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
}
} else {
// Gia su packet nay can verify la user da login
var user = UserManager.getUserByChannel(ctx.channel());
var user = SessionManager.getUserByChannel(ctx.channel().id().asLongText());
if (!user.isAuthenticated()) {
log.warn("Received packet from unauthenticated user: {}", packet);
return;
}
switch (packet) {
case GetPatientInfoReq getPatientInfoReq -> {
var patientInfo =
new Patient(getPatientInfoReq.getPatientId(), new Date(1999, 01, 01), "test",
Sex.MALE);
var response = new GetPatientInfoRes(patientInfo);
UserUtil.sendPacket(user.getId(), response);
UserUtil.sendPacket(user.getUserId(), response);
}
case null, default -> log.warn("Received unknown packet: {}", packet);
}
@@ -79,7 +82,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause instanceof IOException) {
UserManager.onUserDisconnect(ctx.channel());
SessionManager.onUserDisconnect(ctx.channel());
} else {
log.error("ERROR: ", cause);
}
@@ -90,16 +93,16 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
if (evt instanceof IdleStateEvent event) {
if (event.state() == IdleState.READER_IDLE) {
try {
UserManager.onUserDisconnect(ctx.channel());
SessionManager.onUserDisconnect(ctx.channel());
ctx.channel().close();
} catch (Exception e) {
}
}
} else if (evt instanceof HandshakeComplete) {
int userId = UserManager.onUserLogin(ctx.channel());
log.info("User {} logged in", userId);
int SessionId = SessionManager.onUserLogin(ctx.channel());
log.info("Session {} logged in", SessionId);
UserUtil.sendPacket(userId, new HandshakeCompleteResponse());
UserUtil.sendPacket(SessionId, new HandshakeCompleteResponse());
} else {
super.userEventTriggered(ctx, evt);
}
@@ -0,0 +1,48 @@
package BsK.server.network.manager;
import BsK.server.network.entity.User;
import io.netty.channel.Channel;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SessionManager {
private static final Map<Integer, String> SESSION_ID_MAP = new ConcurrentSkipListMap<>();
private static final Map<String, Integer> CHANNEL_SESSION_ID_MAP = new ConcurrentHashMap<>();
private static final Map<String, User> CHANNEL_TO_USER_MAP = new ConcurrentHashMap<>();
private static final AtomicInteger SESSION_ID = new AtomicInteger(0);
public static User getUserByChannel(String channel) {
return CHANNEL_TO_USER_MAP.get(channel);
}
public static int getSessionByChannelId(String channelId) {
return CHANNEL_SESSION_ID_MAP.get(channelId);
}
public static String getChannelBySessionId(int sessionId) {
return SESSION_ID_MAP.get(sessionId);
}
public static int onUserLogin(Channel channel) {
int sessionId = SESSION_ID.incrementAndGet();
var user = new User(channel, sessionId);
SESSION_ID_MAP.put(sessionId, channel.id().asLongText());
CHANNEL_SESSION_ID_MAP.put(channel.id().asLongText(), sessionId);
CHANNEL_TO_USER_MAP.put(channel.id().asLongText(), user);
return sessionId;
}
public static void onUserDisconnect(Channel channel) {
int sessionId = CHANNEL_SESSION_ID_MAP.remove(channel.id().asLongText());
SESSION_ID_MAP.remove(sessionId);
}
}
@@ -1,43 +0,0 @@
package BsK.server.network.manager;
import BsK.server.network.entity.User;
import io.netty.channel.Channel;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class UserManager {
private static final Map<Integer, User> USER_MAP = new ConcurrentSkipListMap<>();
private static final Map<String, Integer> CHANNEL_ID_MAP = new ConcurrentHashMap<>();
private static final AtomicInteger USER_ID = new AtomicInteger(0);
public static User getUserById(int userId) {
return USER_MAP.get(userId);
}
public static User getUserByChannelId(String channelId) {
return USER_MAP.get(CHANNEL_ID_MAP.get(channelId));
}
public static User getUserByChannel(Channel channel) {
return getUserByChannelId(channel.id().asLongText());
}
public static int onUserLogin(Channel channel) {
int userId = USER_ID.incrementAndGet();
var user = new User(userId, channel);
USER_MAP.put(userId, user);
CHANNEL_ID_MAP.put(channel.id().asLongText(), userId);
return userId;
}
public static void onUserDisconnect(Channel channel) {
USER_MAP.remove(CHANNEL_ID_MAP.remove(channel.id().asLongText()));
}
}
@@ -2,14 +2,16 @@ package BsK.server.network.util;
import BsK.common.packet.Packet;
import BsK.common.util.network.NetworkUtil;
import BsK.server.network.manager.UserManager;
import BsK.server.network.manager.SessionManager;
import io.netty.channel.Channel;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class UserUtil {
public static void sendPacket(int userId, Packet packet) {
var user = UserManager.getUserById(userId);
public static void sendPacket(int sessionId, Packet packet) {
String channel = SessionManager.getChannelBySessionId(sessionId);
var user = SessionManager.getUserByChannel(channel);
if (user == null) return;
NetworkUtil.sendPacket(user.getChannel(), packet);
+45
View File
@@ -0,0 +1,45 @@
package BsK.testing;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Sample
{
public static void main(String[] args)
{
// NOTE: Connection and Statement are AutoCloseable.
// Don't forget to close them both in order to avoid leaks.
try
(
// create a database connection
Connection connection = DriverManager.getConnection("jdbc:sqlite:src/main/resources/database/BSK.db");
Statement statement = connection.createStatement();
)
{
System.out.println("Connection established successfully.");
statement.setQueryTimeout(30); // set timeout to 30 sec.
ResultSet rs = statement.executeQuery("select * from User");
if (!rs.isBeforeFirst()) {
System.out.println("No data found in the User table.");
} else {
while(rs.next())
{
// read the result set
System.out.println("name = " + rs.getString("name"));
System.out.println("id = " + rs.getInt("user_id"));
}
}
}
catch(SQLException e)
{
// if the error message is "out of memory",
// it probably means no database file is found
e.printStackTrace(System.err);
}
}
}
Binary file not shown.
View File
Whitespace-only changes.