Add a user registration dialog.

This commit is contained in:
Me Car 2016-01-09 06:09:30 +09:00
parent 9ca716bf76
commit 835f08c18f
14 changed files with 801 additions and 268 deletions

View file

@ -28,12 +28,6 @@
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="btnConnect" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
@ -60,9 +54,21 @@
<Component id="btnFind" min="-2" max="-2" attributes="0"/> <Component id="btnFind" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Component id="chkForceUpdateDB" alignment="0" max="32767" attributes="0"/> <Component id="chkForceUpdateDB" alignment="0" max="32767" attributes="0"/>
<Component id="chkAutoConnect" alignment="0" pref="358" max="32767" attributes="0"/> <Component id="chkAutoConnect" alignment="0" pref="375" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="btnRegister" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="btnConnect" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
</Group>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
@ -103,7 +109,7 @@
<Component id="chkForceUpdateDB" min="-2" max="-2" attributes="0"/> <Component id="chkForceUpdateDB" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/> <Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="50" max="32767" attributes="0"/> <EmptySpace pref="38" max="32767" attributes="0"/>
<Component id="lblStatus" min="-2" pref="24" max="-2" attributes="0"/> <Component id="lblStatus" min="-2" pref="24" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
@ -111,6 +117,8 @@
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="btnRegister" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -226,5 +234,13 @@
</Component> </Component>
<Component class="javax.swing.JLabel" name="lblStatus"> <Component class="javax.swing.JLabel" name="lblStatus">
</Component> </Component>
<Component class="javax.swing.JButton" name="btnRegister">
<Properties>
<Property name="text" type="java.lang.String" value="Register new user"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRegisterActionPerformed"/>
</Events>
</Component>
</SubComponents> </SubComponents>
</Form> </Form>

View file

@ -56,6 +56,7 @@ import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import mage.client.MageFrame; import mage.client.MageFrame;
@ -65,7 +66,6 @@ import static mage.client.dialog.PreferencesDialog.KEY_CONNECT_FLAG;
import mage.client.util.Config; import mage.client.util.Config;
import mage.client.util.gui.countryBox.CountryItemEditor; import mage.client.util.gui.countryBox.CountryItemEditor;
import mage.remote.Connection; import mage.remote.Connection;
import mage.remote.Connection.ProxyType;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
@ -76,6 +76,7 @@ public class ConnectDialog extends MageDialog {
private static final Logger logger = Logger.getLogger(ConnectDialog.class); private static final Logger logger = Logger.getLogger(ConnectDialog.class);
private Connection connection; private Connection connection;
private ConnectTask task; private ConnectTask task;
private RegisterUserDialog registerUserDialog;
private final ActionListener connectAction = new ActionListener() { private final ActionListener connectAction = new ActionListener() {
@Override @Override
@ -94,6 +95,9 @@ public class ConnectDialog extends MageDialog {
this.txtPort.addActionListener(connectAction); this.txtPort.addActionListener(connectAction);
this.txtUserName.addActionListener(connectAction); this.txtUserName.addActionListener(connectAction);
this.txtPassword.addActionListener(connectAction); this.txtPassword.addActionListener(connectAction);
registerUserDialog = new RegisterUserDialog();
MageFrame.getDesktop().add(registerUserDialog, JLayeredPane.POPUP_LAYER);
} }
public void showDialog() { public void showDialog() {
@ -152,6 +156,7 @@ public class ConnectDialog extends MageDialog {
btnConnect = new javax.swing.JButton(); btnConnect = new javax.swing.JButton();
btnCancel = new javax.swing.JButton(); btnCancel = new javax.swing.JButton();
lblStatus = new javax.swing.JLabel(); lblStatus = new javax.swing.JLabel();
btnRegister = new javax.swing.JButton();
setTitle("Connect to server"); setTitle("Connect to server");
setNormalBounds(new java.awt.Rectangle(100, 100, 410, 307)); setNormalBounds(new java.awt.Rectangle(100, 100, 410, 307));
@ -180,21 +185,9 @@ public class ConnectDialog extends MageDialog {
lblUserName.setLabelFor(txtUserName); lblUserName.setLabelFor(txtUserName);
lblUserName.setText("User name:"); lblUserName.setText("User name:");
txtUserName.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtUserNameActionPerformed(evt);
}
});
lblPassword.setLabelFor(txtPassword); lblPassword.setLabelFor(txtPassword);
lblPassword.setText("Password:"); lblPassword.setText("Password:");
txtPassword.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtPasswordActionPerformed(evt);
}
});
lblFlag.setLabelFor(txtUserName); lblFlag.setLabelFor(txtUserName);
lblFlag.setText("User flag:"); lblFlag.setText("User flag:");
@ -237,6 +230,13 @@ public class ConnectDialog extends MageDialog {
} }
}); });
btnRegister.setText("Register new user");
btnRegister.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnRegisterActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
@ -244,11 +244,6 @@ public class ConnectDialog extends MageDialog {
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(btnConnect)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
@ -271,7 +266,16 @@ public class ConnectDialog extends MageDialog {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFind)) .addComponent(btnFind))
.addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, 358, Short.MAX_VALUE)))) .addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, 375, Short.MAX_VALUE)))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnRegister)
.addGroup(layout.createSequentialGroup()
.addComponent(btnConnect)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel)))
.addGap(26, 26, 26)))
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
@ -304,13 +308,15 @@ public class ConnectDialog extends MageDialog {
.addComponent(chkForceUpdateDB) .addComponent(chkForceUpdateDB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jProxySettingsButton) .addComponent(jProxySettingsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 50, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 38, Short.MAX_VALUE)
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnConnect) .addComponent(btnConnect)
.addComponent(btnCancel)) .addComponent(btnCancel))
.addContainerGap()) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnRegister)
.addGap(3, 3, 3))
); );
pack(); pack();
@ -360,28 +366,7 @@ public class ConnectDialog extends MageDialog {
connection.setPassword(this.txtPassword.getText().trim()); connection.setPassword(this.txtPassword.getText().trim());
connection.setForceDBComparison(this.chkForceUpdateDB.isSelected()); connection.setForceDBComparison(this.chkForceUpdateDB.isSelected());
MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem()); MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem());
PreferencesDialog.setProxyInformation(connection);
ProxyType configProxyType = Connection.ProxyType.valueByText(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_TYPE, "None"));
if (configProxyType != null) {
connection.setProxyType(configProxyType);
if (!configProxyType.equals(ProxyType.NONE)) {
String host = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_ADDRESS, "");
String port = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PORT, "");
if (!host.isEmpty() && !port.isEmpty()) {
connection.setProxyHost(host);
connection.setProxyPort(Integer.valueOf(port));
String username = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_USERNAME, "");
connection.setProxyUsername(username);
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_REMEMBER, "false").equals("true")) {
String password = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PSWD, "");
connection.setProxyPassword(password);
}
} else {
logger.warn("host or\\and port are empty: host=" + host + ", port=" + port);
}
}
}
// pref settings // pref settings
MageFrame.getInstance().setUserPrefsToConnection(connection); MageFrame.getInstance().setUserPrefsToConnection(connection);
@ -580,10 +565,15 @@ public class ConnectDialog extends MageDialog {
// TODO add your handling code here: // TODO add your handling code here:
}//GEN-LAST:event_txtPasswordActionPerformed }//GEN-LAST:event_txtPasswordActionPerformed
private void btnRegisterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRegisterActionPerformed
registerUserDialog.showDialog();
}//GEN-LAST:event_btnRegisterActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCancel; private javax.swing.JButton btnCancel;
private javax.swing.JButton btnConnect; private javax.swing.JButton btnConnect;
private javax.swing.JButton btnFind; private javax.swing.JButton btnFind;
private javax.swing.JButton btnRegister;
private mage.client.util.gui.countryBox.CountryComboBox cbFlag; private mage.client.util.gui.countryBox.CountryComboBox cbFlag;
private javax.swing.JCheckBox chkAutoConnect; private javax.swing.JCheckBox chkAutoConnect;
private javax.swing.JCheckBox chkForceUpdateDB; private javax.swing.JCheckBox chkForceUpdateDB;

