diff --git a/.hgignore b/.hgignore
index f7ef203151..02cf303401 100644
--- a/.hgignore
+++ b/.hgignore
@@ -24,9 +24,10 @@ Mage/target
syntax: regexp
.class
.jar
-.iml
-.ipr
-.iws
+.iml
+.ipr
+.iws
nbactions.xml
glob:Mage.Client/cheat.dck
glob:Mage.Client/test.dck
+glob:Mage.Server.Console/target/
diff --git a/Mage.Client/plugins/mage-counter-plugin.jar b/Mage.Client/plugins/mage-counter-plugin.jar
index 7114efce24..4cd8c3e86e 100644
Binary files a/Mage.Client/plugins/mage-counter-plugin.jar and b/Mage.Client/plugins/mage-counter-plugin.jar differ
diff --git a/Mage.Client/plugins/mage-theme-plugin.jar b/Mage.Client/plugins/mage-theme-plugin.jar
index 54a15502b1..575c757aa6 100644
Binary files a/Mage.Client/plugins/mage-theme-plugin.jar and b/Mage.Client/plugins/mage-theme-plugin.jar differ
diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml
index e9b4b4bfad..72b75d7104 100644
--- a/Mage.Client/pom.xml
+++ b/Mage.Client/pom.xml
@@ -97,6 +97,11 @@
0.1
runtime
+
+ ${project.groupId}
+ Mage-Common
+ ${project.version}
+
diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form
index 5354625cd3..9e18483966 100644
--- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form
+++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form
@@ -72,13 +72,11 @@
-
+
-
-
-
-
+
+
diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java
index aa6f1623ba..bcf680160b 100644
--- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java
+++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java
@@ -261,12 +261,11 @@ public class NewTournamentDialog extends MageDialog {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel5)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 57, Short.MAX_VALUE)
+ .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 59, Short.MAX_VALUE)
.addGap(11, 11, 11)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(spnNumPlayers)
- .addComponent(jLabel2))
+ .addComponent(spnNumPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 22, Short.MAX_VALUE)
+ .addComponent(jLabel2)
.addComponent(pnlDraftOptions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
diff --git a/Mage.Client/src/main/java/mage/client/remote/Session.java b/Mage.Client/src/main/java/mage/client/remote/Session.java
index b99bceeb7c..95ad65df90 100644
--- a/Mage.Client/src/main/java/mage/client/remote/Session.java
+++ b/Mage.Client/src/main/java/mage/client/remote/Session.java
@@ -37,8 +37,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
import javax.swing.JOptionPane;
import mage.cards.decks.DeckCardLists;
import mage.client.MageFrame;
@@ -61,6 +63,7 @@ import mage.view.GameTypeView;
import mage.view.TableView;
import mage.view.TournamentTypeView;
import mage.view.TournamentView;
+import org.apache.log4j.Logger;
/**
*
@@ -68,7 +71,8 @@ import mage.view.TournamentView;
*/
public class Session {
- private final static Logger logger = Logging.getLogger(Session.class.getName());
+ private final static Logger logger = Logger.getLogger(Session.class);
+ private static ScheduledExecutorService sessionExecutor = Executors.newScheduledThreadPool(1);
private UUID sessionId;
private Server server;
@@ -81,6 +85,7 @@ public class Session {
private Map drafts = new HashMap();
private Map tournaments = new HashMap();
private CallbackClientDaemon callbackDaemon;
+ private ScheduledFuture> future;
private MageUI ui = new MageUI();
public Session(MageFrame frame) {
@@ -112,20 +117,21 @@ public class Session {
sessionId = server.registerClient(userName, client.getId(), frame.getVersion());
callbackDaemon = new CallbackClientDaemon(sessionId, client, server);
serverState = server.getServerState();
+ future = sessionExecutor.scheduleWithFixedDelay(new ServerPinger(), 5, 5, TimeUnit.SECONDS);
logger.info("Connected to RMI server at " + serverName + ":" + port);
frame.setStatusText("Connected to " + serverName + ":" + port + " ");
frame.enableButtons();
return true;
} catch (MageException ex) {
- logger.log(Level.SEVERE, null, ex);
+ logger.fatal("", ex);
disconnect();
JOptionPane.showMessageDialog(frame, "Unable to connect to server. " + ex.getMessage());
} catch (RemoteException ex) {
- logger.log(Level.SEVERE, "Unable to connect to server - ", ex);
+ logger.fatal("Unable to connect to server - ", ex);
disconnect();
JOptionPane.showMessageDialog(frame, "Unable to connect to server. " + ex.getMessage());
} catch (NotBoundException ex) {
- logger.log(Level.SEVERE, "Unable to connect to server - ", ex);
+ logger.fatal("Unable to connect to server - ", ex);
}
return false;
}
@@ -134,7 +140,6 @@ public class Session {
if (isConnected()) {
try {
- frame.hideTables();
for (UUID chatId: chats.keySet()) {
server.leaveChat(chatId, sessionId);
}
@@ -145,18 +150,26 @@ public class Session {
try {
//TODO: stop daemon
server.deregisterClient(sessionId);
- server = null;
- logger.info("Disconnected ... ");
} catch (RemoteException ex) {
- logger.log(Level.SEVERE, "Error disconnecting ...", ex);
+ logger.fatal("Error disconnecting ...", ex);
} catch (MageException ex) {
- logger.log(Level.SEVERE, "Error disconnecting ...", ex);
+ logger.fatal("Error disconnecting ...", ex);
}
- frame.setStatusText("Not connected ");
- frame.disableButtons();
+ removeServer();
}
}
+ private void removeServer() {
+ if (future != null && !future.isDone())
+ future.cancel(true);
+ server = null;
+ frame.hideTables();
+ frame.setStatusText("Not connected");
+ frame.disableButtons();
+ logger.info("Disconnected ... ");
+ JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Disconnected.", "Disconnected", JOptionPane.INFORMATION_MESSAGE);
+ }
+
public void ack(String message) {
try {
server.ack(message, sessionId);
@@ -167,6 +180,17 @@ public class Session {
}
}
+ public boolean ping() {
+ try {
+ return server.ping(sessionId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
public boolean isConnected() {
return server != null;
}
@@ -717,26 +741,19 @@ public class Session {
}
private void handleRemoteException(RemoteException ex) {
- logger.log(Level.SEVERE, "Communication error", ex);
- if (ex instanceof java.rmi.ConnectException) {
- server = null;
- frame.setStatusText("Not connected");
- frame.disableButtons();
- JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Communication error - disconnecting.", "Error", JOptionPane.ERROR_MESSAGE);
- }
- else
- JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Communication error.", "Error", JOptionPane.ERROR_MESSAGE);
+ logger.fatal("Communication error", ex);
+ removeServer();
}
private void handleMageException(MageException ex) {
- logger.log(Level.SEVERE, "Server error", ex);
+ logger.fatal("Server error", ex);
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Critical server error. Disconnecting", "Error", JOptionPane.ERROR_MESSAGE);
disconnect();
frame.disableButtons();
}
private void handleGameException(GameException ex) {
- logger.log(Level.WARNING, "Game error", ex.getMessage());
+ logger.warn(ex.getMessage());
JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
@@ -752,5 +769,24 @@ public class Session {
public Server getServerRef() {
return server;
}
+
+ class ServerPinger implements Runnable {
+ private int missed = 0;
+
+ @Override
+ public void run() {
+ if (!ping()) {
+ missed++;
+ if (missed > 10) {
+ logger.info("Connection to server timed out");
+ removeServer();
+ }
+ }
+ else {
+ missed = 0;
+ }
+ }
+
+ }
}
\ No newline at end of file
diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java
index 4dac2f9091..bb2f03ca67 100644
--- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java
+++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java
@@ -190,10 +190,11 @@ public class TablesPanel extends javax.swing.JPanel {
}
public void hideTables() {
- if (tableWaitingDialog.isVisible()) {
+ if (tableWaitingDialog != null && tableWaitingDialog.isVisible()) {
tableWaitingDialog.closeDialog();
}
- updateTask.cancel(true);
+ if (updateTask != null)
+ updateTask.cancel(true);
this.chatPanel.disconnect();
Component c = this.getParent();
diff --git a/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.form b/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.form
index a7a2cba1d1..cf0e9c838d 100644
--- a/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.form
+++ b/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.form
@@ -21,7 +21,7 @@
-
+
@@ -78,11 +78,11 @@
-
+
-
+
diff --git a/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.java b/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.java
index ecf9485760..42fdffe889 100644
--- a/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.java
+++ b/Mage.Client/src/main/java/mage/client/table/TournamentPlayerPanel.java
@@ -116,11 +116,11 @@ public class TournamentPlayerPanel extends javax.swing.JPanel {
.addGroup(pnlPlayerNameLayout.createSequentialGroup()
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(cbLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(cbLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(txtPlayerName, javax.swing.GroupLayout.DEFAULT_SIZE, 225, Short.MAX_VALUE))
+ .addComponent(txtPlayerName, javax.swing.GroupLayout.DEFAULT_SIZE, 199, Short.MAX_VALUE))
);
pnlPlayerNameLayout.setVerticalGroup(
pnlPlayerNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -140,7 +140,7 @@ public class TournamentPlayerPanel extends javax.swing.JPanel {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(cbPlayerType, javax.swing.GroupLayout.PREFERRED_SIZE, 138, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(cbPlayerType, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pnlPlayerName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
diff --git a/Mage.Common/src/mage/interfaces/Server.java b/Mage.Common/src/mage/interfaces/Server.java
index e19e092301..852b9f0ded 100644
--- a/Mage.Common/src/mage/interfaces/Server.java
+++ b/Mage.Common/src/mage/interfaces/Server.java
@@ -42,6 +42,7 @@ import mage.view.DraftPickView;
import mage.view.TableView;
import mage.view.GameView;
import mage.view.TournamentView;
+import mage.view.UserView;
/**
*
@@ -50,8 +51,10 @@ import mage.view.TournamentView;
public interface Server extends Remote, CallbackServer {
public UUID registerClient(String userName, UUID clientId, MageVersion version) throws RemoteException, MageException;
+ public UUID registerAdmin(String password, MageVersion version) throws RemoteException, MageException;
public void deregisterClient(UUID sessionId) throws RemoteException, MageException;
public void ack(String message, UUID sessionId) throws RemoteException, MageException;
+ public boolean ping(UUID sessionId) throws RemoteException, MageException;
public ServerState getServerState() throws RemoteException, MageException;
@@ -116,4 +119,8 @@ public interface Server extends Remote, CallbackServer {
public void cheat(UUID gameId, UUID sessionId, UUID playerId, DeckCardLists deckList) throws RemoteException, MageException;
public boolean cheat(UUID gameId, UUID sessionId, UUID playerId, String cardName) throws RemoteException, MageException;
public GameView getGameView(UUID gameId, UUID sessionId, UUID playerId) throws RemoteException, MageException;
+
+ //admin methods
+ public List getUsers(UUID sessionId) throws RemoteException, MageException;
+
}
diff --git a/Mage.Common/src/mage/view/UserView.java b/Mage.Common/src/mage/view/UserView.java
new file mode 100644
index 0000000000..ef91e22892
--- /dev/null
+++ b/Mage.Common/src/mage/view/UserView.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.view;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ *
+ * @author BetaSteward_at_googlemail.com
+ */
+public class UserView implements Serializable {
+
+ private String userName;
+ private String host;
+ private UUID sessionId;
+ private Date timeConnected;
+
+ public UserView(String userName, String host, UUID sessionId, Date timeConnected) {
+ this.userName = userName;
+ this.host = host;
+ this.sessionId = sessionId;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public UUID getSessionId() {
+ return sessionId;
+ }
+
+ public Date getConnectionTime() {
+ return timeConnected;
+ }
+
+}
diff --git a/Mage.Server.Console/pom.xml b/Mage.Server.Console/pom.xml
new file mode 100644
index 0000000000..2fe1efb053
--- /dev/null
+++ b/Mage.Server.Console/pom.xml
@@ -0,0 +1,33 @@
+
+
+ 4.0.0
+
+ mage-root
+ org.mage
+ 0.7.2
+
+ org.mage
+ Mage.Server.Console
+ 0.8
+ Mage Server Console
+ http://maven.apache.org
+
+
+ junit
+ junit
+ 3.8.1
+ test
+
+
+ ${project.groupId}
+ Mage-Common
+ 0.7.2
+
+
+ org.swinglabs
+ swingx
+ 1.6.1
+
+
+
diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.form b/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.form
new file mode 100644
index 0000000000..1ee8b0374f
--- /dev/null
+++ b/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.form
@@ -0,0 +1,240 @@
+
+
+
diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.java b/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.java
new file mode 100644
index 0000000000..58a83b84fd
--- /dev/null
+++ b/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.java
@@ -0,0 +1,410 @@
+/*
+* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are
+* permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright notice, this list
+* of conditions and the following disclaimer in the documentation and/or other materials
+* provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* The views and conclusions contained in the software and documentation are those of the
+* authors and should not be interpreted as representing official policies, either expressed
+* or implied, of BetaSteward_at_googlemail.com.
+*/
+
+/*
+ * ConnectDialog.java
+ *
+ * Created on 20-Jan-2010, 9:37:07 PM
+ */
+
+package mage.server.console;
+
+import java.awt.Cursor;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+
+import org.apache.log4j.Logger;
+
+/**
+ *
+ * @author BetaSteward_at_googlemail.com
+ */
+public class ConnectDialog extends JDialog {
+
+ private final static Logger logger = Logger.getLogger(ConnectDialog.class);
+
+ private ConsoleFrame console;
+
+ /** Creates new form ConnectDialog */
+ public ConnectDialog() {
+ initComponents();
+ }
+
+ public void showDialog(ConsoleFrame console) {
+ this.console = console;
+ this.txtServer.setText(ConsoleFrame.getPreferences().get("serverAddress", ""));
+ this.txtPort.setText(ConsoleFrame.getPreferences().get("serverPort", ""));
+ this.chkAutoConnect.setSelected(Boolean.parseBoolean(ConsoleFrame.getPreferences().get("autoConnect", "false")));
+ this.txtProxyServer.setText(ConsoleFrame.getPreferences().get("proxyAddress", ""));
+ this.txtProxyPort.setText(ConsoleFrame.getPreferences().get("proxyPort", ""));
+ this.chkUseProxy.setSelected(Boolean.parseBoolean(ConsoleFrame.getPreferences().get("useProxy", "false")));
+ this.showProxySettings();
+ this.setModal(true);
+ this.setLocation(50, 50);
+ this.setVisible(true);
+ }
+
+ private void showProxySettings() {
+ if (chkUseProxy.isSelected()) {
+ this.pnlProxy.setVisible(true);
+ }
+ else {
+ this.pnlProxy.setVisible(false);
+ }
+ this.pack();
+// this.revalidate();
+ this.repaint();
+ }
+
+ private void saveSettings() {
+ ConsoleFrame.getPreferences().put("serverAddress", txtServer.getText());
+ ConsoleFrame.getPreferences().put("serverPort", txtPort.getText());
+ ConsoleFrame.getPreferences().put("autoConnect", Boolean.toString(chkAutoConnect.isSelected()));
+ ConsoleFrame.getPreferences().put("proxyAddress", txtProxyServer.getText());
+ ConsoleFrame.getPreferences().put("proxyPort", txtProxyPort.getText());
+ ConsoleFrame.getPreferences().put("useProxy", Boolean.toString(chkUseProxy.isSelected()));
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ txtServer = new javax.swing.JTextField();
+ lblServer = new javax.swing.JLabel();
+ lblPort = new javax.swing.JLabel();
+ txtPort = new javax.swing.JTextField();
+ txtPassword = new javax.swing.JTextField();
+ lblUserName = new javax.swing.JLabel();
+ btnConnect = new javax.swing.JButton();
+ btnCancel = new javax.swing.JButton();
+ chkAutoConnect = new javax.swing.JCheckBox();
+ chkUseProxy = new javax.swing.JCheckBox();
+ pnlProxy = new javax.swing.JPanel();
+ lblProxyServer = new javax.swing.JLabel();
+ txtProxyServer = new javax.swing.JTextField();
+ lblProxyPort = new javax.swing.JLabel();
+ txtProxyPort = new javax.swing.JTextField();
+ jButton1 = new javax.swing.JButton();
+
+ setTitle("Connect");
+
+ lblServer.setLabelFor(txtServer);
+ lblServer.setText("Server:");
+
+ lblPort.setLabelFor(txtPort);
+ lblPort.setText("Port:");
+
+ txtPort.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyTyped(java.awt.event.KeyEvent evt) {
+ ConnectDialog.this.keyTyped(evt);
+ }
+ });
+
+ lblUserName.setLabelFor(txtPassword);
+ lblUserName.setText("Password:");
+
+ btnConnect.setText("Connect");
+ btnConnect.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btnConnectActionPerformed(evt);
+ }
+ });
+
+ btnCancel.setText("Cancel");
+ btnCancel.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btnCancelActionPerformed(evt);
+ }
+ });
+
+ chkAutoConnect.setText("Automatically connect to this server next time");
+ chkAutoConnect.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ chkAutoConnectActionPerformed(evt);
+ }
+ });
+
+ chkUseProxy.setText("Use Proxy");
+ chkUseProxy.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ chkUseProxyActionPerformed(evt);
+ }
+ });
+
+ lblProxyServer.setLabelFor(txtServer);
+ lblProxyServer.setText("Server:");
+
+ lblProxyPort.setLabelFor(txtPort);
+ lblProxyPort.setText("Port:");
+
+ txtProxyPort.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyTyped(java.awt.event.KeyEvent evt) {
+ txtProxyPortkeyTyped(evt);
+ }
+ });
+
+ javax.swing.GroupLayout pnlProxyLayout = new javax.swing.GroupLayout(pnlProxy);
+ pnlProxy.setLayout(pnlProxyLayout);
+ pnlProxyLayout.setHorizontalGroup(
+ pnlProxyLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(pnlProxyLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(pnlProxyLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(lblProxyPort)
+ .addComponent(lblProxyServer))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(pnlProxyLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(txtProxyPort, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(txtProxyServer, javax.swing.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE))
+ .addGap(30, 30, 30))
+ );
+ pnlProxyLayout.setVerticalGroup(
+ pnlProxyLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(pnlProxyLayout.createSequentialGroup()
+ .addGroup(pnlProxyLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(lblProxyServer)
+ .addComponent(txtProxyServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(pnlProxyLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(lblProxyPort)
+ .addComponent(txtProxyPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ jButton1.setText("Find...");
+ jButton1.setToolTipText("Find public server");
+ jButton1.setName("findServerBtn"); // NOI18N
+ jButton1.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jButton1ActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(btnConnect)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(btnCancel))
+ .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(lblPort)
+ .addComponent(lblServer)
+ .addComponent(lblUserName))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(131, 131, 131))
+ .addComponent(txtPassword, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
+ .addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
+ .addComponent(chkUseProxy, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(txtServer, javax.swing.GroupLayout.DEFAULT_SIZE, 205, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jButton1)))))
+ .addContainerGap())
+ .addComponent(pnlProxy, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(lblServer)
+ .addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jButton1))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(lblPort))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(lblUserName))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(chkAutoConnect)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(chkUseProxy)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pnlProxy, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(btnCancel)
+ .addComponent(btnConnect))
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
+ ConsoleFrame.getPreferences().put("autoConnect", Boolean.toString(chkAutoConnect.isSelected()));
+ this.setVisible(false);
+ }//GEN-LAST:event_btnCancelActionPerformed
+
+ private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed
+
+ if (txtPassword.getText().isEmpty()) {
+ JOptionPane.showMessageDialog(rootPane, "Please provide a password");
+ return;
+ }
+ if (txtServer.getText().trim().isEmpty()) {
+ JOptionPane.showMessageDialog(rootPane, "Please provide a server address");
+ return;
+ }
+ if (txtPort.getText().trim().isEmpty()) {
+ JOptionPane.showMessageDialog(rootPane, "Please provide a port number");
+ return;
+ }
+ if (Integer.valueOf(txtPort.getText()) < 1 || Integer.valueOf(txtPort.getText()) > 65535 ) {
+ JOptionPane.showMessageDialog(rootPane, "Invalid port number");
+ txtPort.setText(ConsoleFrame.getPreferences().get("serverPort", ""));
+ return;
+ }
+
+ try {
+ setCursor(new Cursor(Cursor.WAIT_CURSOR));
+ if (chkUseProxy.isSelected()) {
+ if (console.connect(txtPassword.getText(), txtServer.getText().trim(), Integer.valueOf(txtPort.getText()), txtProxyServer.getText().trim(), Integer.valueOf(txtProxyPort.getText()))) {
+ this.saveSettings();
+ this.setVisible(false);
+ }
+ }
+ else {
+ if (console.connect(txtPassword.getText(), txtServer.getText().trim(), Integer.valueOf(txtPort.getText()))) {
+ this.saveSettings();
+ this.setVisible(false);
+ }
+ }
+ }
+ finally {
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
+
+ }//GEN-LAST:event_btnConnectActionPerformed
+
+ private void keyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_keyTyped
+ char c = evt.getKeyChar();
+ if (!Character.isDigit(c))
+ evt.consume();
+ }//GEN-LAST:event_keyTyped
+
+ private void chkAutoConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkAutoConnectActionPerformed
+
+ // TODO add your handling code here:
+ }//GEN-LAST:event_chkAutoConnectActionPerformed
+
+ private void txtProxyPortkeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtProxyPortkeyTyped
+ // TODO add your handling code here:
+ }//GEN-LAST:event_txtProxyPortkeyTyped
+
+ private void chkUseProxyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkUseProxyActionPerformed
+ this.showProxySettings();
+ }//GEN-LAST:event_chkUseProxyActionPerformed
+
+ private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
+ BufferedReader in = null;
+ try {
+ URL serverListURL = new URL("http://mage.googlecode.com/files/server-list.txt");
+ in = new BufferedReader(new InputStreamReader(serverListURL.openStream()));
+
+ List servers = new ArrayList();
+ String inputLine;
+ while ((inputLine = in.readLine()) != null) {
+ System.out.println("Found server: "+inputLine);
+ servers.add(inputLine);
+ }
+
+ if (servers.size() == 0) {
+ JOptionPane.showMessageDialog(null, "Couldn't find any server.");
+ return;
+ }
+
+ String selectedServer = (String) JOptionPane.showInputDialog(null,
+ "Choose MAGE Public Server:", "Input",
+ JOptionPane.INFORMATION_MESSAGE, null, servers.toArray(),
+ servers.get(0));
+ if (selectedServer != null) {
+ String[] params = selectedServer.split(":");
+ if (params.length == 3) {
+ this.txtServer.setText(params[1]);
+ this.txtPort.setText(params[2]);
+ } else {
+ JOptionPane.showMessageDialog(null, "Wrong server data format.");
+ }
+ }
+
+ in.close();
+ } catch(Exception ex) {
+ logger.error(ex,ex);
+ } finally {
+ if (in != null) try { in.close(); } catch (Exception e) {}
+ }
+
+ }//GEN-LAST:event_jButton1ActionPerformed
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton btnCancel;
+ private javax.swing.JButton btnConnect;
+ private javax.swing.JCheckBox chkAutoConnect;
+ private javax.swing.JCheckBox chkUseProxy;
+ private javax.swing.JButton jButton1;
+ private javax.swing.JLabel lblPort;
+ private javax.swing.JLabel lblProxyPort;
+ private javax.swing.JLabel lblProxyServer;
+ private javax.swing.JLabel lblServer;
+ private javax.swing.JLabel lblUserName;
+ private javax.swing.JPanel pnlProxy;
+ private javax.swing.JTextField txtPassword;
+ private javax.swing.JTextField txtPort;
+ private javax.swing.JTextField txtProxyPort;
+ private javax.swing.JTextField txtProxyServer;
+ private javax.swing.JTextField txtServer;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.form b/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.form
new file mode 100644
index 0000000000..950fd48075
--- /dev/null
+++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.form
@@ -0,0 +1,72 @@
+
+
+
diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.java b/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.java
new file mode 100644
index 0000000000..724ff143cb
--- /dev/null
+++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.java
@@ -0,0 +1,198 @@
+/*
+* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are
+* permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright notice, this list
+* of conditions and the following disclaimer in the documentation and/or other materials
+* provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* The views and conclusions contained in the software and documentation are those of the
+* authors and should not be interpreted as representing official policies, either expressed
+* or implied, of BetaSteward_at_googlemail.com.
+*/
+
+/*
+ * ConsoleFrame.java
+ *
+ * Created on May 13, 2011, 2:39:10 PM
+ */
+
+package mage.server.console;
+
+import java.util.logging.Level;
+import java.util.prefs.Preferences;
+import javax.swing.Box;
+import javax.swing.JOptionPane;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+import mage.server.console.remote.Session;
+import mage.utils.MageVersion;
+import org.apache.log4j.Logger;
+
+/**
+ *
+ * @author BetaSteward_at_googlemail.com
+ */
+public class ConsoleFrame extends javax.swing.JFrame {
+
+ private final static Logger logger = Logger.getLogger(ConsoleFrame.class);
+
+ private static Session session;
+ private ConnectDialog connectDialog;
+ private static Preferences prefs = Preferences.userNodeForPackage(ConsoleFrame.class);
+ private final static MageVersion version = new MageVersion(0, 7, 2);
+
+ /**
+ * @return the session
+ */
+ public static Session getSession() {
+ return session;
+ }
+
+ public static Preferences getPreferences() {
+ return prefs;
+ }
+
+ public static MageVersion getVersion() {
+ return version;
+ }
+
+ /** Creates new form ConsoleFrame */
+ public ConsoleFrame() {
+ initComponents();
+ try {
+ UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
+ session = new Session(this);
+ connectDialog = new ConnectDialog();
+ } catch (Exception ex) {
+ logger.fatal("", ex);
+ }
+ }
+
+ public boolean connect(String password, String serverName, int port) {
+ if (session.connect(password, serverName, port)) {
+ this.consolePanel1.start();
+ return true;
+ }
+ return false;
+ }
+
+ public boolean connect(String password, String serverName, int port, String proxyServer, int proxyPort) {
+ if (session.connect(password, serverName, port, proxyServer, proxyPort)) {
+ this.consolePanel1.start();
+ return true;
+ }
+ return false;
+ }
+
+ public void setStatusText(String status) {
+ this.lblStatus.setText(status);
+ }
+
+ public void enableButtons() {
+ btnConnect.setEnabled(true);
+ btnConnect.setText("Disconnect");
+ }
+
+ public void disableButtons() {
+ btnConnect.setEnabled(true);
+ btnConnect.setText("Connect");
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jToolBar1 = new javax.swing.JToolBar();
+ btnConnect = new javax.swing.JButton();
+ lblStatus = new javax.swing.JLabel();
+ consolePanel1 = new mage.server.console.ConsolePanel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+
+ jToolBar1.setFloatable(false);
+ jToolBar1.setRollover(true);
+
+ btnConnect.setText("Connect");
+ btnConnect.setFocusable(false);
+ btnConnect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
+ btnConnect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
+ btnConnect.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btnConnectActionPerformed(evt);
+ }
+ });
+ jToolBar1.add(btnConnect);
+
+ lblStatus.setText("Not Connected");
+ jToolBar1.add(Box.createHorizontalGlue());
+ jToolBar1.add(lblStatus);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 933, Short.MAX_VALUE)
+ .addComponent(consolePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 933, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, 0)
+ .addComponent(consolePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 432, Short.MAX_VALUE))
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed
+ if (session.isConnected()) {
+ if (JOptionPane.showConfirmDialog(this, "Are you sure you want to disconnect?", "Confirm disconnect", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
+ this.consolePanel1.stop();
+ session.disconnect();
+ }
+ } else {
+ connectDialog.showDialog(this);
+ }
+ }//GEN-LAST:event_btnConnectActionPerformed
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+ java.awt.EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ new ConsoleFrame().setVisible(true);
+ }
+ });
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton btnConnect;
+ private mage.server.console.ConsolePanel consolePanel1;
+ private javax.swing.JToolBar jToolBar1;
+ private javax.swing.JLabel lblStatus;
+ // End of variables declaration//GEN-END:variables
+
+}
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
new file mode 100644
index 0000000000..f709629d2b
--- /dev/null
+++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.form
@@ -0,0 +1,219 @@
+
+
+
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
new file mode 100644
index 0000000000..b1259c4831
--- /dev/null
+++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java
@@ -0,0 +1,423 @@
+/*
+* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are
+* permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright notice, this list
+* of conditions and the following disclaimer in the documentation and/or other materials
+* provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* The views and conclusions contained in the software and documentation are those of the
+* authors and should not be interpreted as representing official policies, either expressed
+* or implied, of BetaSteward_at_googlemail.com.
+*/
+
+/*
+ * ConsolePanel.java
+ *
+ * Created on 14-May-2011, 6:08:48 PM
+ */
+package mage.server.console;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+import javax.swing.SwingWorker;
+import javax.swing.table.AbstractTableModel;
+import mage.server.console.remote.Session;
+import mage.view.TableView;
+import mage.view.UserView;
+
+/**
+ *
+ * @author BetaSteward_at_googlemail.com
+ */
+public class ConsolePanel extends javax.swing.JPanel {
+
+ private TableUserModel tableUserModel;
+ private TableTableModel tableTableModel;
+ private UpdateUsersTask updateUsersTask;
+ private UpdateTablesTask updateTablesTask;
+
+ /** Creates new form ConsolePanel */
+ public ConsolePanel() {
+ this.tableUserModel = new TableUserModel();
+ this.tableTableModel = new TableTableModel();
+ initComponents();
+ this.tblUsers.createDefaultColumnsFromModel();
+ this.tblTables.createDefaultColumnsFromModel();
+ }
+
+ public void update(List users) {
+ int row = this.tblUsers.getSelectedRow();
+ tableUserModel.loadData(users);
+ this.tblUsers.repaint();
+ this.tblUsers.getSelectionModel().setSelectionInterval(row, row);
+ }
+
+ public void update(Collection tables) {
+ int row = this.tblTables.getSelectedRow();
+ tableTableModel.loadData(tables);
+ this.tblTables.repaint();
+ this.tblTables.getSelectionModel().setSelectionInterval(row, row);
+ }
+
+
+ public void start() {
+ updateUsersTask = new UpdateUsersTask(ConsoleFrame.getSession(), this);
+ updateTablesTask = new UpdateTablesTask(ConsoleFrame.getSession(), ConsoleFrame.getSession().getMainRoomId(), this);
+ updateUsersTask.execute();
+ updateTablesTask.execute();
+ }
+
+ public void stop() {
+ if (updateUsersTask != null && !updateUsersTask.isDone())
+ updateUsersTask.cancel(true);
+ if (updateTablesTask != null && !updateTablesTask.isDone())
+ updateTablesTask.cancel(true);
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jSplitPane1 = new javax.swing.JSplitPane();
+ jPanel1 = new javax.swing.JPanel();
+ jPanel3 = new javax.swing.JPanel();
+ jScrollPane1 = new javax.swing.JScrollPane();
+ tblUsers = new javax.swing.JTable();
+ jPanel4 = new javax.swing.JPanel();
+ btnDisconnect = 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();
+
+ jSplitPane1.setDividerLocation(250);
+ jSplitPane1.setResizeWeight(0.5);
+
+ tblUsers.setModel(tableUserModel);
+ jScrollPane1.setViewportView(tblUsers);
+
+ javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
+ jPanel3.setLayout(jPanel3Layout);
+ jPanel3Layout.setHorizontalGroup(
+ jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE)
+ );
+ jPanel3Layout.setVerticalGroup(
+ jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE)
+ );
+
+ jPanel4.setVerifyInputWhenFocusTarget(false);
+
+ btnDisconnect.setText("Disconnect");
+
+ 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))
+ );
+ jPanel4Layout.setVerticalGroup(
+ jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel4Layout.createSequentialGroup()
+ .addComponent(btnDisconnect)
+ .addContainerGap(10, Short.MAX_VALUE))
+ );
+
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
+ .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGap(0, 0, 0)
+ .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE))
+ );
+
+ jSplitPane1.setLeftComponent(jPanel1);
+
+ tblTables.setModel(tableTableModel);
+ jScrollPane2.setViewportView(tblTables);
+
+ javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
+ jPanel5.setLayout(jPanel5Layout);
+ jPanel5Layout.setHorizontalGroup(
+ jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 306, Short.MAX_VALUE)
+ );
+ jPanel5Layout.setVerticalGroup(
+ jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE)
+ );
+
+ btnDelete.setText("Remove");
+
+ javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
+ jPanel6.setLayout(jPanel6Layout);
+ jPanel6Layout.setHorizontalGroup(
+ jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel6Layout.createSequentialGroup()
+ .addComponent(btnDelete)
+ .addContainerGap(235, Short.MAX_VALUE))
+ );
+ jPanel6Layout.setVerticalGroup(
+ jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel6Layout.createSequentialGroup()
+ .addComponent(btnDelete)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
+ jPanel2.setLayout(jPanel2Layout);
+ 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)
+ );
+ jPanel2Layout.setVerticalGroup(
+ jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
+ .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGap(0, 0, 0)
+ .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ );
+
+ jSplitPane1.setRightComponent(jPanel2);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 562, Short.MAX_VALUE)
+ );
+ 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)
+ );
+ }// //GEN-END:initComponents
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton btnDelete;
+ private javax.swing.JButton btnDisconnect;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JPanel jPanel2;
+ private javax.swing.JPanel jPanel3;
+ private javax.swing.JPanel jPanel4;
+ private javax.swing.JPanel jPanel5;
+ private javax.swing.JPanel jPanel6;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JScrollPane jScrollPane2;
+ private javax.swing.JSplitPane jSplitPane1;
+ private javax.swing.JTable tblTables;
+ private javax.swing.JTable tblUsers;
+ // End of variables declaration//GEN-END:variables
+}
+
+class TableUserModel extends AbstractTableModel {
+ private String[] columnNames = new String[]{"User Name", "Host", "Time Connected"};
+ private UserView[] users = new UserView[0];
+
+ public void loadData(List users) {
+ this.users = users.toArray(new UserView[0]);
+ this.fireTableDataChanged();
+ }
+
+ @Override
+ public int getRowCount() {
+ return users.length;
+ }
+
+ @Override
+ public int getColumnCount() {
+ return columnNames.length;
+ }
+
+ @Override
+ public Object getValueAt(int arg0, int arg1) {
+ switch (arg1) {
+ case 0:
+ return users[arg0].getUserName();
+ case 1:
+ return users[arg0].getHost();
+ case 2:
+ return users[arg0].getConnectionTime().toString();
+ case 3:
+ return users[arg0].getSessionId();
+ }
+ return "";
+ }
+
+ @Override
+ public String getColumnName(int columnIndex) {
+ String colName = "";
+
+ if (columnIndex <= getColumnCount())
+ colName = columnNames[columnIndex];
+
+ return colName;
+ }
+
+ @Override
+ public Class getColumnClass(int columnIndex){
+ return String.class;
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+
+}
+
+class TableTableModel extends AbstractTableModel {
+ private String[] columnNames = new String[]{"Table Name", "Owner", "Game Type", "Deck Type", "Status"};
+ private TableView[] tables = new TableView[0];
+
+
+ public void loadData(Collection tables) {
+ this.tables = tables.toArray(new TableView[0]);
+ this.fireTableDataChanged();
+ }
+
+ @Override
+ public int getRowCount() {
+ return tables.length;
+ }
+
+ @Override
+ public int getColumnCount() {
+ return columnNames.length;
+ }
+
+ @Override
+ public Object getValueAt(int arg0, int arg1) {
+ switch (arg1) {
+ case 0:
+ return tables[arg0].getTableName();
+ case 1:
+ return tables[arg0].getControllerName();
+ case 2:
+ return tables[arg0].getGameType().toString();
+ case 3:
+ return tables[arg0].getDeckType().toString();
+ case 4:
+ return tables[arg0].getTableState().toString();
+ case 5:
+ return tables[arg0].isTournament();
+ case 6:
+ if (!tables[arg0].getGames().isEmpty())
+ return tables[arg0].getGames().get(0);
+ return null;
+ case 7:
+ return tables[arg0].getTableId();
+ }
+ return "";
+ }
+
+ @Override
+ public String getColumnName(int columnIndex) {
+ String colName = "";
+
+ if (columnIndex <= getColumnCount())
+ colName = columnNames[columnIndex];
+
+ return colName;
+ }
+
+ @Override
+ public Class getColumnClass(int columnIndex){
+ return String.class;
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ if (columnIndex != 5)
+ return false;
+ return true;
+ }
+
+}
+
+class UpdateUsersTask extends SwingWorker> {
+
+ private Session session;
+ private ConsolePanel panel;
+
+ UpdateUsersTask(Session session, ConsolePanel panel) {
+ this.session = session;
+ this.panel = panel;
+ }
+
+ @Override
+ protected Void doInBackground() throws Exception {
+ while (!isCancelled()) {
+ this.publish(session.getUsers());
+ Thread.sleep(1000);
+ }
+ return null;
+ }
+
+ @Override
+ protected void process(List> view) {
+ panel.update(view.get(0));
+ }
+
+}
+
+class UpdateTablesTask extends SwingWorker> {
+
+ private Session session;
+ private UUID roomId;
+ private ConsolePanel panel;
+
+ UpdateTablesTask(Session session, UUID roomId, ConsolePanel panel) {
+ this.session = session;
+ this.roomId = roomId;
+ this.panel = panel;
+ }
+
+ @Override
+ protected Void doInBackground() throws Exception {
+ while (!isCancelled()) {
+ this.publish(session.getTables(roomId));
+ Thread.sleep(1000);
+ }
+ return null;
+ }
+
+ @Override
+ protected void process(List> view) {
+ panel.update(view.get(0));
+ }
+
+}
\ No newline at end of file
diff --git a/Mage.Server.Console/src/main/java/mage/server/console/remote/Session.java b/Mage.Server.Console/src/main/java/mage/server/console/remote/Session.java
new file mode 100644
index 0000000000..4b747911d5
--- /dev/null
+++ b/Mage.Server.Console/src/main/java/mage/server/console/remote/Session.java
@@ -0,0 +1,724 @@
+/*
+* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are
+* permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright notice, this list
+* of conditions and the following disclaimer in the documentation and/or other materials
+* provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* The views and conclusions contained in the software and documentation are those of the
+* authors and should not be interpreted as representing official policies, either expressed
+* or implied, of BetaSteward_at_googlemail.com.
+*/
+
+package mage.server.console.remote;
+
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import javax.swing.JOptionPane;
+import mage.cards.decks.DeckCardLists;
+import mage.game.GameException;
+import mage.interfaces.MageException;
+import mage.game.match.MatchOptions;
+import mage.game.tournament.TournamentOptions;
+import mage.interfaces.Server;
+import mage.interfaces.ServerState;
+import mage.server.console.ConsoleFrame;
+import mage.view.DraftPickView;
+import mage.view.GameTypeView;
+import mage.view.TableView;
+import mage.view.TournamentTypeView;
+import mage.view.TournamentView;
+import mage.view.UserView;
+import org.apache.log4j.Logger;
+
+/**
+ *
+ * @author BetaSteward_at_googlemail.com
+ */
+public class Session {
+
+ private final static Logger logger = Logger.getLogger(Session.class);
+ private static ScheduledExecutorService sessionExecutor = Executors.newScheduledThreadPool(1);
+
+ private UUID sessionId;
+ private Server server;
+ private ConsoleFrame frame;
+ private ServerState serverState;
+ private ScheduledFuture> future;
+
+ public Session(ConsoleFrame frame) {
+ this.frame = frame;
+ }
+ public boolean connect(String password, String serverName, int port) {
+ return connect(password, serverName, port, "", 0);
+ }
+
+ public boolean connect(String password, String serverName, int port, String proxyServer, int proxyPort) {
+ if (isConnected()) {
+ disconnect();
+ }
+ try {
+ System.setSecurityManager(null);
+ if (proxyServer.length() > 0) {
+ System.setProperty("socksProxyHost", proxyServer);
+ System.setProperty("socksProxyPort", Integer.toString(proxyPort));
+ }
+ else {
+ System.clearProperty("socksProxyHost");
+ System.clearProperty("socksProxyPort");
+ }
+ Registry reg = LocateRegistry.getRegistry(serverName, port);
+ this.server = (Server) reg.lookup("mage-server");
+ sessionId = server.registerAdmin(password, frame.getVersion());
+ serverState = server.getServerState();
+ future = sessionExecutor.scheduleWithFixedDelay(new ServerPinger(), 5, 5, TimeUnit.SECONDS);
+ logger.info("Connected to RMI server at " + serverName + ":" + port);
+ frame.setStatusText("Connected to " + serverName + ":" + port + " ");
+ frame.enableButtons();
+ return true;
+ } catch (MageException ex) {
+ logger.fatal("", ex);
+ disconnect();
+ JOptionPane.showMessageDialog(frame, "Unable to connect to server. " + ex.getMessage());
+ } catch (RemoteException ex) {
+ logger.fatal("Unable to connect to server - ", ex);
+ disconnect();
+ JOptionPane.showMessageDialog(frame, "Unable to connect to server. " + ex.getMessage());
+ } catch (NotBoundException ex) {
+ logger.fatal("Unable to connect to server - ", ex);
+ } catch (Exception ex) {
+ logger.fatal("Unable to connect to server - ", ex);
+ }
+ return false;
+ }
+
+ public void disconnect() {
+
+ if (isConnected()) {
+ try {
+ server.deregisterClient(sessionId);
+ } catch (RemoteException ex) {
+ logger.fatal("Error disconnecting ...", ex);
+ } catch (MageException ex) {
+ logger.fatal("Error disconnecting ...", ex);
+ }
+ removeServer();
+ }
+ }
+
+ public void removeServer() {
+ if (future != null && !future.isDone())
+ future.cancel(true);
+ server = null;
+ frame.setStatusText("Not connected");
+ frame.disableButtons();
+ logger.info("Disconnected ... ");
+ JOptionPane.showMessageDialog(frame, "Disconnected.", "Disconnected", JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ public void ack(String message) {
+ try {
+ server.ack(message, sessionId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ }
+
+ public boolean ping() {
+ try {
+ return server.ping(sessionId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean isConnected() {
+ return server != null;
+ }
+
+ public String[] getPlayerTypes() {
+ return serverState.getPlayerTypes();
+ }
+
+ public List getGameTypes() {
+ return serverState.getGameTypes();
+ }
+
+ public String[] getDeckTypes() {
+ return serverState.getDeckTypes();
+ }
+
+ public List getTournamentTypes() {
+ return serverState.getTournamentTypes();
+ }
+
+ public boolean isTestMode() {
+ if (serverState != null)
+ return serverState.isTestMode();
+ return false;
+ }
+
+ public UUID getMainRoomId() {
+ try {
+ return server.getMainRoomId();
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ public UUID getRoomChatId(UUID roomId) {
+ try {
+ return server.getRoomChatId(roomId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ public UUID getTableChatId(UUID tableId) {
+ try {
+ return server.getTableChatId(tableId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ public UUID getGameChatId(UUID gameId) {
+ try {
+ return server.getGameChatId(gameId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ public TableView getTable(UUID roomId, UUID tableId) {
+ try {
+ return server.getTable(roomId, tableId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ public boolean watchTable(UUID roomId, UUID tableId) {
+ try {
+ server.watchTable(sessionId, roomId, tableId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean joinTable(UUID roomId, UUID tableId, String playerName, String playerType, int skill, DeckCardLists deckList) {
+ try {
+ return server.joinTable(sessionId, roomId, tableId, playerName, playerType, skill, deckList);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ } catch (GameException ex) {
+ handleGameException(ex);
+ }
+ return false;
+ }
+
+ public boolean joinTournamentTable(UUID roomId, UUID tableId, String playerName, String playerType, int skill) {
+ try {
+ return server.joinTournamentTable(sessionId, roomId, tableId, playerName, playerType, skill);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ } catch (GameException ex) {
+ handleGameException(ex);
+ }
+ return false;
+ }
+
+ public Collection getTables(UUID roomId) throws Exception {
+ try {
+ return server.getTables(roomId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ throw new Exception();
+ } catch (MageException ex) {
+ handleMageException(ex);
+ throw new Exception();
+ }
+ }
+
+ public TournamentView getTournament(UUID tournamentId) throws Exception {
+ try {
+ return server.getTournament(tournamentId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ throw new Exception();
+ } catch (MageException ex) {
+ handleMageException(ex);
+ throw new Exception();
+ }
+ }
+
+ public UUID getTournamentChatId(UUID tournamentId) {
+ try {
+ return server.getTournamentChatId(tournamentId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ public boolean sendPlayerUUID(UUID gameId, UUID data) {
+ try {
+ server.sendPlayerUUID(gameId, sessionId, data);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean sendPlayerBoolean(UUID gameId, boolean data) {
+ try {
+ server.sendPlayerBoolean(gameId, sessionId, data);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean sendPlayerInteger(UUID gameId, int data) {
+ try {
+ server.sendPlayerInteger(gameId, sessionId, data);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean sendPlayerString(UUID gameId, String data) {
+ try {
+ server.sendPlayerString(gameId, sessionId, data);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public DraftPickView sendCardPick(UUID draftId, UUID cardId) {
+ try {
+ return server.sendCardPick(draftId, sessionId, cardId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ public boolean leaveChat(UUID chatId) {
+ try {
+ server.leaveChat(chatId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean sendChatMessage(UUID chatId, String message) {
+ try {
+ server.sendChatMessage(chatId, "", message);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean joinGame(UUID gameId) {
+ try {
+ server.joinGame(gameId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean joinDraft(UUID draftId) {
+ try {
+ server.joinDraft(draftId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean joinTournament(UUID tournamentId) {
+ try {
+ server.joinTournament(tournamentId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean watchGame(UUID gameId) {
+ try {
+ server.watchGame(gameId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean replayGame(UUID gameId) {
+ try {
+ server.replayGame(gameId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public TableView createTable(UUID roomId, MatchOptions matchOptions) {
+ try {
+ return server.createTable(sessionId, roomId, matchOptions);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ public TableView createTournamentTable(UUID roomId, TournamentOptions tournamentOptions) {
+ try {
+ return server.createTournamentTable(sessionId, roomId, tournamentOptions);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ public boolean isTableOwner(UUID roomId, UUID tableId) {
+ try {
+ return server.isTableOwner(sessionId, roomId, tableId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean removeTable(UUID roomId, UUID tableId) {
+ try {
+ server.removeTable(sessionId, roomId, tableId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean swapSeats(UUID roomId, UUID tableId, int seatNum1, int seatNum2) {
+ try {
+ server.swapSeats(sessionId, roomId, tableId, seatNum1, seatNum2);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean leaveTable(UUID roomId, UUID tableId) {
+ try {
+ server.leaveTable(sessionId, roomId, tableId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean startGame(UUID roomId, UUID tableId) {
+ try {
+ server.startMatch(sessionId, roomId, tableId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean startTournament(UUID roomId, UUID tableId) {
+ try {
+ server.startTournament(sessionId, roomId, tableId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean startChallenge(UUID roomId, UUID tableId, UUID challengeId) {
+ try {
+ server.startChallenge(sessionId, roomId, tableId, challengeId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean submitDeck(UUID tableId, DeckCardLists deck) {
+ try {
+ return server.submitDeck(sessionId, tableId, deck);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ } catch (GameException ex) {
+ handleGameException(ex);
+ }
+ return false;
+ }
+
+ public boolean concedeGame(UUID gameId) {
+ try {
+ server.concedeGame(gameId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean stopWatching(UUID gameId) {
+ try {
+ server.stopWatching(gameId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean startReplay(UUID gameId) {
+ try {
+ server.startReplay(gameId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean stopReplay(UUID gameId) {
+ try {
+ server.stopReplay(gameId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean nextPlay(UUID gameId) {
+ try {
+ server.nextPlay(gameId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean previousPlay(UUID gameId) {
+ try {
+ server.previousPlay(gameId, sessionId);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public boolean cheat(UUID gameId, UUID playerId, DeckCardLists deckList) {
+ try {
+ server.cheat(gameId, sessionId, playerId, deckList);
+ return true;
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return false;
+ }
+
+ public List getUsers() {
+ try {
+ return server.getUsers(sessionId);
+ } catch (RemoteException ex) {
+ handleRemoteException(ex);
+ } catch (MageException ex) {
+ handleMageException(ex);
+ }
+ return null;
+ }
+
+ private void handleRemoteException(RemoteException ex) {
+ logger.fatal("Communication error", ex);
+ if (ex instanceof java.rmi.ConnectException) {
+ server = null;
+ frame.setStatusText("Not connected");
+ frame.disableButtons();
+ JOptionPane.showMessageDialog(frame, "Communication error - disconnecting.", "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ else
+ JOptionPane.showMessageDialog(frame, "Communication error.", "Error", JOptionPane.ERROR_MESSAGE);
+ }
+
+ private void handleMageException(MageException ex) {
+ logger.fatal("Server error", ex);
+ JOptionPane.showMessageDialog(frame, "Critical server error. Disconnecting", "Error", JOptionPane.ERROR_MESSAGE);
+ disconnect();
+ frame.disableButtons();
+ }
+
+ private void handleGameException(GameException ex) {
+ logger.fatal("Game error", ex);
+ JOptionPane.showMessageDialog(frame, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+ }
+
+
+ public Server getServerRef() {
+ return server;
+ }
+
+ class ServerPinger implements Runnable {
+
+ private int missed = 0;
+
+ @Override
+ public void run() {
+ if (!ping()) {
+ missed++;
+ if (missed > 10) {
+ logger.info("Connection to server timed out");
+ removeServer();
+ }
+ }
+ else {
+ missed = 0;
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/Mage.Server.Console/src/test/java/mage/server/console/AppTest.java b/Mage.Server.Console/src/test/java/mage/server/console/AppTest.java
new file mode 100644
index 0000000000..2387d8bd34
--- /dev/null
+++ b/Mage.Server.Console/src/test/java/mage/server/console/AppTest.java
@@ -0,0 +1,38 @@
+package mage.server.console;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+ extends TestCase
+{
+ /**
+ * Create the test case
+ *
+ * @param testName name of the test case
+ */
+ public AppTest( String testName )
+ {
+ super( testName );
+ }
+
+ /**
+ * @return the suite of tests being tested
+ */
+ public static Test suite()
+ {
+ return new TestSuite( AppTest.class );
+ }
+
+ /**
+ * Rigourous Test :-)
+ */
+ public void testApp()
+ {
+ assertTrue( true );
+ }
+}
diff --git a/Mage.Server/config/log4j.properties b/Mage.Server/config/log4j.properties
index f1f6e4f3db..913fd6646f 100644
--- a/Mage.Server/config/log4j.properties
+++ b/Mage.Server/config/log4j.properties
@@ -5,7 +5,7 @@ log4j.rootLogger=debug, console, logfile
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%-5p [%d{yyyy-MM-dd HH:mm [ss:SSS]}] %C{1}[%t]: %m%n
-log4j.appender.console.Threshold=info
+log4j.appender.console.Threshold=debug
#file log
log4j.appender.logfile=org.apache.log4j.FileAppender
diff --git a/Mage.Server/plugins/mage-deck-constructed.jar b/Mage.Server/plugins/mage-deck-constructed.jar
index 3647989d7d..81226541ab 100644
Binary files a/Mage.Server/plugins/mage-deck-constructed.jar and b/Mage.Server/plugins/mage-deck-constructed.jar differ
diff --git a/Mage.Server/plugins/mage-deck-limited.jar b/Mage.Server/plugins/mage-deck-limited.jar
index b4ca904cc5..fa0f9315a6 100644
Binary files a/Mage.Server/plugins/mage-deck-limited.jar and b/Mage.Server/plugins/mage-deck-limited.jar differ
diff --git a/Mage.Server/plugins/mage-game-freeforall.jar b/Mage.Server/plugins/mage-game-freeforall.jar
index 3d3417fd44..57958820b0 100644
Binary files a/Mage.Server/plugins/mage-game-freeforall.jar and b/Mage.Server/plugins/mage-game-freeforall.jar differ
diff --git a/Mage.Server/plugins/mage-game-twoplayerduel.jar b/Mage.Server/plugins/mage-game-twoplayerduel.jar
index 0c6f838e0c..ddeeca8392 100644
Binary files a/Mage.Server/plugins/mage-game-twoplayerduel.jar and b/Mage.Server/plugins/mage-game-twoplayerduel.jar differ
diff --git a/Mage.Server/plugins/mage-tournament-booster-draft.jar b/Mage.Server/plugins/mage-tournament-booster-draft.jar
index 9b81b4c1bf..bbd0b228a5 100644
Binary files a/Mage.Server/plugins/mage-tournament-booster-draft.jar and b/Mage.Server/plugins/mage-tournament-booster-draft.jar differ
diff --git a/Mage.Server/plugins/mage-tournament-sealed.jar b/Mage.Server/plugins/mage-tournament-sealed.jar
index e4a8584a98..9c5b2d1903 100644
Binary files a/Mage.Server/plugins/mage-tournament-sealed.jar and b/Mage.Server/plugins/mage-tournament-sealed.jar differ
diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java
index 70a1d5d1d8..7255ce4ee4 100644
--- a/Mage.Server/src/main/java/mage/server/Main.java
+++ b/Mage.Server/src/main/java/mage/server/Main.java
@@ -28,7 +28,6 @@
package mage.server;
-import java.net.UnknownHostException;
import mage.server.util.PluginClassLoader;
import java.io.File;
import java.io.FilenameFilter;
@@ -60,6 +59,7 @@ public class Main {
private static Logger logger = Logger.getLogger(Main.class);
private final static String testModeArg = "-testMode=";
+ private final static String adminPasswordArg = "-adminPassword=";
private final static String pluginFolder = "plugins";
private static MageVersion version = new MageVersion(0, 7, 2);
@@ -88,14 +88,18 @@ public class Main {
DeckValidatorFactory.getInstance().addDeckType(plugin.getName(), loadPlugin(plugin));
}
boolean testMode = false;
+ String adminPassword = "";
for (String arg: args) {
if (arg.startsWith(testModeArg)) {
testMode = Boolean.valueOf(arg.replace(testModeArg, ""));
}
+ else if (arg.startsWith(adminPasswordArg)) {
+ adminPassword = arg.replace(adminPasswordArg, "");
+ }
}
Copier.setLoader(classLoader);
setServerAddress(config.getServerAddress());
- server = new ServerImpl(config.getPort(), config.getServerName(), testMode);
+ server = new ServerImpl(config.getPort(), config.getServerName(), testMode, adminPassword);
}
diff --git a/Mage.Server/src/main/java/mage/server/ServerImpl.java b/Mage.Server/src/main/java/mage/server/ServerImpl.java
index c40e3fecb0..bbae5591cc 100644
--- a/Mage.Server/src/main/java/mage/server/ServerImpl.java
+++ b/Mage.Server/src/main/java/mage/server/ServerImpl.java
@@ -62,6 +62,7 @@ import mage.view.DraftPickView;
import mage.view.GameView;
import mage.view.TableView;
import mage.view.TournamentView;
+import mage.view.UserView;
import org.apache.log4j.Logger;
/**
@@ -74,14 +75,16 @@ public class ServerImpl extends RemoteServer implements Server {
private static ExecutorService rmiExecutor = ThreadExecutor.getInstance().getRMIExecutor();
private boolean testMode;
+ private String password;
- public ServerImpl(int port, String name, boolean testMode) {
+ public ServerImpl(int port, String name, boolean testMode, String password) {
try {
System.setSecurityManager(null);
Registry reg = LocateRegistry.createRegistry(port);
Server stub = (Server) UnicastRemoteObject.exportObject(this, port);
reg.rebind(name, stub);
this.testMode = testMode;
+ this.password = password;
logger.info("Started MAGE server - listening on port " + port);
if (testMode)
logger.info("MAGE server running in test mode");
@@ -106,6 +109,16 @@ public class ServerImpl extends RemoteServer implements Server {
SessionManager.getInstance().getSession(sessionId).ack(message);
}
+ @Override
+ public boolean ping(UUID sessionId) {
+ Session session = SessionManager.getInstance().getSession(sessionId);
+ if (session != null) {
+ session.ping();
+ return true;
+ }
+ return false;
+ }
+
@Override
public UUID registerClient(String userName, UUID clientId, MageVersion version) throws MageException, RemoteException {
@@ -113,7 +126,7 @@ public class ServerImpl extends RemoteServer implements Server {
try {
if (version.compareTo(Main.getVersion()) != 0)
throw new MageException("Wrong client version " + version + ", expecting version " + Main.getVersion());
- sessionId = SessionManager.getInstance().createSession(userName, clientId);
+ sessionId = SessionManager.getInstance().createSession(userName, getClientHost(), clientId);
logger.info("User " + userName + " connected from " + getClientHost());
} catch (Exception ex) {
handleException(ex);
@@ -121,6 +134,22 @@ public class ServerImpl extends RemoteServer implements Server {
return sessionId;
}
+
+ @Override
+ public UUID registerAdmin(String password, MageVersion version) throws RemoteException, MageException {
+ UUID sessionId = null;
+ try {
+ if (version.compareTo(Main.getVersion()) != 0)
+ throw new MageException("Wrong client version " + version + ", expecting version " + Main.getVersion());
+ if (!password.equals(this.password))
+ throw new MageException("Wrong password");
+ sessionId = SessionManager.getInstance().createSession(getClientHost());
+ logger.info("Admin connected from " + getClientHost());
+ } catch (Exception ex) {
+ handleException(ex);
+ }
+ return sessionId;
+ }
@Override
public TableView createTable(UUID sessionId, UUID roomId, MatchOptions options) throws MageException {
@@ -236,7 +265,6 @@ public class ServerImpl extends RemoteServer implements Server {
return null;
}
-
@Override
public TableView getTable(UUID roomId, UUID tableId) throws MageException {
try {
@@ -258,8 +286,8 @@ public class ServerImpl extends RemoteServer implements Server {
Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) {
session.kill();
+ logger.info("Client deregistered ...");
}
- logger.info("Client deregistered ...");
}
}
);
@@ -812,4 +840,9 @@ public class ServerImpl extends RemoteServer implements Server {
return GameManager.getInstance().getGameView(gameId, sessionId, playerId);
}
+ @Override
+ public List getUsers(UUID sessionId) throws RemoteException, MageException {
+ return SessionManager.getInstance().getUsers(sessionId);
+ }
+
}
diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java
index 871d94ed4a..feb81ba83e 100644
--- a/Mage.Server/src/main/java/mage/server/Session.java
+++ b/Mage.Server/src/main/java/mage/server/Session.java
@@ -28,7 +28,7 @@
package mage.server;
-import java.util.logging.Level;
+import java.util.Date;
import java.util.UUID;
import mage.cards.decks.Deck;
import mage.interfaces.callback.CallbackServerSession;
@@ -48,14 +48,31 @@ public class Session {
private UUID sessionId;
private UUID clientId;
private String username;
+ private String host;
private int messageId = 0;
private String ackMessage;
+ private Date timeConnected;
+ private long lastPing;
+ private boolean isAdmin = false;
private final CallbackServerSession callback = new CallbackServerSession();
- public Session(String userName, UUID clientId) {
+ public Session(String userName, String host, UUID clientId) {
sessionId = UUID.randomUUID();
this.username = userName;
+ this.host = host;
this.clientId = clientId;
+ this.isAdmin = false;
+ this.timeConnected = new Date();
+ ping();
+ }
+
+ public Session(String host) {
+ sessionId = UUID.randomUUID();
+ this.username = "Admin";
+ this.host = host;
+ this.isAdmin = true;
+ this.timeConnected = new Date();
+ ping();
}
public UUID getId() {
@@ -137,4 +154,25 @@ public class Session {
return username;
}
+ public void ping() {
+ this.lastPing = System.currentTimeMillis();
+ if (logger.isTraceEnabled())
+ logger.trace("Ping received from" + username + ":" + sessionId);
+ }
+
+ public boolean stillAlive() {
+ return (System.currentTimeMillis() - lastPing) < 60000;
+ }
+
+ public boolean isAdmin() {
+ return isAdmin;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public Date getConnectionTime() {
+ return timeConnected;
+ }
}
diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java
index 2b5df343b3..597d498dcd 100644
--- a/Mage.Server/src/main/java/mage/server/SessionManager.java
+++ b/Mage.Server/src/main/java/mage/server/SessionManager.java
@@ -28,12 +28,17 @@
package mage.server;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import mage.interfaces.MageException;
+import mage.view.UserView;
import org.apache.log4j.Logger;
/**
@@ -44,11 +49,17 @@ public class SessionManager {
private final static Logger logger = Logger.getLogger(SessionManager.class);
private final static SessionManager INSTANCE = new SessionManager();
+ private static ScheduledExecutorService sessionExecutor;
public static SessionManager getInstance() {
return INSTANCE;
}
+ protected SessionManager() {
+ sessionExecutor = Executors.newScheduledThreadPool(1);
+ sessionExecutor.scheduleWithFixedDelay(new SessionChecker(), 30, 10, TimeUnit.SECONDS);
+ }
+
private ConcurrentHashMap sessions = new ConcurrentHashMap();
public Session getSession(UUID sessionId) {
@@ -56,7 +67,7 @@ public class SessionManager {
return sessions.get(sessionId);
}
- public UUID createSession(String userName, UUID clientId) throws MageException {
+ public UUID createSession(String userName, String host, UUID clientId) throws MageException {
for (Session session: sessions.values()) {
if (session.getUsername().equals(userName)) {
if (session.getClientId().equals(clientId)) {
@@ -68,16 +79,32 @@ public class SessionManager {
}
}
}
- Session session = new Session(userName, clientId);
+ Session session = new Session(userName, host, clientId);
sessions.put(session.getId(), session);
logger.info("Session " + session.getId() + " created for user " + userName);
return session.getId();
}
+ public UUID createSession(String host) throws MageException {
+ Session session = new Session(host);
+ sessions.put(session.getId(), session);
+ logger.info("Admin session created");
+ return session.getId();
+ }
+
public void removeSession(UUID sessionId) {
sessions.remove(sessionId);
}
+ public void checkSessions() {
+ for (Session session: sessions.values()) {
+ if (!session.stillAlive()) {
+ logger.info("Client for user " + session.getUsername() + ":" + session.getId() + " timed out - releasing resources");
+ session.kill();
+ }
+ }
+ }
+
public Map getSessions() {
Map map = new HashMap();
for (Map.Entry entry : sessions.entrySet()) {
@@ -85,4 +112,25 @@ public class SessionManager {
}
return map;
}
+
+ List getUsers(UUID sessionId) {
+ List users = new ArrayList();
+ Session admin = sessions.get(sessionId);
+ if (admin != null && admin.isAdmin()) {
+ for (Session session: sessions.values()) {
+ users.add(new UserView(session.getUsername(), session.getHost(), session.getId(), session.getConnectionTime()));
+ }
+ }
+ return users;
+ }
+
+ class SessionChecker implements Runnable {
+
+ @Override
+ public void run() {
+ checkSessions();
+ }
+
+ }
+
}
diff --git a/Mage.Server/src/main/resources/log4j.properties b/Mage.Server/src/main/resources/log4j.properties
index cdef4d6b9e..08d7f0e74f 100644
--- a/Mage.Server/src/main/resources/log4j.properties
+++ b/Mage.Server/src/main/resources/log4j.properties
@@ -1,5 +1,5 @@
#default levels
-log4j.rootLogger=info, console
+log4j.rootLogger=debug, console
#console log
log4j.appender.console=org.apache.log4j.ConsoleAppender
diff --git a/Mage.Tests/plugins/AIMinimax.properties b/Mage.Tests/plugins/AIMinimax.properties
index 0dbf3860df..16ddf022c0 100644
--- a/Mage.Tests/plugins/AIMinimax.properties
+++ b/Mage.Tests/plugins/AIMinimax.properties
@@ -4,4 +4,4 @@ evaluatorLifeFactor=2
evaluatorPermanentFactor=1
evaluatorCreatureFactor=1
evaluatorHandFactor=1
-maxThinkSeconds=30
\ No newline at end of file
+maxThinkSeconds=10
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java
index 31c49f0852..d4987b7675 100644
--- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java
@@ -96,7 +96,7 @@ public abstract class MageTestBase {
@BeforeClass
public static void init() {
- Logger.getRootLogger().setLevel(Level.DEBUG);
+// Logger.getRootLogger().setLevel(Level.DEBUG);
logger.info("Starting MAGE tests");
logger.info("Logging level: " + logger.getLevel());
deleteSavedGames();
diff --git a/Mage.Tests/src/test/resources/log4j.properties b/Mage.Tests/src/test/resources/log4j.properties
index 605efa2a5e..71576f60a2 100644
--- a/Mage.Tests/src/test/resources/log4j.properties
+++ b/Mage.Tests/src/test/resources/log4j.properties
@@ -1,5 +1,5 @@
#default levels
-log4j.rootLogger=debug, console, file, watchdog
+log4j.rootLogger=info, console, file, watchdog
#console log
log4j.appender.console=org.apache.log4j.ConsoleAppender
diff --git a/Mage/src/mage/target/TargetObject.java b/Mage/src/mage/target/TargetObject.java
index b7be81f5fc..e813dac2a1 100644
--- a/Mage/src/mage/target/TargetObject.java
+++ b/Mage/src/mage/target/TargetObject.java
@@ -58,7 +58,7 @@ public abstract class TargetObject> extends TargetImpl
this.minNumberOfTargets = minNumTargets;
this.maxNumberOfTargets = maxNumTargets;
this.zone = zone;
- this.targetName = "card";
+ this.targetName = "object";
this.notTarget = notTarget;
}
diff --git a/pom.xml b/pom.xml
index a070a2754b..37325b8839 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,5 @@
-
+
4.0.0
@@ -31,6 +30,7 @@
Mage.Client
Mage.Plugins
Mage.Server.Plugins
+ Mage.Server.Console
Mage.Tests
@@ -62,4 +62,4 @@
0.7.2
-
+
\ No newline at end of file