diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java
index 6bac7c971ef..75bde3d85ec 100644
--- a/Mage.Client/src/main/java/mage/client/MageFrame.java
+++ b/Mage.Client/src/main/java/mage/client/MageFrame.java
@@ -712,7 +712,7 @@ public class MageFrame extends javax.swing.JFrame {
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) {
- session.disconnect();
+ session.disconnect(true);
}
} else {
connectDialog.showDialog();
@@ -726,7 +726,7 @@ public class MageFrame extends javax.swing.JFrame {
}//GEN-LAST:event_btnAboutActionPerformed
public void exitApp() {
- session.disconnect();
+ session.disconnect(true);
Plugins.getInstance().shutdown();
dispose();
System.exit(0);
diff --git a/Mage.Client/src/main/java/mage/client/dialog/ReconnectDialog.form b/Mage.Client/src/main/java/mage/client/dialog/ReconnectDialog.form
new file mode 100644
index 00000000000..22a1c40aacb
--- /dev/null
+++ b/Mage.Client/src/main/java/mage/client/dialog/ReconnectDialog.form
@@ -0,0 +1,56 @@
+
+
+
diff --git a/Mage.Client/src/main/java/mage/client/dialog/ReconnectDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ReconnectDialog.java
new file mode 100644
index 00000000000..efa5915d062
--- /dev/null
+++ b/Mage.Client/src/main/java/mage/client/dialog/ReconnectDialog.java
@@ -0,0 +1,167 @@
+/*
+* 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.
+*/
+
+/*
+ * ReconnectDialog.java
+ *
+ * Created on 20-May-2011, 2:39:21 PM
+ */
+package mage.client.dialog;
+
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.SwingWorker;
+import mage.client.remote.Session;
+
+/**
+ *
+ * @author BetaSteward_at_googlemail.com
+ */
+public class ReconnectDialog extends MageDialog {
+
+ private static final int MAX_ATTEMPTS = 3;
+ private boolean result = false;
+ private boolean cancel = false;
+ private ReconnectTask reconnectTask;
+
+ /** Creates new form ReconnectDialog */
+ public ReconnectDialog() {
+ initComponents();
+ }
+
+ public void showDialog(Session session) {
+ result = false;
+ cancel = false;
+ reconnectTask = new ReconnectTask(session, this);
+ reconnectTask.execute();
+ this.setModal(true);
+ this.setLocation(100, 100);
+ this.setVisible(true);
+ }
+
+ public void closeDialog() {
+ if (reconnectTask != null) reconnectTask.cancel(true);
+ this.setVisible(false);
+ }
+
+ public void update(String message) {
+ this.jLabel1.setText(message);
+ }
+
+ public boolean getResult() {
+ return result;
+ }
+
+ /** 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() {
+
+ jLabel1 = new javax.swing.JLabel();
+ btnCancel = new javax.swing.JButton();
+
+ btnCancel.setText("Cancel");
+ btnCancel.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btnCancelActionPerformed(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, false)
+ .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 309, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(btnCancel, javax.swing.GroupLayout.Alignment.TRAILING))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 14, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(btnCancel)
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
+ this.cancel = true;
+ closeDialog();
+ }//GEN-LAST:event_btnCancelActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton btnCancel;
+ private javax.swing.JLabel jLabel1;
+ // End of variables declaration//GEN-END:variables
+
+ class ReconnectTask extends SwingWorker {
+
+ private Session session;
+ private ReconnectDialog dialog;
+
+ ReconnectTask(Session session, ReconnectDialog dialog) {
+ this.session = session;
+ this.dialog = dialog;
+ }
+
+ @Override
+ protected Void doInBackground() throws Exception {
+ int numAttempts = 0;
+ while (numAttempts < MAX_ATTEMPTS && !cancel) {
+ numAttempts++;
+ this.publish("Attempting to reconnect: attempt " + numAttempts + "of " + MAX_ATTEMPTS);
+ Thread.sleep(2000);
+ if (session.connect()) {
+ result = true;
+ closeDialog();
+ break;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void process(List view) {
+ dialog.update(view.get(0));
+ }
+
+ }
+}
+
diff --git a/Mage.Client/src/main/java/mage/client/remote/Client.java b/Mage.Client/src/main/java/mage/client/remote/Client.java
index ed5d894c884..b62f5d7f240 100644
--- a/Mage.Client/src/main/java/mage/client/remote/Client.java
+++ b/Mage.Client/src/main/java/mage/client/remote/Client.java
@@ -316,7 +316,7 @@ public class Client implements CallbackClient {
private void handleException(Exception ex) {
logger.fatal("Client error\n", ex);
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Unrecoverable client error. Disconnecting", "Error", JOptionPane.ERROR_MESSAGE);
- session.disconnect();
+ session.disconnect(false);
frame.disableButtons();
}
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 f8538142f42..acbb0bebde8 100644
--- a/Mage.Client/src/main/java/mage/client/remote/Session.java
+++ b/Mage.Client/src/main/java/mage/client/remote/Session.java
@@ -43,11 +43,13 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import mage.cards.decks.DeckCardLists;
import mage.client.MageFrame;
import mage.client.chat.ChatPanel;
import mage.client.components.MageUI;
+import mage.client.dialog.ReconnectDialog;
import mage.client.draft.DraftPanel;
import mage.client.game.GamePanel;
import mage.client.tournament.TournamentPanel;
@@ -89,15 +91,24 @@ public class Session {
private CallbackClientDaemon callbackDaemon;
private ScheduledFuture> future;
private MageUI ui = new MageUI();
+ private Connection connection;
+ private boolean reconnecting = false;
+ private boolean connecting = false;
public Session(MageFrame frame) {
this.frame = frame;
}
- public boolean connect(Connection connection) {
+ public synchronized boolean connect(Connection connection) {
+ this.connecting = true;
if (isConnected()) {
- disconnect();
+ disconnect(true);
}
+ this.connection = connection;
+ return connect();
+ }
+
+ public boolean connect() {
try {
System.setSecurityManager(null);
System.setProperty("http.nonProxyHosts", "code.google.com");
@@ -132,55 +143,70 @@ public class Session {
logger.info("Connected to RMI server at " + connection.getHost() + ":" + connection.getPort());
frame.setStatusText("Connected to " + connection.getHost() + ":" + connection.getPort() + " ");
frame.enableButtons();
+ reconnecting = false;
+ connecting = false;
return true;
} catch (MageException ex) {
logger.fatal("", ex);
- disconnect();
- JOptionPane.showMessageDialog(frame, "Unable to connect to server. " + ex.getMessage());
+ if (!reconnecting) {
+ disconnect(false);
+ 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());
+ if (!reconnecting) {
+ disconnect(false);
+ JOptionPane.showMessageDialog(frame, "Unable to connect to server. " + ex.getMessage());
+ }
} catch (NotBoundException ex) {
logger.fatal("Unable to connect to server - ", ex);
}
return false;
}
-
- public void disconnect() {
-
- if (isConnected()) {
- try {
- for (UUID chatId: chats.keySet()) {
- server.leaveChat(chatId, sessionId);
- }
- }
- catch (Exception ex) {
- //swallow all exceptions at this point
- }
- try {
- //TODO: stop daemon
- if (server != null)
- server.deregisterClient(sessionId);
- } catch (RemoteException ex) {
- logger.fatal("Error disconnecting ...", ex);
- } catch (MageException ex) {
- logger.fatal("Error disconnecting ...", ex);
- }
- removeServer();
- }
- }
-
- private void removeServer() {
+
+ public synchronized void disconnect(boolean voluntary) {
+ if (reconnecting)
+ return;
if (future != null && !future.isDone())
future.cancel(true);
- server = null;
- frame.hideGames();
- frame.hideTables();
frame.setStatusText("Not connected");
frame.disableButtons();
+ server = null;
+ if (!voluntary && !connecting) {
+ if (attemptReconnect())
+ return;
+ }
+ try {
+ for (UUID chatId: chats.keySet()) {
+ server.leaveChat(chatId, sessionId);
+ }
+ }
+ catch (Exception ex) {
+ //swallow all exceptions at this point
+ }
+ try {
+ //TODO: stop daemon
+ if (server != null)
+ server.deregisterClient(sessionId);
+ } catch (RemoteException ex) {
+ logger.fatal("Error disconnecting ...", ex);
+ } catch (MageException ex) {
+ logger.fatal("Error disconnecting ...", ex);
+ }
+ frame.hideGames();
+ frame.hideTables();
logger.info("Disconnected ... ");
- JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Disconnected.", "Disconnected", JOptionPane.INFORMATION_MESSAGE);
+ if (!voluntary && !connecting)
+ JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Server error. You have been disconnected", "Error", JOptionPane.ERROR_MESSAGE);
+ }
+
+ private boolean attemptReconnect() {
+ reconnecting = true;
+ ReconnectDialog rcd = new ReconnectDialog();
+ MageFrame.getDesktop().add(rcd, JLayeredPane.MODAL_LAYER);
+ rcd.showDialog(this);
+ reconnecting = false;
+ return rcd.getResult();
}
public void ack(String message) {
@@ -755,14 +781,12 @@ public class Session {
private void handleRemoteException(RemoteException ex) {
logger.fatal("Communication error", ex);
- JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Critical server error. Disconnecting", "Error", JOptionPane.ERROR_MESSAGE);
- disconnect();
+ disconnect(false);
}
private void handleMageException(MageException ex) {
logger.fatal("Server error", ex);
- JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Critical server error. Disconnecting", "Error", JOptionPane.ERROR_MESSAGE);
- disconnect();
+ disconnect(false);
}
private void handleGameException(GameException ex) {
@@ -793,7 +817,7 @@ public class Session {
missed++;
if (missed > 10) {
logger.info("Connection to server timed out");
- removeServer();
+ disconnect(false);
}
}
else {