View file

@ -2298,6 +2298,30 @@ public class PreferencesDialog extends javax.swing.JDialog {
this.repaint(); this.repaint();
} }
public static void setProxyInformation(Connection connection) {
ProxyType configProxyType = Connection.ProxyType.valueByText(getCachedValue(KEY_PROXY_TYPE, "None"));
if (configProxyType == null) {
return;
}
connection.setProxyType(configProxyType);
if (!configProxyType.equals(ProxyType.NONE)) {
String host = getCachedValue(KEY_PROXY_ADDRESS, "");
String port = getCachedValue(KEY_PROXY_PORT, "");
if (!host.isEmpty() && !port.isEmpty()) {
connection.setProxyHost(host);
connection.setProxyPort(Integer.valueOf(port));
String username = getCachedValue(KEY_PROXY_USERNAME, "");
connection.setProxyUsername(username);
if (getCachedValue(KEY_PROXY_REMEMBER, "false").equals("true")) {
String password = getCachedValue(KEY_PROXY_PSWD, "");
connection.setProxyPassword(password);
}
} else {
log.warn("host or\\and port are empty: host=" + host + ", port=" + port);
}
}
}
/** /**
* @param args the command line arguments * @param args the command line arguments
*/ */

View file

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="3"/>
<Property name="title" type="java.lang.String" value="Register"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
<Component id="lblUserName" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblPassword" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblPort" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblServer" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblStatus" min="-2" pref="292" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Group type="102" attributes="0">
<Component id="btnRegister" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="txtUserName" alignment="0" max="32767" attributes="0"/>
<Component id="txtPassword" alignment="0" pref="292" max="32767" attributes="0"/>
<Component id="txtServer" alignment="0" max="32767" attributes="0"/>
</Group>
<Component id="txtPort" min="-2" pref="292" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="16" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblServer" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtServer" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblPort" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtPort" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblUserName" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtUserName" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblPassword" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtPassword" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Component id="lblStatus" min="-2" pref="28" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnRegister" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="14" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="lblServer">
<Properties>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtServer"/>
</Property>
<Property name="text" type="java.lang.String" value="Server:"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblPort">
<Properties>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtPort"/>
</Property>
<Property name="text" type="java.lang.String" value="Port:"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblUserName">
<Properties>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtUserName"/>
</Property>
<Property name="text" type="java.lang.String" value="User name:"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblPassword">
<Properties>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtPassword"/>
</Property>
<Property name="text" type="java.lang.String" value="Password:"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtUserName">
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtUserNameActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JPasswordField" name="txtPassword">
</Component>
<Component class="javax.swing.JButton" name="btnRegister">
<Properties>
<Property name="text" type="java.lang.String" value="Register"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRegisterActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnCancel">
<Properties>
<Property name="text" type="java.lang.String" value="Cancel"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCancelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblStatus">
<Properties>
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtServer">
</Component>
<Component class="javax.swing.JTextField" name="txtPort">
</Component>
</SubComponents>
</Form>

View file

