/* MonkeyTalk - a cross-platform functional testing tool
Copyright (C) 2012 Gorilla Logic, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package com.gorillalogic.monkeyconsole.preferences;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.RadioGroupFieldEditor;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import com.gorillalogic.monkeyconsole.editors.utils.CloudServiceException;
import com.gorillalogic.monkeyconsole.editors.utils.CloudServices;
import com.gorillalogic.monkeyconsole.plugin.FoneMonkeyPlugin;
/**
* <p>
* This class represents a preference page that is contributed to the Preferences dialog. By
* subclassing <code>FieldEditorPreferencePage</code>, we can use the field support built into JFace
* that allows us to create a page that is small and knows how to save, restore and apply itself.
* </p>
* <p>
* This page is used to modify preferences only. They are stored in the preference store that
* belongs to the main plug-in class. That way, preferences can be accessed directly via the
* preference store.
* </p>
*/
public class CloudMonkeyAppliancePreferencePage extends FieldEditorPreferencePage implements
IWorkbenchPreferencePage {
private BooleanFieldEditor useProxy;
private BooleanFieldEditor useProxyAuthentication;
private RadioGroupFieldEditor protocolEditor;
private Text cloudUsername;
private Text cloudPassword;
private Text controllerHost;
private Text controllerPort;
private Text controllerSslPort;
private Text proxyHost;
private Text proxyPort;
private Text proxyUsername;
private Text proxyPassword;
public CloudMonkeyAppliancePreferencePage() {
super(GRID);
}
/**
* Creates the field editors. Field editors are abstractions of the common GUI blocks needed to
* manipulate various types of preferences. Each field editor knows how to save and restore
* itself.
*/
public void createFieldEditors() {
// CLOUD PREFERENCES
// / CLOUD CONTROLLER NETWORK PREFS
Label controllerHostLabel = new Label(this.getFieldEditorParent(), SWT.NONE);
controllerHostLabel.setText("CloudMonkey Appliance Hostname:");
controllerHostLabel.setToolTipText("The hostname or IP address for the cloud server.");
GridData gdControllerHost = new GridData(GridData.VERTICAL_ALIGN_END);
gdControllerHost.horizontalSpan = 3;
controllerHostLabel.setLayoutData(gdControllerHost);
controllerHost = new Text(this.getFieldEditorParent(), SWT.BORDER);
gdControllerHost = new GridData(300, 15);
controllerHost.setLayoutData(gdControllerHost);
controllerHost.setText(getPreferenceStore()
.getString(PreferenceConstants.P_CONTROLLER_HOST));
controllerHost.addVerifyListener(new DomainNameVerifyListener());
Label controllerPortLabel = new Label(this.getFieldEditorParent(), SWT.NONE);
controllerPortLabel.setText("CloudMonkey Appliance Port:");
controllerPortLabel
.setToolTipText("The port on which the cloud server will listen for normal HTTP connections. Defaults to 8080.");
controllerPort = new Text(this.getFieldEditorParent(), SWT.BORDER);
GridData gdControllerPort = new GridData(100, 15);
controllerPort.setLayoutData(gdControllerPort);
controllerPort.setText(getPreferenceStore()
.getString(PreferenceConstants.P_CONTROLLER_PORT));
controllerPort.addVerifyListener(new NetworkPortVerifyListener());
Label controllerSSlPortLabel = new Label(this.getFieldEditorParent(), SWT.NONE);
controllerSSlPortLabel.setText("CloudMonkey Appliance SSL Port:");
controllerSSlPortLabel
.setToolTipText("The port on which the cloud server will listen for secure (encrypted) HTTP connections. Defaults to 4430.");
controllerSslPort = new Text(this.getFieldEditorParent(), SWT.BORDER);
GridData gdControllerSslPort = new GridData(100, 15);
controllerSslPort.setLayoutData(gdControllerSslPort);
controllerSslPort.setText(getPreferenceStore().getString(
PreferenceConstants.P_CONTROLLER_SSL_PORT));
controllerSslPort.addVerifyListener(new NetworkPortVerifyListener());
// Radio Buttons to select protocol
protocolEditor = new RadioGroupFieldEditor(PreferenceConstants.P_CONTROLLER_PROTOCOL,
"Protocol", 1, new String[][] { { "HTTP", "http" }, { "HTTPS", "https" } },
this.getFieldEditorParent());
addField(protocolEditor);
// END CLOUD CONTROLLER NETWORK PREFS
// CLOUD LOGIN INFO
Label cloudAuthenticationLabel = new Label(this.getFieldEditorParent(), SWT.NONE);
cloudAuthenticationLabel
.setText("To access the CloudMonkey Appliance, please enter your username and password.");
GridData gdCloudAuthentication = new GridData(GridData.VERTICAL_ALIGN_END);
gdCloudAuthentication.horizontalSpan = 2;
cloudAuthenticationLabel.setLayoutData(gdCloudAuthentication);
Label cloudUsernameLabel = new Label(this.getFieldEditorParent(), SWT.NONE);
cloudUsernameLabel.setText("Username:");
cloudUsername = new Text(this.getFieldEditorParent(), SWT.BORDER);
GridData gdCloudUsername = new GridData(200, 15);
cloudUsername.setLayoutData(gdCloudUsername);
cloudUsername.setText(getPreferenceStore().getString(PreferenceConstants.P_CLOUDUSR));
Label cloudPasswordLabel = new Label(this.getFieldEditorParent(), SWT.NONE);
cloudPasswordLabel.setText("Password:");
cloudPassword = new Text(this.getFieldEditorParent(), SWT.BORDER | SWT.PASSWORD);
GridData gdCloudPassword = new GridData(200, 15);
cloudPassword.setLayoutData(gdCloudPassword);
cloudPassword.setText(getPreferenceStore().getString(PreferenceConstants.P_CLOUDPASS));
Button verifyLogin = new Button(this.getFieldEditorParent(), SWT.NONE);
verifyLogin.setText("Verify Login");
verifyLogin.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
try {
// Apply the settings first, otherwise a rewrite of the networking code is
// needed.
performApply();
setErrorMessage(null);
setMessage("sending login request");
String token = CloudServices.login(cloudUsername.getText(),
cloudPassword.getText());
if (token == null || token.length() == 0) {
throw new CloudServiceException(
"Invalid Connection prefs - hostname, ports, or proxy");
}
setErrorMessage(null);
setMessage("Username and password verified");
} catch (CloudServiceException ex) {
String errorMessage = ex.getMessage();
if (errorMessage == null || errorMessage.length() == 0) {
errorMessage = "The login information was not valid";
}
setErrorMessage(errorMessage);
setMessage("CloudMonkey Appliance Preferences");
}
}
});
GridData gdVerifyLogin = new GridData(GridData.VERTICAL_ALIGN_END);
gdVerifyLogin.horizontalSpan = 2;
verifyLogin.setLayoutData(gdVerifyLogin);
// END CLOUD LOGIN INFO
// PROXY NETWORK PREFS
Group proxyPreferencesGroup = new Group(this.getFieldEditorParent(), SWT.NONE);
GridLayout cloudPreferencesLayout = new GridLayout();
cloudPreferencesLayout.numColumns = 2;
this.getFieldEditorParent().setLayout(cloudPreferencesLayout);
// Check box for Proxy Usage
useProxy = new BooleanFieldEditor(PreferenceConstants.P_USE_PROXY, "Use Proxy",
proxyPreferencesGroup);
addField(useProxy);
// Proxy Host
Label proxyHostLabel = new Label(proxyPreferencesGroup, SWT.NONE);
proxyHostLabel.setText("Proxy Hostname:");
proxyHostLabel.setToolTipText("The hostname or IP address for the proxy server.");
proxyHost = new Text(proxyPreferencesGroup, SWT.BORDER);
proxyHost.setText(getPreferenceStore().getString(PreferenceConstants.P_PROXY_HOST));
proxyHost.addVerifyListener(new DomainNameVerifyListener());
GridData gdProxyHost = new GridData(300, 15);
proxyHost.setLayoutData(gdProxyHost);
// Proxy Port
Label proxyPortLabel = new Label(proxyPreferencesGroup, SWT.NONE);
proxyPortLabel.setText("Proxy Port:");
proxyPortLabel.setToolTipText("Proxy port number");
proxyPort = new Text(proxyPreferencesGroup, SWT.BORDER);
proxyPort.setText(getPreferenceStore().getString(PreferenceConstants.P_PROXY_PORT));
proxyPort.addVerifyListener(new NetworkPortVerifyListener());
GridData gdProxyPort = new GridData(100, 15);
proxyPort.setLayoutData(gdProxyPort);
// Checkbox for Proxy Authentication
useProxyAuthentication = new BooleanFieldEditor(
PreferenceConstants.P_USE_PROXY_AUTHENTICATION, "Proxy server requires password",
proxyPreferencesGroup);
addField(useProxyAuthentication);
// Proxy Username
Label proxyUsernameLabel = new Label(proxyPreferencesGroup, SWT.NONE);
proxyUsernameLabel.setText("Proxy Username:");
proxyUsernameLabel.setToolTipText("The username for the authenticated proxy server.");
proxyUsername = new Text(proxyPreferencesGroup, SWT.BORDER);
proxyUsername.setText(getPreferenceStore().getString(PreferenceConstants.P_PROXY_USERNAME));
GridData gdProxyUsername = new GridData(300, 15);
proxyUsername.setLayoutData(gdProxyUsername);
// Proxy Password
Label proxyPasswordLabel = new Label(proxyPreferencesGroup, SWT.NONE);
proxyPasswordLabel.setText("Proxy Password:");
proxyPasswordLabel.setToolTipText("The password for the authenticated proxy server.");
proxyPassword = new Text(proxyPreferencesGroup, SWT.BORDER | SWT.PASSWORD);
proxyPassword.setText(getPreferenceStore().getString(PreferenceConstants.P_PROXY_PASSWORD));
GridData gdProxyPassword = new GridData(200, 15);
proxyPassword.setLayoutData(gdProxyPassword);
// END PROXY NETWORK PREFS
checkState();
}
@Override
protected void checkState() {
setErrorMessage(null);
setValid(true);
proxyPort.setEnabled(useProxy.getBooleanValue());
proxyHost.setEnabled(useProxy.getBooleanValue());
proxyUsername.setEnabled(useProxy.getBooleanValue()
&& useProxyAuthentication.getBooleanValue());
proxyPassword.setEnabled(useProxy.getBooleanValue()
&& useProxyAuthentication.getBooleanValue());
super.checkState();
}
@Override
protected void performDefaults() {
super.performDefaults();
checkState();
}
@Override
public void propertyChange(PropertyChangeEvent event) {
super.propertyChange(event);
if (event.getProperty().equals(FieldEditor.VALUE)) {
checkState();
}
}
@Override
public void init(IWorkbench workbench) {
setPreferenceStore(FoneMonkeyPlugin.getDefault().getPreferenceStore());
}
public void applySettings() {
getPreferenceStore().setValue(PreferenceConstants.P_CLOUDUSR, cloudUsername.getText());
getPreferenceStore().setValue(PreferenceConstants.P_CLOUDPASS, cloudPassword.getText());
getPreferenceStore().setValue(PreferenceConstants.P_CONTROLLER_HOST,
controllerHost.getText());
setNetworkPortFromText(controllerPort, PreferenceConstants.P_CONTROLLER_PORT);
setNetworkPortFromText(controllerSslPort, PreferenceConstants.P_CONTROLLER_SSL_PORT);
getPreferenceStore().setValue(PreferenceConstants.P_PROXY_HOST, proxyHost.getText());
setNetworkPortFromText(proxyPort, PreferenceConstants.P_PROXY_PORT);
getPreferenceStore()
.setValue(PreferenceConstants.P_PROXY_USERNAME, proxyUsername.getText());
getPreferenceStore()
.setValue(PreferenceConstants.P_PROXY_PASSWORD, proxyPassword.getText());
}
@Override
public void performApply() {
applySettings();
super.performApply();
}
@Override
public boolean performOk() {
applySettings();
return super.performOk();
}
// Shortcut for setIntegerPrefFromText. Cleans up the performOk function.
private void setNetworkPortFromText(Text control, String propName) {
setIntegerPrefFromText(control, propName, 1, 65535);
}
// Validates an Integer from a string. Min and Max used for validation of network port.
private void setIntegerPrefFromText(Text control, String propName, int min, int max) {
int port = -1;
try {
String s = control.getText();
if (s != null) {
port = Integer.parseInt(s);
}
} catch (NumberFormatException nfe) {
port = -1;
}
if (port >= min && port <= max) {
getPreferenceStore().setValue(propName, port);
}
}
private static class CharFilterVerifyListener implements VerifyListener {
int minlength;
int maxlength;
String validchars;
CharFilterVerifyListener(String validchars, int minlength, int maxlength) {
this.validchars = validchars;
this.maxlength = maxlength;
this.minlength = minlength;
}
@Override
public void verifyText(VerifyEvent evt) {
// String txt=((Text)evt . getSource()).getText();
String txt = evt.text;
if (txt == null) {
evt.doit = false;
return;
}
if (txt.length() < minlength) {
evt.doit = false;
return;
}
if (txt.length() > maxlength) {
evt.doit = false;
return;
}
for (int i = 0; i < txt.length(); i++) {
if (validchars.indexOf(txt.charAt(i)) == -1) {
evt.doit = false;
break;
}
}
}
}
private static class DomainNameVerifyListener extends CharFilterVerifyListener {
DomainNameVerifyListener() {
super("01234567890-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, 63);
}
}
private static class NetworkPortVerifyListener extends CharFilterVerifyListener {
NetworkPortVerifyListener() {
super("01234567890", 0, 5);
}
@Override
public void verifyText(VerifyEvent evt) {
super.verifyText(evt);
if (!evt.doit) {
return;
}
Text control = (Text) evt.getSource();
String oldtxt = control.getText();
String newtxt = oldtxt.substring(0, evt.start) + evt.text + oldtxt.substring(evt.end);
if (newtxt.length() == 0) {
return; // ok for now
}
int val = -1;
try {
val = Integer.parseInt(newtxt);
} catch (NumberFormatException nfe) {
evt.doit = false;
return;
}
if (val < 1 || val > 65535) {
evt.doit = false;
return;
}
}
}
}