blob: 8fdd19b005bb2757ed19b1c3f21395465407bc62 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.eclipse.servers;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.eclipse.server.ConfProp;
import org.apache.hadoop.eclipse.server.HadoopServer;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
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.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
/**
* Wizard for editing the settings of a Hadoop location
*
* The wizard contains 3 tabs: General, Tunneling and Advanced. It edits
* parameters of the location member which either a new location or a copy of
* an existing registered location.
*/
public class HadoopLocationWizard extends WizardPage {
Image circle;
/**
* The location effectively edited by the wizard. This location is a copy
* or a new one.
*/
private HadoopServer location;
/**
* The original location being edited by the wizard (null if we create a
* new instance).
*/
private HadoopServer original;
/**
* New Hadoop location wizard
*/
public HadoopLocationWizard() {
super("Hadoop Server", "New Hadoop Location", null);
this.original = null;
this.location = new HadoopServer();
this.location.setLocationName("");
}
/**
* Constructor to edit the parameters of an existing Hadoop server
*
* @param server
*/
public HadoopLocationWizard(HadoopServer server) {
super("Create a new Hadoop location", "Edit Hadoop Location", null);
this.original = server;
this.location = new HadoopServer(server);
}
/**
* Performs any actions appropriate in response to the user having pressed
* the Finish button, or refuse if finishing now is not permitted.
*
* @return the created or updated Hadoop location
*/
public HadoopServer performFinish() {
try {
if (this.original == null) {
// New location
Display.getDefault().syncExec(new Runnable() {
public void run() {
ServerRegistry.getInstance().addServer(
HadoopLocationWizard.this.location);
}
});
return this.location;
} else {
// Update location
final String originalName = this.original.getLocationName();
this.original.load(this.location);
Display.getDefault().syncExec(new Runnable() {
public void run() {
ServerRegistry.getInstance().updateServer(originalName,
HadoopLocationWizard.this.location);
}
});
return this.original;
}
} catch (Exception e) {
e.printStackTrace();
setMessage("Invalid server location values", IMessageProvider.ERROR);
return null;
}
}
/**
* Validates the current Hadoop location settings (look for Hadoop
* installation directory).
*
*/
private void testLocation() {
setMessage("Not implemented yet", IMessageProvider.WARNING);
}
/**
* Location is not complete (and finish button not available) until a host
* name is specified.
*
* @inheritDoc
*/
@Override
public boolean isPageComplete() {
{
String locName = location.getConfProp(ConfProp.PI_LOCATION_NAME);
if ((locName == null) || (locName.length() == 0)
|| locName.contains("/")) {
setMessage("Bad location name: "
+ "the location name should not contain "
+ "any character prohibited in a file name.", WARNING);
return false;
}
}
{
String master = location.getConfProp(ConfProp.PI_JOB_TRACKER_HOST);
if ((master == null) || (master.length() == 0)) {
setMessage("Bad master host name: "
+ "the master host name refers to the machine "
+ "that runs the Job tracker.", WARNING);
return false;
}
}
{
String jobTracker = location.getConfProp(ConfProp.JOB_TRACKER_URI);
String[] strs = jobTracker.split(":");
boolean ok = (strs.length == 2);
if (ok) {
try {
int port = Integer.parseInt(strs[1]);
ok = (port >= 0) && (port < 65536);
} catch (NumberFormatException nfe) {
ok = false;
}
}
if (!ok) {
setMessage("The job tracker information ("
+ ConfProp.JOB_TRACKER_URI.name + ") is invalid. "
+ "This usually looks like \"host:port\"", WARNING);
return false;
}
}
{
String fsDefaultURI = location.getConfProp(ConfProp.FS_DEFAULT_URI);
try {
URI uri = new URI(fsDefaultURI);
} catch (URISyntaxException e) {
setMessage("The default file system URI is invalid. "
+ "This usually looks like \"hdfs://host:port/\" "
+ "or \"file:///dir/\"", WARNING);
}
}
setMessage("Define the location of a Hadoop infrastructure "
+ "for running MapReduce applications.");
return true;
}
/**
* Create the wizard
*/
/* @inheritDoc */
public void createControl(Composite parent) {
setTitle("Define Hadoop location");
setDescription("Define the location of a Hadoop infrastructure "
+ "for running MapReduce applications.");
Composite panel = new Composite(parent, SWT.FILL);
GridLayout glayout = new GridLayout(2, false);
panel.setLayout(glayout);
TabMediator mediator = new TabMediator(panel);
{
GridData gdata = new GridData(GridData.FILL_BOTH);
gdata.horizontalSpan = 2;
mediator.folder.setLayoutData(gdata);
}
this.setControl(panel /* mediator.folder */);
{
final Button btn = new Button(panel, SWT.NONE);
btn.setText("&Load from file");
btn.setEnabled(false);
btn.setToolTipText("Not yet implemented");
btn.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
// TODO
}
});
}
{
final Button validate = new Button(panel, SWT.NONE);
validate.setText("&Validate location");
validate.setEnabled(false);
validate.setToolTipText("Not yet implemented");
validate.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
testLocation();
}
});
}
}
private interface TabListener {
void notifyChange(ConfProp prop, String propValue);
}
/*
* Mediator pattern to keep tabs synchronized with each other and with the
* location state.
*/
private class TabMediator {
TabFolder folder;
private Set<TabListener> tabs = new HashSet<TabListener>();
TabMediator(Composite parent) {
folder = new TabFolder(parent, SWT.NONE);
tabs.add(new TabMain(this));
tabs.add(new TabAdvanced(this));
}
/**
* Access to current configuration settings
*
* @param propName the property name
* @return the current property value
*/
String get(String propName) {
return location.getConfProp(propName);
}
String get(ConfProp prop) {
return location.getConfProp(prop);
}
/**
* Implements change notifications from any tab: update the location
* state and other tabs
*
* @param source origin of the notification (one of the tree tabs)
* @param propName modified property
* @param propValue new value
*/
void notifyChange(TabListener source, final ConfProp prop,
final String propValue) {
// Ignore notification when no change
String oldValue = location.getConfProp(prop);
if ((oldValue != null) && oldValue.equals(propValue))
return;
location.setConfProp(prop, propValue);
Display.getDefault().syncExec(new Runnable() {
public void run() {
getContainer().updateButtons();
}
});
this.fireChange(source, prop, propValue);
/*
* Now we deal with dependencies between settings
*/
final String jobTrackerHost =
location.getConfProp(ConfProp.PI_JOB_TRACKER_HOST);
final String jobTrackerPort =
location.getConfProp(ConfProp.PI_JOB_TRACKER_PORT);
final String nameNodeHost =
location.getConfProp(ConfProp.PI_NAME_NODE_HOST);
final String nameNodePort =
location.getConfProp(ConfProp.PI_NAME_NODE_PORT);
final boolean colocate =
location.getConfProp(ConfProp.PI_COLOCATE_MASTERS)
.equalsIgnoreCase("yes");
final String jobTrackerURI =
location.getConfProp(ConfProp.JOB_TRACKER_URI);
final String fsDefaultURI =
location.getConfProp(ConfProp.FS_DEFAULT_URI);
final String socksServerURI =
location.getConfProp(ConfProp.SOCKS_SERVER);
final boolean socksProxyEnable =
location.getConfProp(ConfProp.PI_SOCKS_PROXY_ENABLE)
.equalsIgnoreCase("yes");
final String socksProxyHost =
location.getConfProp(ConfProp.PI_SOCKS_PROXY_HOST);
final String socksProxyPort =
location.getConfProp(ConfProp.PI_SOCKS_PROXY_PORT);
Display.getDefault().syncExec(new Runnable() {
public void run() {
switch (prop) {
case PI_JOB_TRACKER_HOST: {
if (colocate)
notifyChange(null, ConfProp.PI_NAME_NODE_HOST,
jobTrackerHost);
String newJobTrackerURI =
String.format("%s:%s", jobTrackerHost, jobTrackerPort);
notifyChange(null, ConfProp.JOB_TRACKER_URI, newJobTrackerURI);
break;
}
case PI_JOB_TRACKER_PORT: {
String newJobTrackerURI =
String.format("%s:%s", jobTrackerHost, jobTrackerPort);
notifyChange(null, ConfProp.JOB_TRACKER_URI, newJobTrackerURI);
break;
}
case PI_NAME_NODE_HOST: {
String newHDFSURI =
String.format("hdfs://%s:%s/", nameNodeHost, nameNodePort);
notifyChange(null, ConfProp.FS_DEFAULT_URI, newHDFSURI);
// Break colocation if someone force the DFS Master
if (!colocate && !nameNodeHost.equals(jobTrackerHost))
notifyChange(null, ConfProp.PI_COLOCATE_MASTERS, "no");
break;
}
case PI_NAME_NODE_PORT: {
String newHDFSURI =
String.format("hdfs://%s:%s/", nameNodeHost, nameNodePort);
notifyChange(null, ConfProp.FS_DEFAULT_URI, newHDFSURI);
break;
}
case PI_SOCKS_PROXY_HOST: {
String newSocksProxyURI =
String.format("%s:%s", socksProxyHost, socksProxyPort);
notifyChange(null, ConfProp.SOCKS_SERVER, newSocksProxyURI);
break;
}
case PI_SOCKS_PROXY_PORT: {
String newSocksProxyURI =
String.format("%s:%s", socksProxyHost, socksProxyPort);
notifyChange(null, ConfProp.SOCKS_SERVER, newSocksProxyURI);
break;
}
case JOB_TRACKER_URI: {
String[] strs = jobTrackerURI.split(":", 2);
String host = strs[0];
String port = (strs.length == 2) ? strs[1] : "";
notifyChange(null, ConfProp.PI_JOB_TRACKER_HOST, host);
notifyChange(null, ConfProp.PI_JOB_TRACKER_PORT, port);
break;
}
case FS_DEFAULT_URI: {
try {
URI uri = new URI(fsDefaultURI);
if (uri.getScheme().equals("hdfs")) {
String host = uri.getHost();
String port = Integer.toString(uri.getPort());
notifyChange(null, ConfProp.PI_NAME_NODE_HOST, host);
notifyChange(null, ConfProp.PI_NAME_NODE_PORT, port);
}
} catch (URISyntaxException use) {
// Ignore the update!
}
break;
}
case SOCKS_SERVER: {
String[] strs = socksServerURI.split(":", 2);
String host = strs[0];
String port = (strs.length == 2) ? strs[1] : "";
notifyChange(null, ConfProp.PI_SOCKS_PROXY_HOST, host);
notifyChange(null, ConfProp.PI_SOCKS_PROXY_PORT, port);
break;
}
case PI_COLOCATE_MASTERS: {
if (colocate)
notifyChange(null, ConfProp.PI_NAME_NODE_HOST,
jobTrackerHost);
break;
}
case PI_SOCKS_PROXY_ENABLE: {
if (socksProxyEnable) {
notifyChange(null, ConfProp.SOCKET_FACTORY_DEFAULT,
"org.apache.hadoop.net.SocksSocketFactory");
} else {
notifyChange(null, ConfProp.SOCKET_FACTORY_DEFAULT,
"org.apache.hadoop.net.StandardSocketFactory");
}
break;
}
}
}
});
}
/**
* Change notifications on properties (by name). A property might not be
* reflected as a ConfProp enum. If it is, the notification is forwarded
* to the ConfProp notifyChange method. If not, it is processed here.
*
* @param source
* @param propName
* @param propValue
*/
void notifyChange(TabListener source, String propName, String propValue) {
ConfProp prop = ConfProp.getByName(propName);
if (prop != null)
notifyChange(source, prop, propValue);
location.setConfProp(propName, propValue);
}
/**
* Broadcast a property change to all registered tabs. If a tab is
* identified as the source of the change, this tab will not be notified.
*
* @param source TODO
* @param prop
* @param value
*/
private void fireChange(TabListener source, ConfProp prop, String value) {
for (TabListener tab : tabs) {
if (tab != source)
tab.notifyChange(prop, value);
}
}
}
/**
* Create a SWT Text component for the given {@link ConfProp} text
* configuration property.
*
* @param listener
* @param parent
* @param prop
* @return
*/
private Text createConfText(ModifyListener listener, Composite parent,
ConfProp prop) {
Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
text.setLayoutData(data);
text.setData("hProp", prop);
text.setText(location.getConfProp(prop));
text.addModifyListener(listener);
return text;
}
/**
* Create a SWT Checked Button component for the given {@link ConfProp}
* boolean configuration property.
*
* @param listener
* @param parent
* @param prop
* @return
*/
private Button createConfCheckButton(SelectionListener listener,
Composite parent, ConfProp prop, String text) {
Button button = new Button(parent, SWT.CHECK);
button.setText(text);
button.setData("hProp", prop);
button.setSelection(location.getConfProp(prop).equalsIgnoreCase("yes"));
button.addSelectionListener(listener);
return button;
}
/**
* Create editor entry for the given configuration property. The editor is
* a couple (Label, Text).
*
* @param listener the listener to trigger on property change
* @param parent the SWT parent container
* @param prop the property to create an editor for
* @param labelText a label (null will defaults to the property name)
*
* @return a SWT Text field
*/
private Text createConfLabelText(ModifyListener listener,
Composite parent, ConfProp prop, String labelText) {
Label label = new Label(parent, SWT.NONE);
if (labelText == null)
labelText = prop.name;
label.setText(labelText);
return createConfText(listener, parent, prop);
}
/**
* Create an editor entry for the given configuration name
*
* @param listener the listener to trigger on property change
* @param parent the SWT parent container
* @param propName the name of the property to create an editor for
* @param labelText a label (null will defaults to the property name)
*
* @return a SWT Text field
*/
private Text createConfNameEditor(ModifyListener listener,
Composite parent, String propName, String labelText) {
{
ConfProp prop = ConfProp.getByName(propName);
if (prop != null)
return createConfLabelText(listener, parent, prop, labelText);
}
Label label = new Label(parent, SWT.NONE);
if (labelText == null)
labelText = propName;
label.setText(labelText);
Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
text.setLayoutData(data);
text.setData("hPropName", propName);
text.setText(location.getConfProp(propName));
text.addModifyListener(listener);
return text;
}
/**
* Main parameters of the Hadoop location:
* <li> host and port of the Map/Reduce master (Job tracker)
* <li> host and port of the DFS master (Name node)
* <li> SOCKS proxy
*/
private class TabMain implements TabListener, ModifyListener,
SelectionListener {
TabMediator mediator;
Text locationName;
Text textJTHost;
Text textNNHost;
Button colocateMasters;
Text textJTPort;
Text textNNPort;
Text userName;
Button useSocksProxy;
Text socksProxyHost;
Text socksProxyPort;
TabMain(TabMediator mediator) {
this.mediator = mediator;
TabItem tab = new TabItem(mediator.folder, SWT.NONE);
tab.setText("General");
tab.setToolTipText("General location parameters");
tab.setImage(circle);
tab.setControl(createControl(mediator.folder));
}
private Control createControl(Composite parent) {
Composite panel = new Composite(parent, SWT.FILL);
panel.setLayout(new GridLayout(2, false));
GridData data;
/*
* Location name
*/
{
Composite subpanel = new Composite(panel, SWT.FILL);
subpanel.setLayout(new GridLayout(2, false));
data = new GridData();
data.horizontalSpan = 2;
data.horizontalAlignment = SWT.FILL;
subpanel.setLayoutData(data);
locationName =
createConfLabelText(this, subpanel, ConfProp.PI_LOCATION_NAME,
"&Location name:");
}
/*
* Map/Reduce group
*/
{
Group groupMR = new Group(panel, SWT.SHADOW_NONE);
groupMR.setText("Map/Reduce Master");
groupMR.setToolTipText("Address of the Map/Reduce master node "
+ "(the Job Tracker).");
GridLayout layout = new GridLayout(2, false);
groupMR.setLayout(layout);
data = new GridData();
data.verticalAlignment = SWT.FILL;
data.horizontalAlignment = SWT.CENTER;
data.widthHint = 250;
groupMR.setLayoutData(data);
// Job Tracker host
Label label = new Label(groupMR, SWT.NONE);
label.setText("Host:");
data =
new GridData(GridData.BEGINNING, GridData.CENTER, false, true);
label.setLayoutData(data);
textJTHost =
createConfText(this, groupMR, ConfProp.PI_JOB_TRACKER_HOST);
data = new GridData(GridData.FILL, GridData.CENTER, true, true);
textJTHost.setLayoutData(data);
// Job Tracker port
label = new Label(groupMR, SWT.NONE);
label.setText("Port:");
data =
new GridData(GridData.BEGINNING, GridData.CENTER, false, true);
label.setLayoutData(data);
textJTPort =
createConfText(this, groupMR, ConfProp.PI_JOB_TRACKER_PORT);
data = new GridData(GridData.FILL, GridData.CENTER, true, true);
textJTPort.setLayoutData(data);
}
/*
* DFS group
*/
{
Group groupDFS = new Group(panel, SWT.SHADOW_NONE);
groupDFS.setText("DFS Master");
groupDFS.setToolTipText("Address of the Distributed FileSystem "
+ "master node (the Name Node).");
GridLayout layout = new GridLayout(2, false);
groupDFS.setLayout(layout);
data = new GridData();
data.horizontalAlignment = SWT.CENTER;
data.widthHint = 250;
groupDFS.setLayoutData(data);
colocateMasters =
createConfCheckButton(this, groupDFS,
ConfProp.PI_COLOCATE_MASTERS, "Use M/R Master host");
data = new GridData();
data.horizontalSpan = 2;
colocateMasters.setLayoutData(data);
// Job Tracker host
Label label = new Label(groupDFS, SWT.NONE);
data = new GridData();
label.setText("Host:");
label.setLayoutData(data);
textNNHost =
createConfText(this, groupDFS, ConfProp.PI_NAME_NODE_HOST);
// Job Tracker port
label = new Label(groupDFS, SWT.NONE);
data = new GridData();
label.setText("Port:");
label.setLayoutData(data);
textNNPort =
createConfText(this, groupDFS, ConfProp.PI_NAME_NODE_PORT);
}
{
Composite subpanel = new Composite(panel, SWT.FILL);
subpanel.setLayout(new GridLayout(2, false));
data = new GridData();
data.horizontalSpan = 2;
data.horizontalAlignment = SWT.FILL;
subpanel.setLayoutData(data);
userName =
createConfLabelText(this, subpanel, ConfProp.PI_USER_NAME,
"&User name:");
}
// SOCKS proxy group
{
Group groupSOCKS = new Group(panel, SWT.SHADOW_NONE);
groupSOCKS.setText("SOCKS proxy");
groupSOCKS.setToolTipText("Address of the SOCKS proxy to use "
+ "to connect to the infrastructure.");
GridLayout layout = new GridLayout(2, false);
groupSOCKS.setLayout(layout);
data = new GridData();
data.horizontalAlignment = SWT.CENTER;
data.horizontalSpan = 2;
data.widthHint = 250;
groupSOCKS.setLayoutData(data);
useSocksProxy =
createConfCheckButton(this, groupSOCKS,
ConfProp.PI_SOCKS_PROXY_ENABLE, "Enable SOCKS proxy");
data = new GridData();
data.horizontalSpan = 2;
useSocksProxy.setLayoutData(data);
// SOCKS proxy host
Label label = new Label(groupSOCKS, SWT.NONE);
data = new GridData();
label.setText("Host:");
label.setLayoutData(data);
socksProxyHost =
createConfText(this, groupSOCKS, ConfProp.PI_SOCKS_PROXY_HOST);
// SOCKS proxy port
label = new Label(groupSOCKS, SWT.NONE);
data = new GridData();
label.setText("Port:");
label.setLayoutData(data);
socksProxyPort =
createConfText(this, groupSOCKS, ConfProp.PI_SOCKS_PROXY_PORT);
}
// Update the state of all widgets according to the current values!
reloadConfProp(ConfProp.PI_COLOCATE_MASTERS);
reloadConfProp(ConfProp.PI_SOCKS_PROXY_ENABLE);
reloadConfProp(ConfProp.PI_JOB_TRACKER_HOST);
return panel;
}
/**
* Reload the given configuration property value
*
* @param prop
*/
private void reloadConfProp(ConfProp prop) {
this.notifyChange(prop, location.getConfProp(prop));
}
public void notifyChange(ConfProp prop, String propValue) {
switch (prop) {
case PI_JOB_TRACKER_HOST: {
textJTHost.setText(propValue);
break;
}
case PI_JOB_TRACKER_PORT: {
textJTPort.setText(propValue);
break;
}
case PI_LOCATION_NAME: {
locationName.setText(propValue);
break;
}
case PI_USER_NAME: {
userName.setText(propValue);
break;
}
case PI_COLOCATE_MASTERS: {
if (colocateMasters != null) {
boolean colocate = propValue.equalsIgnoreCase("yes");
colocateMasters.setSelection(colocate);
if (textNNHost != null) {
textNNHost.setEnabled(!colocate);
}
}
break;
}
case PI_NAME_NODE_HOST: {
textNNHost.setText(propValue);
break;
}
case PI_NAME_NODE_PORT: {
textNNPort.setText(propValue);
break;
}
case PI_SOCKS_PROXY_ENABLE: {
if (useSocksProxy != null) {
boolean useProxy = propValue.equalsIgnoreCase("yes");
useSocksProxy.setSelection(useProxy);
if (socksProxyHost != null)
socksProxyHost.setEnabled(useProxy);
if (socksProxyPort != null)
socksProxyPort.setEnabled(useProxy);
}
break;
}
case PI_SOCKS_PROXY_HOST: {
socksProxyHost.setText(propValue);
break;
}
case PI_SOCKS_PROXY_PORT: {
socksProxyPort.setText(propValue);
break;
}
}
}
/* @inheritDoc */
public void modifyText(ModifyEvent e) {
final Text text = (Text) e.widget;
final ConfProp prop = (ConfProp) text.getData("hProp");
Display.getDefault().syncExec(new Runnable() {
public void run() {
mediator.notifyChange(TabMain.this, prop, text.getText());
}
});
}
/* @inheritDoc */
public void widgetDefaultSelected(SelectionEvent e) {
this.widgetSelected(e);
}
/* @inheritDoc */
public void widgetSelected(SelectionEvent e) {
final Button button = (Button) e.widget;
final ConfProp prop = (ConfProp) button.getData("hProp");
Display.getDefault().syncExec(new Runnable() {
public void run() {
// We want to receive the update also!
mediator.notifyChange(null, prop, button.getSelection() ? "yes"
: "no");
}
});
}
}
private class TabAdvanced implements TabListener, ModifyListener {
TabMediator mediator;
private Composite panel;
private Map<String, Text> textMap = new TreeMap<String, Text>();
TabAdvanced(TabMediator mediator) {
this.mediator = mediator;
TabItem tab = new TabItem(mediator.folder, SWT.NONE);
tab.setText("Advanced parameters");
tab.setToolTipText("Access to advanced Hadoop parameters");
tab.setImage(circle);
tab.setControl(createControl(mediator.folder));
}
private Control createControl(Composite parent) {
ScrolledComposite sc =
new ScrolledComposite(parent, SWT.BORDER | SWT.H_SCROLL
| SWT.V_SCROLL);
panel = new Composite(sc, SWT.NONE);
sc.setContent(panel);
sc.setExpandHorizontal(true);
sc.setExpandVertical(true);
sc.setMinSize(640, 480);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.makeColumnsEqualWidth = false;
panel.setLayout(layout);
panel.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,
true, 1, 1));
// Sort by property name
Configuration config = location.getConfiguration();
SortedMap<String, String> map = new TreeMap<String, String>();
Iterator<Entry<String, String>> it = config.iterator();
while (it.hasNext()) {
Entry<String, String> entry = it.next();
map.put(entry.getKey(), entry.getValue());
}
for (Entry<String, String> entry : map.entrySet()) {
Text text = createConfNameEditor(this, panel, entry.getKey(), null);
textMap.put(entry.getKey(), text);
}
sc.setMinSize(panel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
return sc;
}
public void notifyChange(ConfProp prop, final String propValue) {
Text text = textMap.get(prop.name);
text.setText(propValue);
}
public void modifyText(ModifyEvent e) {
final Text text = (Text) e.widget;
Object hProp = text.getData("hProp");
final ConfProp prop = (hProp != null) ? (ConfProp) hProp : null;
Object hPropName = text.getData("hPropName");
final String propName =
(hPropName != null) ? (String) hPropName : null;
Display.getDefault().syncExec(new Runnable() {
public void run() {
if (prop != null)
mediator.notifyChange(TabAdvanced.this, prop, text.getText());
else
mediator
.notifyChange(TabAdvanced.this, propName, text.getText());
}
});
}
}
}