@ -0,0 +1,231 @@
package mage.client.dialog;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.swing.SwingWorker;
import mage.client.MageFrame;
import mage.client.util.Config;
import mage.remote.Connection;
import mage.remote.Session;
import mage.remote.SessionImpl;
import org.apache.log4j.Logger;
public class RegisterUserDialog extends MageDialog {
private static final Logger logger = Logger.getLogger(ConnectDialog.class);
private Connection connection;
private ConnectTask task;
private Session session;
/**
* Creates new form RegisterUserDialog
*/
public RegisterUserDialog() {
initComponents();
}
public void showDialog() {
this.txtServer.setText(MageFrame.getPreferences().get("serverAddress", Config.serverName));
this.txtPort.setText(MageFrame.getPreferences().get("serverPort", Integer.toString(Config.port)));
this.lblStatus.setText("");
this.setModal(true);
this.setLocation(50, 50);
this.setVisible(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")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
lblServer = new javax.swing.JLabel();
lblPort = new javax.swing.JLabel();
lblUserName = new javax.swing.JLabel();
lblPassword = new javax.swing.JLabel();
txtUserName = new javax.swing.JTextField();
txtPassword = new javax.swing.JPasswordField();
btnRegister = new javax.swing.JButton();
btnCancel = new javax.swing.JButton();
lblStatus = new javax.swing.JLabel();
txtServer = new javax.swing.JTextField();
txtPort = new javax.swing.JTextField();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Register");
lblServer.setLabelFor(txtServer);
lblServer.setText("Server:");
lblPort.setLabelFor(txtPort);
lblPort.setText("Port:");
lblUserName.setLabelFor(txtUserName);
lblUserName.setText("User name:");
lblPassword.setLabelFor(txtPassword);
lblPassword.setText("Password:");
txtUserName.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtUserNameActionPerformed(evt);
}
});
btnRegister.setText("Register");
btnRegister.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnRegisterActionPerformed(evt);
}
});
btnCancel.setText("Cancel");
btnCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCancelActionPerformed(evt);
}
});
lblStatus.setToolTipText("");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(14, 14, 14)
.addComponent(lblUserName))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblPassword, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblPort, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblServer, javax.swing.GroupLayout.Alignment.TRAILING))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(layout.createSequentialGroup()
.addComponent(btnRegister)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel))
.addComponent(txtUserName, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtPassword, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE)
.addComponent(txtServer, javax.swing.GroupLayout.Alignment.LEADING))
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(16, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(9, 9, 9)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblPort)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblUserName)
.addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblPassword)
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnRegister)
.addComponent(btnCancel))
.addContainerGap(14, Short.MAX_VALUE))
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void txtUserNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtUserNameActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_txtUserNameActionPerformed
private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
this.hideDialog();
}//GEN-LAST:event_btnCancelActionPerformed
private void btnRegisterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRegisterActionPerformed
connection = new Connection();
connection.setHost(this.txtServer.getText().trim());
connection.setPort(Integer.valueOf(this.txtPort.getText().trim()));
connection.setUsername(this.txtUserName.getText().trim());
connection.setPassword(this.txtPassword.getText().trim());
PreferencesDialog.setProxyInformation(connection);
task = new ConnectTask();
task.execute();
}//GEN-LAST:event_btnRegisterActionPerformed
private class ConnectTask extends SwingWorker<Boolean, Void> {
private boolean result = false;
private static final int CONNECTION_TIMEOUT_MS = 2100;
@Override
protected Boolean doInBackground() throws Exception {
lblStatus.setText("Connecting...");
btnRegister.setEnabled(false);
session = new SessionImpl(MageFrame.getInstance());
result = session.register(connection);
return result;
}
@Override
protected void done() {
try {
get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (result) {
lblStatus.setText("Registration succeeded");
MageFrame.getInstance().showMessage("Registration succeeded");
hideDialog();
} else {
lblStatus.setText("Could not register");
}
} catch (InterruptedException ex) {
logger.fatal("Update Players Task error", ex);
} catch (ExecutionException ex) {
logger.fatal("Update Players Task error", ex);
} catch (CancellationException ex) {
logger.info("Registration was canceled");
lblStatus.setText("Registration was canceled (but an account might have been actually created)");
} catch (TimeoutException ex) {
logger.fatal("Registration timeout: ", ex);
} finally {
MageFrame.stopConnecting();
btnRegister.setEnabled(true);
}
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCancel;
private javax.swing.JButton btnRegister;
private javax.swing.JLabel lblPassword;
private javax.swing.JLabel lblPort;
private javax.swing.JLabel lblServer;
private javax.swing.JLabel lblStatus;
private javax.swing.JLabel lblUserName;
private javax.swing.JPasswordField txtPassword;
private javax.swing.JTextField txtPort;
private javax.swing.JTextField txtServer;
private javax.swing.JTextField txtUserName;
// End of variables declaration//GEN-END:variables
}

View file

@ -55,14 +55,17 @@ import mage.view.UserView;
*/ */
public interface MageServer { public interface MageServer {
// registers a user to the user DB.
boolean registerUser(String sessionId, String userName, String password, String email) throws MageException;
// connection methods // connection methods
// DEPRECATED - Use registerClientWithPassword instead. This is kept for older clients. // DEPRECATED - Use connectUser instead. This is only kept for older clients.
// This can be deleted once users transitioned to newer clients (1.4.6v1 and later). // This can be deleted once users transitioned to newer clients (1.4.6v1 and later).
boolean registerClient(String userName, String sessionId, MageVersion version) throws MageException; boolean registerClient(String userName, String sessionId, MageVersion version) throws MageException;
boolean registerClientWithPassword(String userName, String password, String sessionId, MageVersion version) throws MageException; boolean connectUser(String userName, String password, String sessionId, MageVersion version) throws MageException;
boolean registerAdmin(String password, String sessionId, MageVersion version) throws MageException; boolean connectAdmin(String password, String sessionId, MageVersion version) throws MageException;
// Not used // Not used
// void deregisterClient(String sessionId) throws MageException; // void deregisterClient(String sessionId) throws MageException;

View file

@ -122,183 +122,18 @@ public class SessionImpl implements Session {
return sessionId; return sessionId;
} }
@Override // RemotingTask encapsulates a task which is involved with some JBoss Remoting. This is
public synchronized boolean connect(Connection connection) { // intended to be used with handleRemotingTaskExceptions for sharing the common exception
if (isConnected()) { // handling.
disconnect(true); public interface RemotingTask {
} public boolean run() throws Throwable;
this.connection = connection;
this.canceled = false;
return connect();
} }
@Override // handleRemotingTaskExceptions runs the given task and handles exceptions appropriately. This
public boolean stopConnecting() { // way we can share the common exception handling.
canceled = true; private boolean handleRemotingTaskExceptions(RemotingTask remoting) {
return true;
}
@Override
public boolean connect() {
sessionState = SessionState.CONNECTING;
try { try {
System.setProperty("http.nonProxyHosts", "code.google.com"); return remoting.run();
System.setProperty("socksNonProxyHosts", "code.google.com");
// clear previous values
System.clearProperty("socksProxyHost");
System.clearProperty("socksProxyPort");
System.clearProperty("http.proxyHost");
System.clearProperty("http.proxyPort");
switch (connection.getProxyType()) {
case SOCKS:
System.setProperty("socksProxyHost", connection.getProxyHost());
System.setProperty("socksProxyPort", Integer.toString(connection.getProxyPort()));
break;
case HTTP:
System.setProperty("http.proxyHost", connection.getProxyHost());
System.setProperty("http.proxyPort", Integer.toString(connection.getProxyPort()));
Authenticator.setDefault(new MageAuthenticator(connection.getProxyUsername(), connection.getProxyPassword()));
break;
}
InvokerLocator clientLocator = new InvokerLocator(connection.getURI());
Map<String, String> metadata = new HashMap<>();
/*
5.8.3.1.1. Write timeouts
The socket timeout facility offered by the JDK applies only to read operations on the socket. As of release 2.5.2,
the socket and bisocket (and also sslsocket and sslbisocket) transports offer a write timeout facility. When a client
or server is configured, in any of the usual ways, with the parameter org.jboss.remoting.transport.socket.SocketWrapper.WRITE_TIMEOUT
(actual value "writeTimeout") set to a positive value (in milliseconds), all write operations will time out if they do
not complete within the configured period. When a write operation times out, the socket upon which the write was invoked
will be closed, which is likely to result in a java.net.SocketException.
Note. A SocketException is considered to be a "retriable" exception, so, if the parameter "numberOfCallRetries" is set
to a value greater than 1, an invocation interrupted by a write timeout can be retried.
Note. The write timeout facility applies to writing of both invocations and responses. It applies to push callbacks as well.
*/
metadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
metadata.put("generalizeSocketException", "true");
server = (MageServer) TransporterClient.createTransporterClient(clientLocator.getLocatorURI(), MageServer.class, metadata);
// http://docs.jboss.org/jbossremoting/docs/guide/2.5/html_single/#d0e1057
Map<String, String> clientMetadata = new HashMap<>();
clientMetadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
/* generalizeSocketException
* If set to false, a failed invocation will be retried in the case of
* SocketExceptions. If set to true, a failed invocation will be retried in the case of
* <classname>SocketException</classname>s and also any <classname>IOException</classname>
* whose message matches the regular expression
* <code>^.*(?:connection.*reset|connection.*closed|broken.*pipe).*$</code>.
* See also the "numberOfCallRetries" parameter, above. The default value is false.*/
clientMetadata.put("generalizeSocketException", "true");
/* A remoting server also has the capability to detect when a client is no longer available.
* This is done by estabilishing a lease with the remoting clients that connect to a server.
* On the client side, an org.jboss.remoting.LeasePinger periodically sends PING messages to
* the server, and on the server side an org.jboss.remoting.Lease informs registered listeners
* if the PING doesn't arrive withing the specified timeout period. */
clientMetadata.put(Client.ENABLE_LEASE, "true");
/*
When the socket client invoker makes its first invocation, it will check to see if there is an available
socket connection in its pool. Since is the first invocation, there will not be and will create a new socket
connection and use it for making the invocation. Then when finished making invocation, will return the still
active socket connection to the pool. As more client invocations are made, is possible for the number of
socket connections to reach the maximum allowed (which is controlled by 'clientMaxPoolSize' property). At this
point, when the next client invocation is made, it will wait up to some configured number of milliseconds, at
which point it will throw an org.jboss.remoting.CannotConnectException. The number of milliseconds is given by
the parameter MicroSocketClientInvoker.CONNECTION_WAIT (actual value "connectionWait"), with a default of
30000 milliseconds. Note that if more than one call retry is configured (see next paragraph),
the CannotConnectException will be swallowed.
Once the socket client invoker get an available socket connection from the pool, are not out of the woods yet.
For example, a network problem could cause a java.net.SocketException. There is also a possibility that the socket
connection, while still appearing to be valid, has "gone stale" while sitting in the pool. For example, a ServerThread
on the other side of the connection could time out and close its socket. If the attempt to complete an invocation
fails, then MicroSocketClientInvoker will make a number of attempts, according to the parameter "numberOfCallRetries",
with a default value of 3. Once the configured number of retries has been exhausted,
an org.jboss.remoting.InvocationFailureException will be thrown.
*/
clientMetadata.put("numberOfCallRetries", "1");
/**
* I'll explain the meaning of "secondaryBindPort" and
* "secondaryConnectPort", and maybe that will help. The Remoting
* bisocket transport creates two ServerSockets on the server. The
* "primary" ServerSocket is used to create connections used for
* ordinary invocations, e.g., a request to create a JMS consumer,
* and the "secondary" ServerSocket is used to create "control"
* connections for internal Remoting messages. The port for the
* primary ServerSocket is configured by the "serverBindPort"
* parameter, and the port for the secondary ServerSocket is, by
* default, chosen randomly. The "secondaryBindPort" parameter can
* be used to assign a specific port to the secondary ServerSocket.
* Now, if there is a translating firewall between the client and
* server, the client should be given the value of the port that is
* translated to the actual binding port of the secondary
* ServerSocket. For example, your configuration will tell the
* secondary ServerSocket to bind to port 14000, and it will tell
* the client to connect to port 14001. It assumes that there is a
* firewall which will translate 14001 to 14000. Apparently, that's
* not happening.
*/
// secondaryBindPort - the port to which the secondary server socket is to be bound. By default, an arbitrary port is selected.
// secondaryConnectPort - the port clients are to use to connect to the secondary server socket.
// By default, the value of secondaryBindPort is used. secondaryConnectPort is useful if the server is behind a translating firewall.
// Indicated the max number of threads used within oneway thread pool.
clientMetadata.put(Client.MAX_NUM_ONEWAY_THREADS, "10");
clientMetadata.put(Remoting.USE_CLIENT_CONNECTION_IDENTITY, "true");
callbackClient = new Client(clientLocator, "callback", clientMetadata);
Map<String, String> listenerMetadata = new HashMap<>();
if (debugMode) {
// prevent client from disconnecting while debugging
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "1000000");
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "900000");
} else {
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "15000");
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "13000");
}
callbackClient.connect(new ClientConnectionListener(), listenerMetadata);
Map<String, String> callbackMetadata = new HashMap<>();
callbackMetadata.put(Bisocket.IS_CALLBACK_SERVER, "true");
if (callbackHandler == null) {
callbackHandler = new CallbackHandler();
}
callbackClient.addListener(callbackHandler, callbackMetadata);
Set callbackConnectors = callbackClient.getCallbackConnectors(callbackHandler);
if (callbackConnectors.size() != 1) {
logger.warn("There should be one callback Connector (number existing = " + callbackConnectors.size() + ")");
}
logger.info("Trying to connect as " + (this.getUserName() == null ? "" : this.getUserName()) + " to XMAGE server at " + connection.getHost() + ":" + connection.getPort());
callbackClient.invoke(null);
this.sessionId = callbackClient.getSessionId();
boolean registerResult;
if (connection.getAdminPassword() == null) {
// for backward compatibility. don't remove twice call - first one does nothing but for version checking
registerResult = server.registerClientWithPassword(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion());
if (registerResult) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData());
}
} else {
registerResult = server.registerAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
}
if (registerResult) {
sessionState = SessionState.CONNECTED;
serverState = server.getServerState();
if (!connection.getUsername().equals("Admin")) {
updateDatabase(connection.isForceDBComparison(), serverState);
}
logger.info("Connected as " + (this.getUserName() == null ? "" : this.getUserName()) + " to MAGE server at " + connection.getHost() + ":" + connection.getPort());
client.connected(this.getUserName() == null ? "" : this.getUserName() + "@" + connection.getHost() + ":" + connection.getPort() + " ");
return true;
}
disconnect(false);
// client.showMessage("Unable to connect to server.");
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
logger.fatal("", ex); logger.fatal("", ex);
client.showMessage("Unable to connect to server. " + ex.getMessage()); client.showMessage("Unable to connect to server. " + ex.getMessage());
@ -353,6 +188,217 @@ public class SessionImpl implements Session {
return false; return false;
} }
@Override
public synchronized boolean register(final Connection connection) {
return establishJBossRemotingConnection(connection) && handleRemotingTaskExceptions(new RemotingTask() {
@Override
public boolean run() throws Throwable {
logger.info("Trying to register as " + getUserName() + " to XMAGE server at " + connection.getHost() + ":" + connection.getPort());
boolean registerResult = server.registerUser(sessionId, connection.getUsername(),
connection.getPassword(), "");
if (registerResult) {
logger.info("Registered as " + getUserName() + " to MAGE server at " + connection.getHost() + ":" + connection.getPort());
}
return registerResult;
}
});
}
@Override
public synchronized boolean connect(final Connection connection) {
return establishJBossRemotingConnection(connection) && handleRemotingTaskExceptions(new RemotingTask() {
@Override
public boolean run() throws Throwable {
logger.info("Trying to log-in as " + getUserName() + " to XMAGE server at " + connection.getHost() + ":" + connection.getPort());
boolean registerResult;
if (connection.getAdminPassword() == null) {
// for backward compatibility. don't remove twice call - first one does nothing but for version checking
registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion());
if (registerResult) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData());
}
} else {
registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
}
if (registerResult) {
serverState = server.getServerState();
if (!connection.getUsername().equals("Admin")) {
updateDatabase(connection.isForceDBComparison(), serverState);
}
logger.info("Logged-in as " + getUserName() + " to MAGE server at " + connection.getHost() + ":" + connection.getPort());
client.connected(getUserName() + "@" + connection.getHost() + ":" + connection.getPort() + " ");
return true;
}
disconnect(false);
return false;
}
});
}
@Override
public boolean stopConnecting() {
canceled = true;
return true;
}
private boolean establishJBossRemotingConnection(final Connection connection) {
if (isConnected()) {
disconnect(true);
}
this.connection = connection;
this.canceled = false;
sessionState = SessionState.CONNECTING;
boolean result = handleRemotingTaskExceptions(new RemotingTask() {
@Override
public boolean run() throws Throwable {
logger.info("Trying to connect to XMAGE server at " + connection.getHost() + ":" + connection.getPort());
System.setProperty("http.nonProxyHosts", "code.google.com");
System.setProperty("socksNonProxyHosts", "code.google.com");
// clear previous values
System.clearProperty("socksProxyHost");
System.clearProperty("socksProxyPort");
System.clearProperty("http.proxyHost");
System.clearProperty("http.proxyPort");
switch (connection.getProxyType()) {
case SOCKS:
System.setProperty("socksProxyHost", connection.getProxyHost());
System.setProperty("socksProxyPort", Integer.toString(connection.getProxyPort()));
break;
case HTTP:
System.setProperty("http.proxyHost", connection.getProxyHost());
System.setProperty("http.proxyPort", Integer.toString(connection.getProxyPort()));
Authenticator.setDefault(new MageAuthenticator(connection.getProxyUsername(), connection.getProxyPassword()));
break;
}
InvokerLocator clientLocator = new InvokerLocator(connection.getURI());
Map<String, String> metadata = new HashMap<>();
/*
5.8.3.1.1. Write timeouts
The socket timeout facility offered by the JDK applies only to read operations on the socket. As of release 2.5.2,
the socket and bisocket (and also sslsocket and sslbisocket) transports offer a write timeout facility. When a client
or server is configured, in any of the usual ways, with the parameter org.jboss.remoting.transport.socket.SocketWrapper.WRITE_TIMEOUT
(actual value "writeTimeout") set to a positive value (in milliseconds), all write operations will time out if they do
not complete within the configured period. When a write operation times out, the socket upon which the write was invoked
will be closed, which is likely to result in a java.net.SocketException.
Note. A SocketException is considered to be a "retriable" exception, so, if the parameter "numberOfCallRetries" is set
to a value greater than 1, an invocation interrupted by a write timeout can be retried.
Note. The write timeout facility applies to writing of both invocations and responses. It applies to push callbacks as well.
*/
metadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
metadata.put("generalizeSocketException", "true");
server = (MageServer) TransporterClient.createTransporterClient(clientLocator.getLocatorURI(), MageServer.class, metadata);
// http://docs.jboss.org/jbossremoting/docs/guide/2.5/html_single/#d0e1057
Map<String, String> clientMetadata = new HashMap<>();
clientMetadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
/* generalizeSocketException
* If set to false, a failed invocation will be retried in the case of
* SocketExceptions. If set to true, a failed invocation will be retried in the case of
* <classname>SocketException</classname>s and also any <classname>IOException</classname>
* whose message matches the regular expression
* <code>^.*(?:connection.*reset|connection.*closed|broken.*pipe).*$</code>.
* See also the "numberOfCallRetries" parameter, above. The default value is false.*/
clientMetadata.put("generalizeSocketException", "true");
/* A remoting server also has the capability to detect when a client is no longer available.
* This is done by estabilishing a lease with the remoting clients that connect to a server.
* On the client side, an org.jboss.remoting.LeasePinger periodically sends PING messages to
* the server, and on the server side an org.jboss.remoting.Lease informs registered listeners
* if the PING doesn't arrive withing the specified timeout period. */
clientMetadata.put(Client.ENABLE_LEASE, "true");
/*
When the socket client invoker makes its first invocation, it will check to see if there is an available
socket connection in its pool. Since is the first invocation, there will not be and will create a new socket
connection and use it for making the invocation. Then when finished making invocation, will return the still
active socket connection to the pool. As more client invocations are made, is possible for the number of
socket connections to reach the maximum allowed (which is controlled by 'clientMaxPoolSize' property). At this
point, when the next client invocation is made, it will wait up to some configured number of milliseconds, at
which point it will throw an org.jboss.remoting.CannotConnectException. The number of milliseconds is given by
the parameter MicroSocketClientInvoker.CONNECTION_WAIT (actual value "connectionWait"), with a default of
30000 milliseconds. Note that if more than one call retry is configured (see next paragraph),
the CannotConnectException will be swallowed.
Once the socket client invoker get an available socket connection from the pool, are not out of the woods yet.
For example, a network problem could cause a java.net.SocketException. There is also a possibility that the socket
connection, while still appearing to be valid, has "gone stale" while sitting in the pool. For example, a ServerThread
on the other side of the connection could time out and close its socket. If the attempt to complete an invocation
fails, then MicroSocketClientInvoker will make a number of attempts, according to the parameter "numberOfCallRetries",
with a default value of 3. Once the configured number of retries has been exhausted,
an org.jboss.remoting.InvocationFailureException will be thrown.
*/
clientMetadata.put("numberOfCallRetries", "1");
/**
* I'll explain the meaning of "secondaryBindPort" and
* "secondaryConnectPort", and maybe that will help. The Remoting
* bisocket transport creates two ServerSockets on the server. The
* "primary" ServerSocket is used to create connections used for
* ordinary invocations, e.g., a request to create a JMS consumer,
* and the "secondary" ServerSocket is used to create "control"
* connections for internal Remoting messages. The port for the
* primary ServerSocket is configured by the "serverBindPort"
* parameter, and the port for the secondary ServerSocket is, by
* default, chosen randomly. The "secondaryBindPort" parameter can
* be used to assign a specific port to the secondary ServerSocket.
* Now, if there is a translating firewall between the client and
* server, the client should be given the value of the port that is
* translated to the actual binding port of the secondary
* ServerSocket. For example, your configuration will tell the
* secondary ServerSocket to bind to port 14000, and it will tell
* the client to connect to port 14001. It assumes that there is a
* firewall which will translate 14001 to 14000. Apparently, that's
* not happening.
*/
// secondaryBindPort - the port to which the secondary server socket is to be bound. By default, an arbitrary port is selected.
// secondaryConnectPort - the port clients are to use to connect to the secondary server socket.
// By default, the value of secondaryBindPort is used. secondaryConnectPort is useful if the server is behind a translating firewall.
// Indicated the max number of threads used within oneway thread pool.
clientMetadata.put(Client.MAX_NUM_ONEWAY_THREADS, "10");
clientMetadata.put(Remoting.USE_CLIENT_CONNECTION_IDENTITY, "true");
callbackClient = new Client(clientLocator, "callback", clientMetadata);
Map<String, String> listenerMetadata = new HashMap<>();
if (debugMode) {
// prevent client from disconnecting while debugging
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "1000000");
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "900000");
} else {
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "15000");
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "13000");
}
callbackClient.connect(new ClientConnectionListener(), listenerMetadata);
Map<String, String> callbackMetadata = new HashMap<>();
callbackMetadata.put(Bisocket.IS_CALLBACK_SERVER, "true");
if (callbackHandler == null) {
callbackHandler = new CallbackHandler();
}
callbackClient.addListener(callbackHandler, callbackMetadata);
Set callbackConnectors = callbackClient.getCallbackConnectors(callbackHandler);
if (callbackConnectors.size() != 1) {
logger.warn("There should be one callback Connector (number existing = " + callbackConnectors.size() + ")");
}
callbackClient.invoke(null);
sessionId = callbackClient.getSessionId();
sessionState = SessionState.CONNECTED;
logger.info("Connected to MAGE server at " + connection.getHost() + ":" + connection.getPort());
return true;
}
});
if (result) {
return true;
}
disconnect(false);
return false;
}
private void updateDatabase(boolean forceDBComparison, ServerState serverState) { private void updateDatabase(boolean forceDBComparison, ServerState serverState) {
long cardDBVersion = CardRepository.instance.getContentVersionFromDB(); long cardDBVersion = CardRepository.instance.getContentVersionFromDB();
if (forceDBComparison || serverState.getCardsContentVersion() > cardDBVersion) { if (forceDBComparison || serverState.getCardsContentVersion() > cardDBVersion) {
@ -1395,7 +1441,8 @@ public class SessionImpl implements Session {
@Override @Override
public String getUserName() { public String getUserName() {
return connection.getUsername(); String username = connection.getUsername();
return username == null ? "" : username;
} }
@Override @Override

View file

@ -34,12 +34,12 @@ import mage.remote.Connection;
*/ */
public interface Connect { public interface Connect {
boolean register(Connection connection);
boolean connect(Connection connection); boolean connect(Connection connection);
boolean stopConnecting(); boolean stopConnecting();
boolean connect();
void disconnect(boolean showMessage); void disconnect(boolean showMessage);
void reconnect(Throwable throwable); void reconnect(Throwable throwable);

View file

@ -29,15 +29,19 @@ public class AuthorizedUser {
@DatabaseField @DatabaseField
protected int hashIterations; protected int hashIterations;
@DatabaseField
protected String email;
public AuthorizedUser() { public AuthorizedUser() {
} }
public AuthorizedUser(String name, Hash hash) { public AuthorizedUser(String name, Hash hash, String email) {
this.name = name; this.name = name;
this.password = hash.toBase64(); this.password = hash.toBase64();
this.salt = hash.getSalt().toBase64(); this.salt = hash.getSalt().toBase64();
this.hashAlgorithm = hash.getAlgorithmName(); this.hashAlgorithm = hash.getAlgorithmName();
this.hashIterations = hash.getIterations(); this.hashIterations = hash.getIterations();
this.email = email;
} }
public boolean doCredentialsMatch(String name, String password) { public boolean doCredentialsMatch(String name, String password) {

View file

@ -27,7 +27,7 @@ public enum AuthorizedUserRepository {
private static final String JDBC_URL = "jdbc:h2:file:./db/authorized_user.h2;AUTO_SERVER=TRUE"; private static final String JDBC_URL = "jdbc:h2:file:./db/authorized_user.h2;AUTO_SERVER=TRUE";
private static final String VERSION_ENTITY_NAME = "authorized_user"; private static final String VERSION_ENTITY_NAME = "authorized_user";
// raise this if db structure was changed // raise this if db structure was changed
private static final long DB_VERSION = 0; private static final long DB_VERSION = 1;
private static final RandomNumberGenerator rng = new SecureRandomNumberGenerator(); private static final RandomNumberGenerator rng = new SecureRandomNumberGenerator();
private Dao<AuthorizedUser, Object> dao; private Dao<AuthorizedUser, Object> dao;
@ -52,14 +52,14 @@ public enum AuthorizedUserRepository {
} }
} }
public void add(final String userName, final String password) { public void add(final String userName, final String password, final String email) {
try { try {
dao.callBatchTasks(new Callable<Object>() { dao.callBatchTasks(new Callable<Object>() {
@Override @Override
public Object call() throws Exception { public Object call() throws Exception {
try { try {
Hash hash = new SimpleHash(Sha256Hash.ALGORITHM_NAME, password, rng.nextBytes(), 1024); Hash hash = new SimpleHash(Sha256Hash.ALGORITHM_NAME, password, rng.nextBytes(), 1024);
AuthorizedUser user = new AuthorizedUser(userName, hash); AuthorizedUser user = new AuthorizedUser(userName, hash, email);
dao.create(user); dao.create(user);
} catch (SQLException ex) { } catch (SQLException ex) {
Logger.getLogger(AuthorizedUserRepository.class).error("Error adding a user to DB - ", ex); Logger.getLogger(AuthorizedUserRepository.class).error("Error adding a user to DB - ", ex);
@ -68,6 +68,7 @@ public enum AuthorizedUserRepository {
} }
}); });
} catch (Exception ex) { } catch (Exception ex) {
Logger.getLogger(AuthorizedUserRepository.class).error("Error adding a authorized_user - ", ex);
} }
} }
@ -81,6 +82,7 @@ public enum AuthorizedUserRepository {
} }
return null; return null;
} catch (SQLException ex) { } catch (SQLException ex) {
Logger.getLogger(AuthorizedUserRepository.class).error("Error getting a authorized_user - ", ex);
} }
return null; return null;
} }
@ -92,6 +94,7 @@ public enum AuthorizedUserRepository {
conn.executeStatement("shutdown compact", 0); conn.executeStatement("shutdown compact", 0);
} }
} catch (SQLException ex) { } catch (SQLException ex) {
Logger.getLogger(AuthorizedUserRepository.class).error("Error closing authorized_user repository - ", ex);
} }
} }
} }

