diff --git a/README.md b/README.md index 847ae3a..f153730 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@ LiMe is a communication app which allows you to send messages whenever and where The Li Xin Messenger ## Version -- C_v 0.5 -- S_v 0.5 +- C_v 0.6.0 +- S_v 0.6.0 ``` _______________________ -/ Finally, v_0.5! \ +/ Finally, v_0.6! \ | _ _ __ __ | | | | (_) \/ | ___ | | | | | | |\/| |/ _ \ | @@ -43,28 +43,38 @@ The Register GUI ![](./ScreenShots/LiMeRegister.png) -The Chat GUI of user @Lixin, the friend list is on the left side of the panel +The User Agreement (HTML parsing) + +![](./ScreenShots/LiMeAgreement.png) + +The Chat GUI of user @lixin, the friend list is on the left side of the panel ![](./ScreenShots/LiMeChatLixin.png) The Chat GUI of user @Test ![](./ScreenShots/LiMeChatTest.png) -## The File Transmission +### The Group Chat + +![](./ScreenShots/LiMeChatTest.png) + +### The File Transmission + +![](./ScreenShots/LiMeGroupChat.png) -![](./ScreenShots/LiMeChatFile.png) +## Data persistence -## Data persistence and user management +MySQL table structure -MySQL +![](./ScreenShots/TableStructure.png) ## TODO - [ ] Gradle the project - [ ] Use HTML to render the email content - [ ] Use hibernate or Mybatis as a persistence framework - [ ] The process bar for the file transmission -- [ ] Open group chat for all users - [ ] A fancy website for LiMe +- [X] Open group chat for all users - [x] Enable user to reset password via a server-sent Email - [x] Redirect LiMe to the new domain name - [x] Email is should be a unique key (LiMeSeedRecoverPassword) diff --git a/ScreenShots/LiMeAgreement.png b/ScreenShots/LiMeAgreement.png new file mode 100644 index 0000000..c4b8b64 Binary files /dev/null and b/ScreenShots/LiMeAgreement.png differ diff --git a/ScreenShots/LiMeChatFile.png b/ScreenShots/LiMeChatFile.png index 5e4167f..c597133 100644 Binary files a/ScreenShots/LiMeChatFile.png and b/ScreenShots/LiMeChatFile.png differ diff --git a/ScreenShots/LiMeChatLixin.png b/ScreenShots/LiMeChatLixin.png index 1e2fa4b..088a70d 100644 Binary files a/ScreenShots/LiMeChatLixin.png and b/ScreenShots/LiMeChatLixin.png differ diff --git a/ScreenShots/LiMeChatTest.png b/ScreenShots/LiMeChatTest.png index e33fc91..248024b 100644 Binary files a/ScreenShots/LiMeChatTest.png and b/ScreenShots/LiMeChatTest.png differ diff --git a/ScreenShots/LiMeGroupChat.png b/ScreenShots/LiMeGroupChat.png new file mode 100644 index 0000000..9f6d616 Binary files /dev/null and b/ScreenShots/LiMeGroupChat.png differ diff --git a/ScreenShots/LiMeLogin.png b/ScreenShots/LiMeLogin.png index c6bdac5..67ffac9 100644 Binary files a/ScreenShots/LiMeLogin.png and b/ScreenShots/LiMeLogin.png differ diff --git a/ScreenShots/LiMeRegister.png b/ScreenShots/LiMeRegister.png index 8157cd9..07787f6 100644 Binary files a/ScreenShots/LiMeRegister.png and b/ScreenShots/LiMeRegister.png differ diff --git a/ScreenShots/LiMeServer.png b/ScreenShots/LiMeServer.png index 5e53154..9279e50 100644 Binary files a/ScreenShots/LiMeServer.png and b/ScreenShots/LiMeServer.png differ diff --git a/ScreenShots/TableStructure.png b/ScreenShots/TableStructure.png new file mode 100644 index 0000000..f0438d0 Binary files /dev/null and b/ScreenShots/TableStructure.png differ diff --git a/out/.DS_Store b/out/.DS_Store index 107b1cb..ff2e08d 100644 Binary files a/out/.DS_Store and b/out/.DS_Store differ diff --git a/out/artifacts/.DS_Store b/out/artifacts/.DS_Store index 1b9599d..79beed0 100644 Binary files a/out/artifacts/.DS_Store and b/out/artifacts/.DS_Store differ diff --git a/out/artifacts/LiMeServer_jar/LiMeServer.jar b/out/artifacts/LiMeServer_jar/LiMeServer.jar index 13973ff..e59d6b1 100644 Binary files a/out/artifacts/LiMeServer_jar/LiMeServer.jar and b/out/artifacts/LiMeServer_jar/LiMeServer.jar differ diff --git a/out/artifacts/LiMe_jar/LiMe.jar b/out/artifacts/LiMe_jar/LiMe.jar index 22e32ab..362978d 100644 Binary files a/out/artifacts/LiMe_jar/LiMe.jar and b/out/artifacts/LiMe_jar/LiMe.jar differ diff --git a/out/production/LiMe/com/lixin/lime/client/META-INF/MANIFEST.MF b/out/production/LiMe/com/lixin/lime/client/META-INF/MANIFEST.MF index 9a42dd6..500cc96 100644 --- a/out/production/LiMe/com/lixin/lime/client/META-INF/MANIFEST.MF +++ b/out/production/LiMe/com/lixin/lime/client/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ -Manifest-Version: 0.5.2 +Manifest-Version: 0.6.0 Main-Class: com.lixin.lime.LiMe diff --git a/out/production/LiMe/com/lixin/lime/client/controller/LiMeController.class b/out/production/LiMe/com/lixin/lime/client/controller/LiMeController.class index bf37a86..07dff8a 100644 Binary files a/out/production/LiMe/com/lixin/lime/client/controller/LiMeController.class and b/out/production/LiMe/com/lixin/lime/client/controller/LiMeController.class differ diff --git a/out/production/LiMe/com/lixin/lime/client/controller/LiMeKnight.class b/out/production/LiMe/com/lixin/lime/client/controller/LiMeKnight.class index ef9fb66..cc41d8f 100644 Binary files a/out/production/LiMe/com/lixin/lime/client/controller/LiMeKnight.class and b/out/production/LiMe/com/lixin/lime/client/controller/LiMeKnight.class differ diff --git a/out/production/LiMe/com/lixin/lime/client/model/LiMeModel$SeedGrinder.class b/out/production/LiMe/com/lixin/lime/client/model/LiMeModel$SeedGrinder.class index 70833a9..58da348 100644 Binary files a/out/production/LiMe/com/lixin/lime/client/model/LiMeModel$SeedGrinder.class and b/out/production/LiMe/com/lixin/lime/client/model/LiMeModel$SeedGrinder.class differ diff --git a/out/production/LiMe/com/lixin/lime/client/model/LiMeModel.class b/out/production/LiMe/com/lixin/lime/client/model/LiMeModel.class index 232a2e1..295b4cb 100644 Binary files a/out/production/LiMe/com/lixin/lime/client/model/LiMeModel.class and b/out/production/LiMe/com/lixin/lime/client/model/LiMeModel.class differ diff --git a/out/production/LiMe/com/lixin/lime/client/view/LiMeLoginFrame.class b/out/production/LiMe/com/lixin/lime/client/view/LiMeLoginFrame.class index 30ee441..ccc70e1 100644 Binary files a/out/production/LiMe/com/lixin/lime/client/view/LiMeLoginFrame.class and b/out/production/LiMe/com/lixin/lime/client/view/LiMeLoginFrame.class differ diff --git a/out/production/LiMe/com/lixin/lime/protocol/seed/LiMeSeed.class b/out/production/LiMe/com/lixin/lime/protocol/seed/LiMeSeed.class index 4ed2010..7a593de 100644 Binary files a/out/production/LiMe/com/lixin/lime/protocol/seed/LiMeSeed.class and b/out/production/LiMe/com/lixin/lime/protocol/seed/LiMeSeed.class differ diff --git a/out/production/LiMe/com/lixin/lime/protocol/util/factory/MyStaticFactory.class b/out/production/LiMe/com/lixin/lime/protocol/util/factory/MyStaticFactory.class index 934b11b..462afd4 100644 Binary files a/out/production/LiMe/com/lixin/lime/protocol/util/factory/MyStaticFactory.class and b/out/production/LiMe/com/lixin/lime/protocol/util/factory/MyStaticFactory.class differ diff --git a/out/production/LiMe/com/lixin/lime/server/META-INF/MANIFEST.MF b/out/production/LiMe/com/lixin/lime/server/META-INF/MANIFEST.MF index 89af709..9887d74 100644 --- a/out/production/LiMe/com/lixin/lime/server/META-INF/MANIFEST.MF +++ b/out/production/LiMe/com/lixin/lime/server/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ -Manifest-Version: 0.5.2 +Manifest-Version: 0.6.0 Main-Class: com.lixin.lime.LiMeServer diff --git a/out/production/LiMe/com/lixin/lime/server/controller/LiMeServerController.class b/out/production/LiMe/com/lixin/lime/server/controller/LiMeServerController.class index c4c23d4..92b819d 100644 Binary files a/out/production/LiMe/com/lixin/lime/server/controller/LiMeServerController.class and b/out/production/LiMe/com/lixin/lime/server/controller/LiMeServerController.class differ diff --git a/out/production/LiMe/com/lixin/lime/server/controller/LiMeServerKnight.class b/out/production/LiMe/com/lixin/lime/server/controller/LiMeServerKnight.class index 46e2756..0b073d5 100644 Binary files a/out/production/LiMe/com/lixin/lime/server/controller/LiMeServerKnight.class and b/out/production/LiMe/com/lixin/lime/server/controller/LiMeServerKnight.class differ diff --git a/out/production/LiMe/com/lixin/lime/server/dao/MyDatabaseConnector.class b/out/production/LiMe/com/lixin/lime/server/dao/MyDatabaseConnector.class index 2f3053a..f570f9e 100644 Binary files a/out/production/LiMe/com/lixin/lime/server/dao/MyDatabaseConnector.class and b/out/production/LiMe/com/lixin/lime/server/dao/MyDatabaseConnector.class differ diff --git a/out/production/LiMe/com/lixin/lime/server/model/LiMeServerModel$ServerSeedGrinder.class b/out/production/LiMe/com/lixin/lime/server/model/LiMeServerModel$ServerSeedGrinder.class index 2305e19..3b9192c 100644 Binary files a/out/production/LiMe/com/lixin/lime/server/model/LiMeServerModel$ServerSeedGrinder.class and b/out/production/LiMe/com/lixin/lime/server/model/LiMeServerModel$ServerSeedGrinder.class differ diff --git a/out/production/LiMe/com/lixin/lime/server/model/LiMeServerModel.class b/out/production/LiMe/com/lixin/lime/server/model/LiMeServerModel.class index 6dad443..cf2be83 100644 Binary files a/out/production/LiMe/com/lixin/lime/server/model/LiMeServerModel.class and b/out/production/LiMe/com/lixin/lime/server/model/LiMeServerModel.class differ diff --git a/out/production/LiMe/com/lixin/lime/server/view/LiMeServerFrame.class b/out/production/LiMe/com/lixin/lime/server/view/LiMeServerFrame.class index 5791268..3f1706b 100644 Binary files a/out/production/LiMe/com/lixin/lime/server/view/LiMeServerFrame.class and b/out/production/LiMe/com/lixin/lime/server/view/LiMeServerFrame.class differ diff --git a/src/com/lixin/lime/client/META-INF/MANIFEST.MF b/src/com/lixin/lime/client/META-INF/MANIFEST.MF index 9a42dd6..500cc96 100644 --- a/src/com/lixin/lime/client/META-INF/MANIFEST.MF +++ b/src/com/lixin/lime/client/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ -Manifest-Version: 0.5.2 +Manifest-Version: 0.6.0 Main-Class: com.lixin.lime.LiMe diff --git a/src/com/lixin/lime/client/controller/LiMeController.java b/src/com/lixin/lime/client/controller/LiMeController.java index 3c2e322..a3d2ef1 100644 --- a/src/com/lixin/lime/client/controller/LiMeController.java +++ b/src/com/lixin/lime/client/controller/LiMeController.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.HashSet; +import static com.lixin.lime.protocol.seed.LiMeSeed.LIME_GROUP_CHAT; import static com.lixin.lime.protocol.util.factory.MyStaticFactory.*; /** @@ -65,7 +66,7 @@ public LiMeController() { private void initialize() { // 测试版本 try { - model = new LiMeModel(HOST, PORT, this); + model = new LiMeModel(HOST, PORT, this, this); initLoginFrame(); model.connectToServer(); } catch (LiMeException e) { @@ -93,6 +94,11 @@ private void initChatFrame() { chatFrame.getButtonLogout().addActionListener(this); chatFrame.getButtonSendFile().addActionListener(this); chatFrame.getButtonSendMessage().addActionListener(this); + + HashMap history = chatFrame.getHistory(); + history.put(LIME_GROUP_CHAT, ""); + // Update UI from history + chatFrame.updateTextAreaHistory(); } private void encryptAndWriteToFile(File file, String username, String password) { @@ -324,6 +330,9 @@ public void newFriendList(LiMeSeed seed) { } // Remove ex-friends from oldList for (String friend : friendList) { + if (friend.equals(LIME_GROUP_CHAT)) { + continue; + } if (!newFriendList.contains(friend)) { history.remove(friend); } @@ -382,7 +391,17 @@ public void handleLiMeException(LiMeException e) { } @Override - public void newGroupChat(String sender, String time, String message) { - + public void newGroupChat(LiMeSeed seed) { + if (seed.getSender().equals(username)) { + return; + } + LiMeSeedMessage seedMessage = (LiMeSeedMessage) seed; + String message = seedMessage.getMessage(); + String time = seedMessage.getTime(); + HashMap history = chatFrame.getHistory(); + String msgLog = history.get(LIME_GROUP_CHAT) + "< " + seed.getSender() + " > | < " + time + " >\n" + message + "\n\n"; + history.put(LIME_GROUP_CHAT, msgLog); + // Update UI from history + chatFrame.updateTextAreaHistory(); } } diff --git a/src/com/lixin/lime/client/controller/LiMeKnight.java b/src/com/lixin/lime/client/controller/LiMeKnight.java index 937941b..4865a39 100644 --- a/src/com/lixin/lime/client/controller/LiMeKnight.java +++ b/src/com/lixin/lime/client/controller/LiMeKnight.java @@ -1,5 +1,7 @@ package com.lixin.lime.client.controller; +import com.lixin.lime.protocol.seed.LiMeSeed; + /** * @author lixin */ @@ -7,9 +9,7 @@ public interface LiMeKnight { /** * 接收到新的信息,显示在屏幕上 * - * @param sender 发信方 - * @param time 时间戳 - * @param message 信息 + * @param seed 承载信息的 LiMeSeed */ - void newGroupChat(String sender, String time, String message); + void newGroupChat(LiMeSeed seed); } diff --git a/src/com/lixin/lime/client/model/LiMeModel.java b/src/com/lixin/lime/client/model/LiMeModel.java index 73c997e..ad24724 100644 --- a/src/com/lixin/lime/client/model/LiMeModel.java +++ b/src/com/lixin/lime/client/model/LiMeModel.java @@ -1,6 +1,7 @@ package com.lixin.lime.client.model; import com.lixin.lime.client.controller.LiMeFarmer; +import com.lixin.lime.client.controller.LiMeKnight; import com.lixin.lime.protocol.exception.LiMeException; import com.lixin.lime.protocol.seed.*; import com.lixin.lime.protocol.util.factory.LiMeExceptionFactory; @@ -23,6 +24,7 @@ public class LiMeModel { private String host; private int port; private LiMeFarmer farmer; + private LiMeKnight knight; private Socket socket; private ObjectOutputStream oos; @@ -38,10 +40,11 @@ public class LiMeModel { private ExecutorService cachedThreadPool; private LiMeExceptionFactory exceptionFactory; - public LiMeModel(String host, int port, LiMeFarmer farmer) { + public LiMeModel(String host, int port, LiMeFarmer farmer, LiMeKnight knight) { this.host = host; this.port = port; this.farmer = farmer; + this.knight = knight; cachedThreadPool = Executors.newCachedThreadPool(); exceptionFactory = new LiMeExceptionFactory(); } @@ -147,7 +150,11 @@ public void run() { // 被踢 throw exceptionFactory.newLiMeException(ERROR_ADMIN_KICKED); case MESSAGE: - farmer.newLiMeMessage(seed); + if (seed.getReceiver().equals(LIME_GROUP_CHAT)) { + knight.newGroupChat(seed); + } else { + farmer.newLiMeMessage(seed); + } break; case FRIENDS_UPDATE: farmer.newFriendList(seed); diff --git a/src/com/lixin/lime/protocol/seed/LiMeSeed.java b/src/com/lixin/lime/protocol/seed/LiMeSeed.java index 80e7091..fa1fbd7 100644 --- a/src/com/lixin/lime/protocol/seed/LiMeSeed.java +++ b/src/com/lixin/lime/protocol/seed/LiMeSeed.java @@ -51,6 +51,7 @@ public class LiMeSeed implements Serializable { public static final int STATUS_LOGIN_SUCCESS = 9; public static final int STATUS_REGISTER_SUCCESS = 10; + public static final String LIME_GROUP_CHAT = "[ LiMe Group Chat ]"; private int action; private String sender; diff --git a/src/com/lixin/lime/protocol/util/factory/MyStaticFactory.java b/src/com/lixin/lime/protocol/util/factory/MyStaticFactory.java index 4b3766c..39248ef 100644 --- a/src/com/lixin/lime/protocol/util/factory/MyStaticFactory.java +++ b/src/com/lixin/lime/protocol/util/factory/MyStaticFactory.java @@ -20,12 +20,12 @@ public class MyStaticFactory { public static final String THE_TITLE = "Lixin Messenger"; public static final String THE_BRAND = "LiMe"; public static final String THE_AUTHOR = "Lixin"; - public static final String THE_COPYRIGHT = "™ and © 2015-" + getLiMeYear() + " " + THE_AUTHOR + ". All Rights Reserved."; - public static final String THE_LIME_VERSION = "C_v 0.5.2"; + public static final String THE_COPYRIGHT = "™ and © 1997-" + getLiMeYear() + " " + THE_AUTHOR + ". All Rights Reserved."; + public static final String THE_LIME_VERSION = "C_v 0.6.0"; public static final String THE_SERVER_TITLE = THE_TITLE + " Server"; public static final String THE_SERVER_BRAND = THE_BRAND + " Server"; - public static final String THE_SERVER_VERSION = "S_v 0.5.2"; + public static final String THE_SERVER_VERSION = "S_v 0.6.0"; /** * The Actions diff --git a/src/com/lixin/lime/server/META-INF/MANIFEST.MF b/src/com/lixin/lime/server/META-INF/MANIFEST.MF index 89af709..9887d74 100644 --- a/src/com/lixin/lime/server/META-INF/MANIFEST.MF +++ b/src/com/lixin/lime/server/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ -Manifest-Version: 0.5.2 +Manifest-Version: 0.6.0 Main-Class: com.lixin.lime.LiMeServer diff --git a/src/com/lixin/lime/server/controller/LiMeServerController.java b/src/com/lixin/lime/server/controller/LiMeServerController.java index 0c349d4..7fa0375 100644 --- a/src/com/lixin/lime/server/controller/LiMeServerController.java +++ b/src/com/lixin/lime/server/controller/LiMeServerController.java @@ -1,5 +1,6 @@ package com.lixin.lime.server.controller; +import com.lixin.lime.protocol.seed.LiMeSeed; import com.lixin.lime.server.view.LiMeServerFrame; import com.lixin.lime.server.model.LiMeServerModel; @@ -35,7 +36,7 @@ public LiMeServerController() { */ private void initialize() { initServerFrame(); - serverModel = new LiMeServerModel(this); + serverModel = new LiMeServerModel(this, this); cachedThreadPool = Executors.newCachedThreadPool(); } @@ -112,8 +113,8 @@ public void enablePrivileges(boolean bool) { } @Override - public void newChatHistory(String sender, String time, String message) { - serverFrame.appendHistory("< " + sender + " > | < " + time + " >\n" + message + "\n"); + public void newChatHistory(LiMeSeed seed) { + serverFrame.appendHistory("< " + seed.getSender() + " > | < " + seed.getTime() + " >\n" + seed.getMessage() + "\n\n"); } } diff --git a/src/com/lixin/lime/server/controller/LiMeServerKnight.java b/src/com/lixin/lime/server/controller/LiMeServerKnight.java index dfea5b1..acda735 100644 --- a/src/com/lixin/lime/server/controller/LiMeServerKnight.java +++ b/src/com/lixin/lime/server/controller/LiMeServerKnight.java @@ -1,8 +1,15 @@ package com.lixin.lime.server.controller; +import com.lixin.lime.protocol.seed.LiMeSeed; + /** * @author lixin */ public interface LiMeServerKnight { - void newChatHistory(String sender, String time, String message); + /** + * 接收到新的信息,显示在屏幕上 + * + * @param seed 承载信息的 LiMeSeed + */ + void newChatHistory(LiMeSeed seed); } diff --git a/src/com/lixin/lime/server/dao/MyDatabaseConnector.java b/src/com/lixin/lime/server/dao/MyDatabaseConnector.java index e5fdde7..a42d501 100644 --- a/src/com/lixin/lime/server/dao/MyDatabaseConnector.java +++ b/src/com/lixin/lime/server/dao/MyDatabaseConnector.java @@ -13,7 +13,7 @@ public class MyDatabaseConnector { private Statement statement; private ResultSet resultSet; - public MyDatabaseConnector(String host, int port, String database, String username, String password) { + public MyDatabaseConnector(String host, int port, String database, String username, String password) throws SQLException { String url = "jdbc:mysql://" + host + ":" + port + "/" + database + "?" + "User=" + username + "&password=" + password + "&useUnicode=true&characterEncoding=UTF8&useSSL=true" + "&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC"; @@ -27,10 +27,6 @@ public MyDatabaseConnector(String host, int port, String database, String userna System.err.println("Database driver loading failure."); e.printStackTrace(); System.exit(0); - } catch (SQLException e) { - System.err.println("Database connection failure."); - e.printStackTrace(); - System.exit(0); } } diff --git a/src/com/lixin/lime/server/model/LiMeServerModel.java b/src/com/lixin/lime/server/model/LiMeServerModel.java index 1619c65..127b158 100644 --- a/src/com/lixin/lime/server/model/LiMeServerModel.java +++ b/src/com/lixin/lime/server/model/LiMeServerModel.java @@ -4,6 +4,7 @@ import com.lixin.lime.protocol.entity.User; import com.lixin.lime.protocol.seed.*; import com.lixin.lime.server.controller.LiMeServerFarmer; +import com.lixin.lime.server.controller.LiMeServerKnight; import com.lixin.lime.server.dao.MyDatabaseConnector; import com.lixin.lime.server.mailbox.LiMeServerMailBox; import com.lixin.lime.server.mailbox.MailAccountAliYun; @@ -33,15 +34,16 @@ public class LiMeServerModel implements Runnable { private HashMap limeHub; private LiMeServerFarmer serverFarmer; - private MyDatabaseConnector databaseConnector; + private LiMeServerKnight serverKnight; private Connection connection; private LiMeServerMailBox mailBox; private ExecutorService cachedThreadPool; - public LiMeServerModel(LiMeServerFarmer serverFarmer) { + public LiMeServerModel(LiMeServerFarmer serverFarmer, LiMeServerKnight serverKnight) { limeHub = new HashMap<>(); this.serverFarmer = serverFarmer; + this.serverKnight = serverKnight; cachedThreadPool = Executors.newCachedThreadPool(); } @@ -49,13 +51,13 @@ public LiMeServerModel(LiMeServerFarmer serverFarmer) { @Override public void run() { // init sql - databaseConnector = new MyDatabaseConnector(SQL_HOST, SQL_PORT, SQL_DATABASE, SQL_USERNAME, SQL_PASSWORD); - connection = databaseConnector.getConnection(); - mailBox = new LiMeServerMailBox( - new MailAccountAliYun(SERVER_EMAIL_USER, SERVER_EMAIL_DOMAIN, SERVER_EMAIL_PASSWORD) - ); - // init socket try { + MyDatabaseConnector databaseConnector = new MyDatabaseConnector(SQL_HOST, SQL_PORT, SQL_DATABASE, SQL_USERNAME, SQL_PASSWORD); + connection = databaseConnector.getConnection(); + mailBox = new LiMeServerMailBox( + new MailAccountAliYun(SERVER_EMAIL_USER, SERVER_EMAIL_DOMAIN, SERVER_EMAIL_PASSWORD) + ); + // init socket ServerSocket serverSock = new ServerSocket(PORT); while (true) { try { @@ -70,6 +72,10 @@ public void run() { ex.printStackTrace(); } } + } catch (SQLException e) { + System.err.println("Database connection failure."); + e.printStackTrace(); + limeInternalError(this.getClass().getCanonicalName(), THE_SERVER_BRAND + "连不上数据库"); } catch (Exception e) { e.printStackTrace(); } @@ -112,9 +118,14 @@ public void ban(String username) { private boolean verify(User user) { // Verify Login from Database[MySql Server] try { + String username = user.getUsername(); + // 不可与系统服务重名 + if (username.equals(LIME_GROUP_CHAT)) { + return false; + } PreparedStatement preparedStatement = connection.prepareStatement( "SELECT `password` FROM `users` WHERE `username` = ? AND `banned` = FALSE;"); - preparedStatement.setString(1, user.getUsername()); + preparedStatement.setString(1, username); ResultSet resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { return resultSet.getString(1).equals(user.getPassword()); @@ -131,6 +142,10 @@ private boolean register(User user) { // Register User to Database[MySql Server] try { String username = user.getUsername(); + // 不可与系统服务重名 + if (username.equals(LIME_GROUP_CHAT)) { + return false; + } PreparedStatement preparedStatement = connection.prepareStatement( "INSERT INTO `users`(`username`, `password`, `gender`, `email`) VALUES (?, ?, ?, ?);"); preparedStatement.setString(1, username); @@ -140,7 +155,7 @@ private boolean register(User user) { preparedStatement.executeUpdate(); String subject = "LiMe Register Success!"; String content = "Congratulations, " + username + "!\n" + - "You are new a new LiMe user now!"; + "You are a nobel LiMe user now!"; emailUser(username, subject, content); return true; } catch (SQLException e) { @@ -152,6 +167,10 @@ private boolean register(User user) { private void resetPassword(String username, String password) { // Update User's Password to Database[MySql Server] try { + // 不可与系统服务重名 + if (username.equals(LIME_GROUP_CHAT)) { + return; + } PreparedStatement preparedStatement = connection.prepareStatement( "UPDATE `users` SET `password` = ? WHERE `username` = ?;"); preparedStatement.setString(1, encrypt(password)); @@ -249,9 +268,20 @@ public void run() { switch (action) { case MESSAGE: LiMeSeedMessage seedMessage = (LiMeSeedMessage) seed; - LiMeStalk receiverStalk = limeHub.get(seedMessage.getReceiver()); - receiverStalk.getOos().writeObject(seedMessage); - receiverStalk.getOos().flush(); + String receiver = seedMessage.getReceiver(); + if (!receiver.equals(LIME_GROUP_CHAT)) { + LiMeStalk receiverStalk = limeHub.get(receiver); + receiverStalk.getOos().writeObject(seedMessage); + receiverStalk.getOos().flush(); + } else { + // 群发功能 + for (LiMeStalk stalk : limeHub.values()) { + stalk.getOos().writeObject(seedMessage); + stalk.getOos().flush(); + } + // Log Group Chat History + serverKnight.newChatHistory(seed); + } // 如果发生了 Exception 就表示用户掉线,则把用户从HashMap中踢掉 break; case LOGIN: @@ -302,9 +332,16 @@ public void run() { case FILE: // TODO: 这个版本直接转发,下个版本让两个用户建立独立链接 LiMeSeedFile seedFile = (LiMeSeedFile) seed; - LiMeStalk limeStalk = limeHub.get(seedFile.getReceiver()); - limeStalk.getOos().writeObject(seedFile); - limeStalk.getOos().flush(); + + String fileReceiver = seedFile.getReceiver(); + if (!fileReceiver.equals(LIME_GROUP_CHAT)) { + LiMeStalk limeStalk = limeHub.get(seedFile.getReceiver()); + limeStalk.getOos().writeObject(seedFile); + limeStalk.getOos().flush(); + } else { + // TODO: 下个版本允许群发文件 + System.out.println("Group File Request"); + } break; case FORGOT_PASSWORD: LiMeSeedRequest liMeSeedRequest = (LiMeSeedRequest) seed; diff --git a/src/com/lixin/lime/server/view/LiMeServerFrame.java b/src/com/lixin/lime/server/view/LiMeServerFrame.java index abb0b47..dd07b68 100644 --- a/src/com/lixin/lime/server/view/LiMeServerFrame.java +++ b/src/com/lixin/lime/server/view/LiMeServerFrame.java @@ -40,7 +40,7 @@ public class LiMeServerFrame extends JFrame implements ActionListener { public LiMeServerFrame() { setResizable(false); setTitle(THE_SERVER_TITLE); - setBounds(300, 140, 1080, 720); + setBounds(200, 140, 1280, 720); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); @@ -113,7 +113,7 @@ public void mouseClicked(MouseEvent e) { labelLog.setHorizontalAlignment(SwingConstants.CENTER); labelLog.setForeground(new Color(154, 154, 154)); labelLog.setFont(new Font("Harry P", Font.PLAIN, 99)); - labelLog.setBounds(342, 6, 397, 100); + labelLog.setBounds(342, 6, 417, 100); contentPane.add(labelLog); textAreaLog = new JTextArea(); @@ -123,28 +123,26 @@ public void mouseClicked(MouseEvent e) { textAreaLog.setEditable(false); JScrollPane scrollPaneLog = new JScrollPane(textAreaLog); scrollPaneLog.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - scrollPaneLog.setPreferredSize(new Dimension(832, 430)); - scrollPaneLog.setMinimumSize(new Dimension(832, 150)); - scrollPaneLog.setBounds(342, 119, 397, 506); + scrollPaneLog.setBounds(342, 119, 417, 506); contentPane.add(scrollPaneLog); buttonClearLog = new JButton("清空 Log"); buttonClearLog.setEnabled(false); buttonClearLog.setFont(new Font("PingFang SC", Font.PLAIN, 13)); - buttonClearLog.setBounds(342, 635, 397, 29); + buttonClearLog.setBounds(342, 635, 417, 29); buttonClearLog.setActionCommand(SERVER_ACTION_CLEAR_LOG); contentPane.add(buttonClearLog); JSeparator separatorRight = new JSeparator(); separatorRight.setOrientation(SwingConstants.VERTICAL); - separatorRight.setBounds(751, 6, 12, 658); + separatorRight.setBounds(771, 6, 12, 658); contentPane.add(separatorRight); labelHistory = new JLabel("Chat Log"); labelHistory.setHorizontalAlignment(SwingConstants.CENTER); labelHistory.setForeground(new Color(154, 154, 154)); labelHistory.setFont(new Font("Harry P", Font.PLAIN, 99)); - labelHistory.setBounds(775, 6, 300, 100); + labelHistory.setBounds(795, 6, 480, 100); contentPane.add(labelHistory); textAreaHistory = new JTextArea(); @@ -153,21 +151,19 @@ public void mouseClicked(MouseEvent e) { textAreaHistory.setEditable(false); JScrollPane scrollPaneGroup = new JScrollPane(textAreaHistory); scrollPaneGroup.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - scrollPaneGroup.setPreferredSize(new Dimension(832, 430)); - scrollPaneGroup.setMinimumSize(new Dimension(832, 150)); - scrollPaneGroup.setBounds(775, 119, 300, 505); + scrollPaneGroup.setBounds(795, 119, 480, 505); contentPane.add(scrollPaneGroup); buttonClearHistory = new JButton("清空群聊记录"); buttonClearHistory.setEnabled(false); buttonClearHistory.setFont(new Font("PingFang SC", Font.PLAIN, 13)); - buttonClearHistory.setBounds(775, 635, 300, 29); + buttonClearHistory.setBounds(795, 635, 480, 29); buttonClearHistory.setActionCommand(SERVER_ACTION_CLEAR_HISTORY); contentPane.add(buttonClearHistory); JLabel labelCopyright = new JLabel(THE_COPYRIGHT); labelCopyright.setForeground(new Color(154, 154, 154)); - labelCopyright.setBounds(392, 676, 296, 16); + labelCopyright.setBounds(492, 676, 296, 16); contentPane.add(labelCopyright); setFocusTraversalPolicy( diff --git a/testQuote.txt b/testQuote.txt new file mode 100644 index 0000000..86ad2b5 --- /dev/null +++ b/testQuote.txt @@ -0,0 +1,4 @@ +Fate Whispers To The Warrior, +“You Cannot Withstand This Storm” +And The Warrior Whispers Back, +“I Am The Storm” \ No newline at end of file