diff --git a/Mage.Common/src/mage/interfaces/MageServer.java b/Mage.Common/src/mage/interfaces/MageServer.java index e9f38575c4..2886000ab2 100644 --- a/Mage.Common/src/mage/interfaces/MageServer.java +++ b/Mage.Common/src/mage/interfaces/MageServer.java @@ -146,6 +146,7 @@ public interface MageServer { //admin methods List getUsers(String sessionId) throws MageException; void disconnectUser(String sessionId, String userSessionId) throws MageException; + void endUserSession(String sessionId, String userSessionId) throws MageException; void removeTable(String sessionId, UUID tableId) throws MageException; void sendBroadcastMessage(String sessionId, String message) throws MageException; } diff --git a/Mage.Common/src/mage/remote/SessionImpl.java b/Mage.Common/src/mage/remote/SessionImpl.java index 13af7e29de..9176871de0 100644 --- a/Mage.Common/src/mage/remote/SessionImpl.java +++ b/Mage.Common/src/mage/remote/SessionImpl.java @@ -28,18 +28,6 @@ package mage.remote; -import java.net.Authenticator; -import java.net.ConnectException; -import java.net.MalformedURLException; -import java.net.PasswordAuthentication; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.MageException; import mage.cards.decks.DeckCardLists; import mage.cards.decks.InvalidDeckException; @@ -56,22 +44,9 @@ import mage.interfaces.MageServer; import mage.interfaces.ServerState; import mage.interfaces.callback.ClientCallback; import mage.utils.CompressUtil; -import mage.view.DraftPickView; -import mage.view.GameTypeView; -import mage.view.MatchView; -import mage.view.TableView; -import mage.view.TournamentTypeView; -import mage.view.TournamentView; -import mage.view.UserDataView; -import mage.view.UserView; -import mage.view.UsersView; +import mage.view.*; import org.apache.log4j.Logger; -import org.jboss.remoting.CannotConnectException; -import org.jboss.remoting.Client; -import org.jboss.remoting.ConnectionListener; -import org.jboss.remoting.ConnectionValidator; -import org.jboss.remoting.InvokerLocator; -import org.jboss.remoting.Remoting; +import org.jboss.remoting.*; import org.jboss.remoting.callback.Callback; import org.jboss.remoting.callback.HandleCallbackException; import org.jboss.remoting.callback.InvokerCallbackHandler; @@ -79,6 +54,9 @@ import org.jboss.remoting.transport.bisocket.Bisocket; import org.jboss.remoting.transport.socket.SocketWrapper; import org.jboss.remoting.transporter.TransporterClient; +import java.net.*; +import java.util.*; + /** * * @author BetaSteward_at_googlemail.com @@ -1244,6 +1222,21 @@ public class SessionImpl implements Session { return false; } + @Override + public boolean endUserSession(String userSessionId) { + try { + if (isConnected()) { + server.endUserSession(sessionId, userSessionId); + return true; + } + } catch (MageException ex) { + handleMageException(ex); + } catch (Throwable t) { + handleThrowable(t); + } + return false; + } + private void handleThrowable(Throwable t) { logger.fatal("Communication error", t); sessionState = SessionState.SERVER_UNAVAILABLE; diff --git a/Mage.Common/src/mage/remote/interfaces/Connect.java b/Mage.Common/src/mage/remote/interfaces/Connect.java index da736cd578..da4346a16b 100644 --- a/Mage.Common/src/mage/remote/interfaces/Connect.java +++ b/Mage.Common/src/mage/remote/interfaces/Connect.java @@ -27,7 +27,6 @@ */ package mage.remote.interfaces; -import java.util.UUID; import mage.remote.Connection; /** @@ -48,6 +47,8 @@ public interface Connect { boolean isConnected(); boolean disconnectUser(String userSessionId); - + + boolean endUserSession(String userSessionId); + String getSessionId(); } diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.form b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.form index f73700c30a..6bb32d56a2 100644 --- a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.form +++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.form @@ -1,4 +1,4 @@ - +
@@ -21,7 +21,7 @@ - + @@ -69,7 +69,7 @@ - + @@ -101,16 +101,21 @@ - - + + + + - - + + + + + @@ -124,6 +129,14 @@ + + + + + + + + @@ -139,7 +152,7 @@ - + @@ -163,7 +176,7 @@ - + @@ -192,27 +205,27 @@ - - + + - + - + - + - + diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java index ec2c355d90..7effc6d11a 100644 --- a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java +++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java @@ -33,18 +33,18 @@ */ package mage.server.console; +import mage.remote.Session; +import mage.view.TableView; +import mage.view.UserView; +import org.apache.log4j.Logger; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; -import javax.swing.SwingWorker; -import javax.swing.table.AbstractTableModel; - -import mage.remote.Session; -import mage.view.TableView; -import mage.view.UserView; -import org.apache.log4j.Logger; /** * @@ -113,12 +113,13 @@ public class ConsolePanel extends javax.swing.JPanel { tblUsers = new javax.swing.JTable(); jPanel4 = new javax.swing.JPanel(); btnDisconnect = new javax.swing.JButton(); + btnEndSession = new javax.swing.JButton(); jPanel2 = new javax.swing.JPanel(); jPanel5 = new javax.swing.JPanel(); jScrollPane2 = new javax.swing.JScrollPane(); tblTables = new javax.swing.JTable(); jPanel6 = new javax.swing.JPanel(); - btnDelete = new javax.swing.JButton(); + btnRemoveTable = new javax.swing.JButton(); jSplitPane1.setDividerLocation(250); jSplitPane1.setResizeWeight(0.5); @@ -134,7 +135,7 @@ public class ConsolePanel extends javax.swing.JPanel { ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 358, Short.MAX_VALUE) ); jPanel4.setVerifyInputWhenFocusTarget(false); @@ -146,19 +147,30 @@ public class ConsolePanel extends javax.swing.JPanel { } }); + btnEndSession.setText("End session"); + btnEndSession.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnEndSessionActionPerformed(evt); + } + }); + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); jPanel4.setLayout(jPanel4Layout); jPanel4Layout.setHorizontalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel4Layout.createSequentialGroup() - .addComponent(btnDisconnect) - .addContainerGap(164, Short.MAX_VALUE)) + .addComponent(btnDisconnect, javax.swing.GroupLayout.PREFERRED_SIZE, 103, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(btnEndSession) + .addContainerGap(8, Short.MAX_VALUE)) ); jPanel4Layout.setVerticalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel4Layout.createSequentialGroup() - .addComponent(btnDisconnect) - .addContainerGap(10, Short.MAX_VALUE)) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnDisconnect) + .addComponent(btnEndSession)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); @@ -189,13 +201,13 @@ public class ConsolePanel extends javax.swing.JPanel { ); jPanel5Layout.setVerticalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE) ); - btnDelete.setText("Remove"); - btnDelete.addActionListener(new java.awt.event.ActionListener() { + btnRemoveTable.setLabel("Remove Table"); + btnRemoveTable.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - btnDeleteActionPerformed(evt); + btnRemoveTableActionPerformed(evt); } }); @@ -204,13 +216,13 @@ public class ConsolePanel extends javax.swing.JPanel { jPanel6Layout.setHorizontalGroup( jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel6Layout.createSequentialGroup() - .addComponent(btnDelete) - .addContainerGap(235, Short.MAX_VALUE)) + .addComponent(btnRemoveTable) + .addContainerGap(170, Short.MAX_VALUE)) ); jPanel6Layout.setVerticalGroup( jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel6Layout.createSequentialGroup() - .addComponent(btnDelete) + .addComponent(btnRemoveTable) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); @@ -219,7 +231,7 @@ public class ConsolePanel extends javax.swing.JPanel { jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, 301, Short.MAX_VALUE) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -239,7 +251,7 @@ public class ConsolePanel extends javax.swing.JPanel { ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 395, Short.MAX_VALUE) + .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING) ); }// //GEN-END:initComponents @@ -248,14 +260,20 @@ public class ConsolePanel extends javax.swing.JPanel { ConsoleFrame.getSession().disconnectUser((String)tableUserModel.getValueAt(row, 3)); }//GEN-LAST:event_btnDisconnectActionPerformed - private void btnDeleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteActionPerformed + private void btnRemoveTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveTableActionPerformed int row = this.tblTables.getSelectedRow(); ConsoleFrame.getSession().removeTable((UUID)tableTableModel.getValueAt(row, 7)); - }//GEN-LAST:event_btnDeleteActionPerformed + }//GEN-LAST:event_btnRemoveTableActionPerformed + + private void btnEndSessionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEndSessionActionPerformed + int row = this.tblUsers.getSelectedRow(); + ConsoleFrame.getSession().endUserSession((String) tableUserModel.getValueAt(row, 3)); + }//GEN-LAST:event_btnEndSessionActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnDelete; private javax.swing.JButton btnDisconnect; + private javax.swing.JButton btnEndSession; + private javax.swing.JButton btnRemoveTable; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; @@ -399,6 +417,7 @@ class UpdateUsersTask extends SwingWorker> { private Session session; private ConsolePanel panel; + private List previousUsers; private static final Logger logger = Logger.getLogger(UpdateUsersTask.class); @@ -410,12 +429,42 @@ class UpdateUsersTask extends SwingWorker> { @Override protected Void doInBackground() throws Exception { while (!isCancelled()) { - this.publish(session.getUsers()); + List users = session.getUsers(); + if (previousUsers == null || checkUserListChanged(users)) { + logger.debug("Need to update the user list"); + this.publish(users); + previousUsers = users; + } Thread.sleep(1000); } return null; } + private boolean checkUserListChanged(List usersToCheck) { + if (previousUsers == null || usersToCheck == null) { + return true; + } + if (previousUsers.size() != usersToCheck.size()) { + // new user appeared + return true; + } + for (UserView u1 : previousUsers) { + boolean found = false; + for (UserView u2 : usersToCheck) { + if (u1.getUserName().equals(u2.getUserName())) { + found = true; + break; + } + } + if (!found) { + // some new user replaced old one + return true; + } + } + // seems nothing has been changed + return false; + } + @Override protected void process(List> view) { panel.update(view.get(0)); diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index c62480f218..227a9dc1a0 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -28,11 +28,6 @@ package mage.server; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.UUID; -import java.util.concurrent.ExecutorService; import mage.MageException; import mage.cards.decks.DeckCardLists; import mage.cards.repository.CardInfo; @@ -51,13 +46,7 @@ import mage.interfaces.callback.ClientCallback; import mage.remote.MageVersionException; import mage.server.draft.CubeFactory; import mage.server.draft.DraftManager; -import mage.server.game.DeckValidatorFactory; -import mage.server.game.GameFactory; -import mage.server.game.GameManager; -import mage.server.game.GamesRoom; -import mage.server.game.GamesRoomManager; -import mage.server.game.PlayerFactory; -import mage.server.game.ReplayManager; +import mage.server.game.*; import mage.server.services.LogKeys; import mage.server.services.impl.FeedbackServiceImpl; import mage.server.services.impl.LogServiceImpl; @@ -66,23 +55,17 @@ import mage.server.tournament.TournamentManager; import mage.server.util.ConfigSettings; import mage.server.util.ServerMessagesUtil; import mage.server.util.ThreadExecutor; -import mage.utils.ActionWithBooleanResult; -import mage.utils.ActionWithNullNegativeResult; -import mage.utils.ActionWithTableViewResult; -import mage.utils.CompressUtil; -import mage.utils.MageVersion; -import mage.view.ChatMessage; +import mage.utils.*; +import mage.view.*; import mage.view.ChatMessage.MessageColor; -import mage.view.DraftPickView; -import mage.view.GameView; -import mage.view.MatchView; -import mage.view.TableView; -import mage.view.TournamentView; -import mage.view.UserDataView; -import mage.view.UserView; -import mage.view.UsersView; import org.apache.log4j.Logger; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.UUID; +import java.util.concurrent.ExecutorService; + /** * * @author BetaSteward_at_googlemail.com, noxx @@ -920,6 +903,16 @@ public class MageServerImpl implements MageServer { }); } + @Override + public void endUserSession(final String sessionId, final String userSessionId) throws MageException { + execute("endUserSession", sessionId, new Action() { + @Override + public void execute() { + SessionManager.getInstance().endUserSession(sessionId, userSessionId); + } + }); + } + @Override public void removeTable(final String sessionId, final UUID tableId) throws MageException { execute("removeTable", sessionId, new Action() { diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java index 8a06fdafef..7066fb77f7 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManager.java @@ -27,9 +27,6 @@ */ package mage.server; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import mage.MageException; import mage.server.services.LogKeys; import mage.server.services.impl.LogServiceImpl; @@ -37,6 +34,10 @@ import mage.view.UserDataView; import org.apache.log4j.Logger; import org.jboss.remoting.callback.InvokerCallbackHandler; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * * @author BetaSteward_at_googlemail.com @@ -134,6 +135,13 @@ public class SessionManager { } } + public void endUserSession(String sessionId, String userSessionId) { + if (isAdmin(sessionId)) { + disconnect(userSessionId, false); + LogServiceImpl.instance.log(LogKeys.KEY_SESSION_END_BY_ADMIN, sessionId, userSessionId); + } + } + public boolean isAdmin(String sessionId) { Session admin = sessions.get(sessionId); if (admin != null) { diff --git a/Mage.Server/src/main/java/mage/server/services/LogKeys.java b/Mage.Server/src/main/java/mage/server/services/LogKeys.java index 4a4593f42f..15090223dd 100644 --- a/Mage.Server/src/main/java/mage/server/services/LogKeys.java +++ b/Mage.Server/src/main/java/mage/server/services/LogKeys.java @@ -17,6 +17,8 @@ public interface LogKeys { String KEY_SESSION_DISCONNECTED_BY_ADMIN = "sessionDisconnectedByAdmin"; + String KEY_SESSION_END_BY_ADMIN = "sessionEndSessionByAdmin"; + String KEY_NOT_VALID_SESSION = "sessionNotValid"; String KEY_NOT_VALID_SESSION_INTERNAL = "sessionNotValidInternal";