View file

@ -105,6 +105,11 @@ public class MageServerImpl implements MageServer {
ServerMessagesUtil.getInstance().getMessages(); ServerMessagesUtil.getInstance().getMessages();
} }
@Override
public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException {
return SessionManager.getInstance().registerUser(sessionId, userName, password, email);
}
@Override @Override
public boolean registerClient(String userName, String sessionId, MageVersion version) throws MageException { public boolean registerClient(String userName, String sessionId, MageVersion version) throws MageException {
// This method is deprecated, so just inform the server version. // This method is deprecated, so just inform the server version.
@ -114,14 +119,14 @@ public class MageServerImpl implements MageServer {
} }
@Override @Override
public boolean registerClientWithPassword(String userName, String password, String sessionId, MageVersion version) throws MageException { public boolean connectUser(String userName, String password, String sessionId, MageVersion version) throws MageException {
try { try {
if (version.compareTo(Main.getVersion()) != 0) { if (version.compareTo(Main.getVersion()) != 0) {
logger.info("MageVersionException: userName=" + userName + ", version=" + version); logger.info("MageVersionException: userName=" + userName + ", version=" + version);
LogServiceImpl.instance.log(LogKeys.KEY_WRONG_VERSION, userName, version.toString(), Main.getVersion().toString(), sessionId); LogServiceImpl.instance.log(LogKeys.KEY_WRONG_VERSION, userName, version.toString(), Main.getVersion().toString(), sessionId);
throw new MageVersionException(version, Main.getVersion()); throw new MageVersionException(version, Main.getVersion());
} }
return SessionManager.getInstance().registerUser(sessionId, userName, password); return SessionManager.getInstance().connectUser(sessionId, userName, password);
} catch (MageException ex) { } catch (MageException ex) {
if (ex instanceof MageVersionException) { if (ex instanceof MageVersionException) {
throw (MageVersionException) ex; throw (MageVersionException) ex;
@ -142,7 +147,7 @@ public class MageServerImpl implements MageServer {
} }
@Override @Override
public boolean registerAdmin(String adminPassword, String sessionId, MageVersion version) throws MageException { public boolean connectAdmin(String adminPassword, String sessionId, MageVersion version) throws MageException {
try { try {
if (version.compareTo(Main.getVersion()) != 0) { if (version.compareTo(Main.getVersion()) != 0) {
throw new MageException("Wrong client version " + version + ", expecting version " + Main.getVersion()); throw new MageException("Wrong client version " + version + ", expecting version " + Main.getVersion());
@ -150,7 +155,7 @@ public class MageServerImpl implements MageServer {
if (!adminPassword.equals(this.adminPassword)) { if (!adminPassword.equals(this.adminPassword)) {
throw new MageException("Wrong password"); throw new MageException("Wrong password");
} }
return SessionManager.getInstance().registerAdmin(sessionId); return SessionManager.getInstance().connectAdmin(sessionId);
} catch (Exception ex) { } catch (Exception ex) {
handleException(ex); handleException(ex);
} }

View file

@ -74,20 +74,24 @@ public class Session {
this.lock = new ReentrantLock(); this.lock = new ReentrantLock();
} }
public String registerUser(String userName, String password) throws MageException { public String registerUser(String userName, String password, String email) throws MageException {
String returnMessage = registerUserHandling(userName, password); synchronized(AuthorizedUserRepository.instance) {
if (returnMessage != null) { String returnMessage = validateUserName(userName);
sendErrorMessageToClient(returnMessage); if (returnMessage != null) {
sendErrorMessageToClient(returnMessage);
return returnMessage;
}
returnMessage = validatePassword(password);
if (returnMessage != null) {
sendErrorMessageToClient(returnMessage);
return returnMessage;
}
AuthorizedUserRepository.instance.add(userName, password, email);
return null;
} }
return returnMessage;
} }
public boolean isLocked() { static private String validateUserName(String userName) {
return lock.isLocked();
}
public String registerUserHandling(String userName, String password) throws MageException {
this.isAdmin = false;
if (userName.equals("Admin")) { if (userName.equals("Admin")) {
return "User name Admin already in use"; return "User name Admin already in use";
} }
@ -102,22 +106,44 @@ public class Session {
if (m.find()) { if (m.find()) {
return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9"; return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9";
} }
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.get(userName); AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.get(userName);
if (authorizedUser == null) { if (authorizedUser != null) {
// Do this in an explicit sign-up flow. return "User name '" + userName + "' already in use";
AuthorizedUserRepository.instance.add(userName, password); }
} else { return null;
if (!authorizedUser.doCredentialsMatch(userName, password)) { }
return "Wrong username or password";
} static private String validatePassword(String password) {
if (password.length() == 0) {
return "Password needs to be non-empty";
}
return null;
}
public String connectUser(String userName, String password) throws MageException {
String returnMessage = connectUserHandling(userName, password);
if (returnMessage != null) {
sendErrorMessageToClient(returnMessage);
}
return returnMessage;
}
public boolean isLocked() {
return lock.isLocked();
}
public String connectUserHandling(String userName, String password) throws MageException {
this.isAdmin = false;
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.get(userName);
if (authorizedUser == null || !authorizedUser.doCredentialsMatch(userName, password)) {
return "Wrong username or password";
} }
// TODO: Do an authentication with userName and password.
User user = UserManager.getInstance().createUser(userName, host); User user = UserManager.getInstance().createUser(userName, host);
boolean reconnect = false; boolean reconnect = false;
if (user == null) { // user already exists if (user == null) { // user already exists
user = UserManager.getInstance().findUser(userName); user = UserManager.getInstance().findUser(userName);
// TODO: Remove this check since now we do a user authentication.
if (user.getHost().equals(host)) { if (user.getHost().equals(host)) {
user.updateLastActivity(null); // minimizes possible expiration user.updateLastActivity(null); // minimizes possible expiration
this.userId = user.getId(); this.userId = user.getId();
@ -147,7 +173,7 @@ public class Session {
return null; return null;
} }
public void registerAdmin() { public void connectAdmin() {
this.isAdmin = true; this.isAdmin = true;
User user = UserManager.getInstance().createUser("Admin", host); User user = UserManager.getInstance().createUser("Admin", host);
if (user == null) { if (user == null) {

View file

@ -70,14 +70,14 @@ public class SessionManager {
sessions.put(sessionId, session); sessions.put(sessionId, session);
} }
public boolean registerUser(String sessionId, String userName, String password) throws MageException { public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException {
Session session = sessions.get(sessionId); Session session = sessions.get(sessionId);
if (session != null) { if (session != null) {
String returnMessage = session.registerUser(userName, password); String returnMessage = session.registerUser(userName, password, email);
if (returnMessage == null) { if (returnMessage == null) {
LogServiceImpl.instance.log(LogKeys.KEY_USER_CONNECTED, userName, session.getHost(), sessionId); LogServiceImpl.instance.log(LogKeys.KEY_USER_REGISTERED, userName, session.getHost(), sessionId);
logger.info(userName + " joined server"); logger.info(userName + " registered");
logger.debug("- userId: " + session.getUserId()); logger.debug("- userId: " + session.getUserId());
logger.debug("- sessionId: " + sessionId); logger.debug("- sessionId: " + sessionId);
logger.debug("- host: " + session.getHost()); logger.debug("- host: " + session.getHost());
@ -86,15 +86,36 @@ public class SessionManager {
logger.debug(userName + " not registered: " + returnMessage); logger.debug(userName + " not registered: " + returnMessage);
} }
} else { } else {
logger.error(userName + " tried to join with no sessionId"); logger.error(userName + " tried to register with no sessionId");
} }
return false; return false;
} }
public boolean registerAdmin(String sessionId) { public boolean connectUser(String sessionId, String userName, String password) throws MageException {
Session session = sessions.get(sessionId); Session session = sessions.get(sessionId);
if (session != null) { if (session != null) {
session.registerAdmin(); String returnMessage = session.connectUser(userName, password);
if (returnMessage == null) {
LogServiceImpl.instance.log(LogKeys.KEY_USER_CONNECTED, userName, session.getHost(), sessionId);
logger.info(userName + " connected to server");
logger.debug("- userId: " + session.getUserId());
logger.debug("- sessionId: " + sessionId);
logger.debug("- host: " + session.getHost());
return true;
} else {
logger.debug(userName + " not connected: " + returnMessage);
}
} else {
logger.error(userName + " tried to connect with no sessionId");
}
return false;
}
public boolean connectAdmin(String sessionId) {
Session session = sessions.get(sessionId);
if (session != null) {
session.connectAdmin();
LogServiceImpl.instance.log(LogKeys.KEY_ADMIN_CONNECTED, "Admin", session.getHost(), sessionId); LogServiceImpl.instance.log(LogKeys.KEY_ADMIN_CONNECTED, "Admin", session.getHost(), sessionId);
logger.info("Admin connected from " + session.getHost()); logger.info("Admin connected from " + session.getHost());
return true; return true;

View file

@ -7,6 +7,8 @@ public interface LogKeys {
String KEY_GAME_STARTED = "gameStarted"; String KEY_GAME_STARTED = "gameStarted";
String KEY_USER_REGISTERED = "userRegistered";
String KEY_USER_CONNECTED = "userConnected"; String KEY_USER_CONNECTED = "userConnected";
String KEY_ADMIN_CONNECTED = "adminConnected"; String KEY_ADMIN_CONNECTED = "adminConnected";