HadoopLocationWizard.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:30k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.eclipse.servers;
  19. import java.net.URI;
  20. import java.net.URISyntaxException;
  21. import java.util.HashSet;
  22. import java.util.Iterator;
  23. import java.util.Map;
  24. import java.util.Set;
  25. import java.util.SortedMap;
  26. import java.util.TreeMap;
  27. import java.util.Map.Entry;
  28. import org.apache.hadoop.conf.Configuration;
  29. import org.apache.hadoop.eclipse.server.ConfProp;
  30. import org.apache.hadoop.eclipse.server.HadoopServer;
  31. import org.eclipse.jface.dialogs.IMessageProvider;
  32. import org.eclipse.jface.wizard.WizardPage;
  33. import org.eclipse.swt.SWT;
  34. import org.eclipse.swt.custom.ScrolledComposite;
  35. import org.eclipse.swt.events.ModifyEvent;
  36. import org.eclipse.swt.events.ModifyListener;
  37. import org.eclipse.swt.events.SelectionEvent;
  38. import org.eclipse.swt.events.SelectionListener;
  39. import org.eclipse.swt.graphics.Image;
  40. import org.eclipse.swt.layout.GridData;
  41. import org.eclipse.swt.layout.GridLayout;
  42. import org.eclipse.swt.widgets.Button;
  43. import org.eclipse.swt.widgets.Composite;
  44. import org.eclipse.swt.widgets.Control;
  45. import org.eclipse.swt.widgets.Display;
  46. import org.eclipse.swt.widgets.Event;
  47. import org.eclipse.swt.widgets.Group;
  48. import org.eclipse.swt.widgets.Label;
  49. import org.eclipse.swt.widgets.Listener;
  50. import org.eclipse.swt.widgets.TabFolder;
  51. import org.eclipse.swt.widgets.TabItem;
  52. import org.eclipse.swt.widgets.Text;
  53. /**
  54.  * Wizard for editing the settings of a Hadoop location
  55.  * 
  56.  * The wizard contains 3 tabs: General, Tunneling and Advanced. It edits
  57.  * parameters of the location member which either a new location or a copy of
  58.  * an existing registered location.
  59.  */
  60. public class HadoopLocationWizard extends WizardPage {
  61.   Image circle;
  62.   /**
  63.    * The location effectively edited by the wizard. This location is a copy
  64.    * or a new one.
  65.    */
  66.   private HadoopServer location;
  67.   /**
  68.    * The original location being edited by the wizard (null if we create a
  69.    * new instance).
  70.    */
  71.   private HadoopServer original;
  72.   /**
  73.    * New Hadoop location wizard
  74.    */
  75.   public HadoopLocationWizard() {
  76.     super("Hadoop Server", "New Hadoop Location", null);
  77.     this.original = null;
  78.     this.location = new HadoopServer();
  79.     this.location.setLocationName("");
  80.   }
  81.   /**
  82.    * Constructor to edit the parameters of an existing Hadoop server
  83.    * 
  84.    * @param server
  85.    */
  86.   public HadoopLocationWizard(HadoopServer server) {
  87.     super("Create a new Hadoop location", "Edit Hadoop Location", null);
  88.     this.original = server;
  89.     this.location = new HadoopServer(server);
  90.   }
  91.   /**
  92.    * Performs any actions appropriate in response to the user having pressed
  93.    * the Finish button, or refuse if finishing now is not permitted.
  94.    * 
  95.    * @return the created or updated Hadoop location
  96.    */
  97.   public HadoopServer performFinish() {
  98.     try {
  99.       if (this.original == null) {
  100.         // New location
  101.         Display.getDefault().syncExec(new Runnable() {
  102.           public void run() {
  103.             ServerRegistry.getInstance().addServer(
  104.                 HadoopLocationWizard.this.location);
  105.           }
  106.         });
  107.         return this.location;
  108.       } else {
  109.         // Update location
  110.         final String originalName = this.original.getLocationName();
  111.         this.original.load(this.location);
  112.         Display.getDefault().syncExec(new Runnable() {
  113.           public void run() {
  114.             ServerRegistry.getInstance().updateServer(originalName,
  115.                 HadoopLocationWizard.this.location);
  116.           }
  117.         });
  118.         return this.original;
  119.       }
  120.     } catch (Exception e) {
  121.       e.printStackTrace();
  122.       setMessage("Invalid server location values", IMessageProvider.ERROR);
  123.       return null;
  124.     }
  125.   }
  126.   /**
  127.    * Validates the current Hadoop location settings (look for Hadoop
  128.    * installation directory).
  129.    * 
  130.    */
  131.   private void testLocation() {
  132.     setMessage("Not implemented yet", IMessageProvider.WARNING);
  133.   }
  134.   /**
  135.    * Location is not complete (and finish button not available) until a host
  136.    * name is specified.
  137.    * 
  138.    * @inheritDoc
  139.    */
  140.   @Override
  141.   public boolean isPageComplete() {
  142.     {
  143.       String locName = location.getConfProp(ConfProp.PI_LOCATION_NAME);
  144.       if ((locName == null) || (locName.length() == 0)
  145.           || locName.contains("/")) {
  146.         setMessage("Bad location name: "
  147.             + "the location name should not contain "
  148.             + "any character prohibited in a file name.", WARNING);
  149.         return false;
  150.       }
  151.     }
  152.     {
  153.       String master = location.getConfProp(ConfProp.PI_JOB_TRACKER_HOST);
  154.       if ((master == null) || (master.length() == 0)) {
  155.         setMessage("Bad master host name: "
  156.             + "the master host name refers to the machine "
  157.             + "that runs the Job tracker.", WARNING);
  158.         return false;
  159.       }
  160.     }
  161.     {
  162.       String jobTracker = location.getConfProp(ConfProp.JOB_TRACKER_URI);
  163.       String[] strs = jobTracker.split(":");
  164.       boolean ok = (strs.length == 2);
  165.       if (ok) {
  166.         try {
  167.           int port = Integer.parseInt(strs[1]);
  168.           ok = (port >= 0) && (port < 65536);
  169.         } catch (NumberFormatException nfe) {
  170.           ok = false;
  171.         }
  172.       }
  173.       if (!ok) {
  174.         setMessage("The job tracker information ("
  175.             + ConfProp.JOB_TRACKER_URI.name + ") is invalid. "
  176.             + "This usually looks like "host:port"", WARNING);
  177.         return false;
  178.       }
  179.     }
  180.     {
  181.       String fsDefaultURI = location.getConfProp(ConfProp.FS_DEFAULT_URI);
  182.       try {
  183.         URI uri = new URI(fsDefaultURI);
  184.       } catch (URISyntaxException e) {
  185.         setMessage("The default file system URI is invalid. "
  186.             + "This usually looks like "hdfs://host:port/" "
  187.             + "or "file:///dir/"", WARNING);
  188.       }
  189.     }
  190.     setMessage("Define the location of a Hadoop infrastructure "
  191.         + "for running MapReduce applications.");
  192.     return true;
  193.   }
  194.   /**
  195.    * Create the wizard
  196.    */
  197.   /* @inheritDoc */
  198.   public void createControl(Composite parent) {
  199.     setTitle("Define Hadoop location");
  200.     setDescription("Define the location of a Hadoop infrastructure "
  201.         + "for running MapReduce applications.");
  202.     Composite panel = new Composite(parent, SWT.FILL);
  203.     GridLayout glayout = new GridLayout(2, false);
  204.     panel.setLayout(glayout);
  205.     TabMediator mediator = new TabMediator(panel);
  206.     {
  207.       GridData gdata = new GridData(GridData.FILL_BOTH);
  208.       gdata.horizontalSpan = 2;
  209.       mediator.folder.setLayoutData(gdata);
  210.     }
  211.     this.setControl(panel /* mediator.folder */);
  212.     {
  213.       final Button btn = new Button(panel, SWT.NONE);
  214.       btn.setText("&Load from file");
  215.       btn.setEnabled(false);
  216.       btn.setToolTipText("Not yet implemented");
  217.       btn.addListener(SWT.Selection, new Listener() {
  218.         public void handleEvent(Event e) {
  219.           // TODO
  220.         }
  221.       });
  222.     }
  223.     {
  224.       final Button validate = new Button(panel, SWT.NONE);
  225.       validate.setText("&Validate location");
  226.       validate.setEnabled(false);
  227.       validate.setToolTipText("Not yet implemented");
  228.       validate.addListener(SWT.Selection, new Listener() {
  229.         public void handleEvent(Event e) {
  230.           testLocation();
  231.         }
  232.       });
  233.     }
  234.   }
  235.   private interface TabListener {
  236.     void notifyChange(ConfProp prop, String propValue);
  237.   }
  238.   /*
  239.    * Mediator pattern to keep tabs synchronized with each other and with the
  240.    * location state.
  241.    */
  242.   private class TabMediator {
  243.     TabFolder folder;
  244.     private Set<TabListener> tabs = new HashSet<TabListener>();
  245.     TabMediator(Composite parent) {
  246.       folder = new TabFolder(parent, SWT.NONE);
  247.       tabs.add(new TabMain(this));
  248.       tabs.add(new TabAdvanced(this));
  249.     }
  250.     /**
  251.      * Access to current configuration settings
  252.      * 
  253.      * @param propName the property name
  254.      * @return the current property value
  255.      */
  256.     String get(String propName) {
  257.       return location.getConfProp(propName);
  258.     }
  259.     String get(ConfProp prop) {
  260.       return location.getConfProp(prop);
  261.     }
  262.     /**
  263.      * Implements change notifications from any tab: update the location
  264.      * state and other tabs
  265.      * 
  266.      * @param source origin of the notification (one of the tree tabs)
  267.      * @param propName modified property
  268.      * @param propValue new value
  269.      */
  270.     void notifyChange(TabListener source, final ConfProp prop,
  271.         final String propValue) {
  272.       // Ignore notification when no change
  273.       String oldValue = location.getConfProp(prop);
  274.       if ((oldValue != null) && oldValue.equals(propValue))
  275.         return;
  276.       location.setConfProp(prop, propValue);
  277.       Display.getDefault().syncExec(new Runnable() {
  278.         public void run() {
  279.           getContainer().updateButtons();
  280.         }
  281.       });
  282.       this.fireChange(source, prop, propValue);
  283.       /*
  284.        * Now we deal with dependencies between settings
  285.        */
  286.       final String jobTrackerHost =
  287.           location.getConfProp(ConfProp.PI_JOB_TRACKER_HOST);
  288.       final String jobTrackerPort =
  289.           location.getConfProp(ConfProp.PI_JOB_TRACKER_PORT);
  290.       final String nameNodeHost =
  291.           location.getConfProp(ConfProp.PI_NAME_NODE_HOST);
  292.       final String nameNodePort =
  293.           location.getConfProp(ConfProp.PI_NAME_NODE_PORT);
  294.       final boolean colocate =
  295.           location.getConfProp(ConfProp.PI_COLOCATE_MASTERS)
  296.               .equalsIgnoreCase("yes");
  297.       final String jobTrackerURI =
  298.           location.getConfProp(ConfProp.JOB_TRACKER_URI);
  299.       final String fsDefaultURI =
  300.           location.getConfProp(ConfProp.FS_DEFAULT_URI);
  301.       final String socksServerURI =
  302.           location.getConfProp(ConfProp.SOCKS_SERVER);
  303.       final boolean socksProxyEnable =
  304.           location.getConfProp(ConfProp.PI_SOCKS_PROXY_ENABLE)
  305.               .equalsIgnoreCase("yes");
  306.       final String socksProxyHost =
  307.           location.getConfProp(ConfProp.PI_SOCKS_PROXY_HOST);
  308.       final String socksProxyPort =
  309.           location.getConfProp(ConfProp.PI_SOCKS_PROXY_PORT);
  310.       Display.getDefault().syncExec(new Runnable() {
  311.         public void run() {
  312.           switch (prop) {
  313.             case PI_JOB_TRACKER_HOST: {
  314.               if (colocate)
  315.                 notifyChange(null, ConfProp.PI_NAME_NODE_HOST,
  316.                     jobTrackerHost);
  317.               String newJobTrackerURI =
  318.                   String.format("%s:%s", jobTrackerHost, jobTrackerPort);
  319.               notifyChange(null, ConfProp.JOB_TRACKER_URI, newJobTrackerURI);
  320.               break;
  321.             }
  322.             case PI_JOB_TRACKER_PORT: {
  323.               String newJobTrackerURI =
  324.                   String.format("%s:%s", jobTrackerHost, jobTrackerPort);
  325.               notifyChange(null, ConfProp.JOB_TRACKER_URI, newJobTrackerURI);
  326.               break;
  327.             }
  328.             case PI_NAME_NODE_HOST: {
  329.               String newHDFSURI =
  330.                   String.format("hdfs://%s:%s/", nameNodeHost, nameNodePort);
  331.               notifyChange(null, ConfProp.FS_DEFAULT_URI, newHDFSURI);
  332.               // Break colocation if someone force the DFS Master
  333.               if (!colocate && !nameNodeHost.equals(jobTrackerHost))
  334.                 notifyChange(null, ConfProp.PI_COLOCATE_MASTERS, "no");
  335.               break;
  336.             }
  337.             case PI_NAME_NODE_PORT: {
  338.               String newHDFSURI =
  339.                   String.format("hdfs://%s:%s/", nameNodeHost, nameNodePort);
  340.               notifyChange(null, ConfProp.FS_DEFAULT_URI, newHDFSURI);
  341.               break;
  342.             }
  343.             case PI_SOCKS_PROXY_HOST: {
  344.               String newSocksProxyURI =
  345.                   String.format("%s:%s", socksProxyHost, socksProxyPort);
  346.               notifyChange(null, ConfProp.SOCKS_SERVER, newSocksProxyURI);
  347.               break;
  348.             }
  349.             case PI_SOCKS_PROXY_PORT: {
  350.               String newSocksProxyURI =
  351.                   String.format("%s:%s", socksProxyHost, socksProxyPort);
  352.               notifyChange(null, ConfProp.SOCKS_SERVER, newSocksProxyURI);
  353.               break;
  354.             }
  355.             case JOB_TRACKER_URI: {
  356.               String[] strs = jobTrackerURI.split(":", 2);
  357.               String host = strs[0];
  358.               String port = (strs.length == 2) ? strs[1] : "";
  359.               notifyChange(null, ConfProp.PI_JOB_TRACKER_HOST, host);
  360.               notifyChange(null, ConfProp.PI_JOB_TRACKER_PORT, port);
  361.               break;
  362.             }
  363.             case FS_DEFAULT_URI: {
  364.               try {
  365.                 URI uri = new URI(fsDefaultURI);
  366.                 if (uri.getScheme().equals("hdfs")) {
  367.                   String host = uri.getHost();
  368.                   String port = Integer.toString(uri.getPort());
  369.                   notifyChange(null, ConfProp.PI_NAME_NODE_HOST, host);
  370.                   notifyChange(null, ConfProp.PI_NAME_NODE_PORT, port);
  371.                 }
  372.               } catch (URISyntaxException use) {
  373.                 // Ignore the update!
  374.               }
  375.               break;
  376.             }
  377.             case SOCKS_SERVER: {
  378.               String[] strs = socksServerURI.split(":", 2);
  379.               String host = strs[0];
  380.               String port = (strs.length == 2) ? strs[1] : "";
  381.               notifyChange(null, ConfProp.PI_SOCKS_PROXY_HOST, host);
  382.               notifyChange(null, ConfProp.PI_SOCKS_PROXY_PORT, port);
  383.               break;
  384.             }
  385.             case PI_COLOCATE_MASTERS: {
  386.               if (colocate)
  387.                 notifyChange(null, ConfProp.PI_NAME_NODE_HOST,
  388.                     jobTrackerHost);
  389.               break;
  390.             }
  391.             case PI_SOCKS_PROXY_ENABLE: {
  392.               if (socksProxyEnable) {
  393.                 notifyChange(null, ConfProp.SOCKET_FACTORY_DEFAULT,
  394.                     "org.apache.hadoop.net.SocksSocketFactory");
  395.               } else {
  396.                 notifyChange(null, ConfProp.SOCKET_FACTORY_DEFAULT,
  397.                 "org.apache.hadoop.net.StandardSocketFactory");
  398.               }
  399.               break;
  400.             }
  401.           }
  402.         }
  403.       });
  404.     }
  405.     /**
  406.      * Change notifications on properties (by name). A property might not be
  407.      * reflected as a ConfProp enum. If it is, the notification is forwarded
  408.      * to the ConfProp notifyChange method. If not, it is processed here.
  409.      * 
  410.      * @param source
  411.      * @param propName
  412.      * @param propValue
  413.      */
  414.     void notifyChange(TabListener source, String propName, String propValue) {
  415.       ConfProp prop = ConfProp.getByName(propName);
  416.       if (prop != null)
  417.         notifyChange(source, prop, propValue);
  418.       location.setConfProp(propName, propValue);
  419.     }
  420.     /**
  421.      * Broadcast a property change to all registered tabs. If a tab is
  422.      * identified as the source of the change, this tab will not be notified.
  423.      * 
  424.      * @param source TODO
  425.      * @param prop
  426.      * @param value
  427.      */
  428.     private void fireChange(TabListener source, ConfProp prop, String value) {
  429.       for (TabListener tab : tabs) {
  430.         if (tab != source)
  431.           tab.notifyChange(prop, value);
  432.       }
  433.     }
  434.   }
  435.   /**
  436.    * Create a SWT Text component for the given {@link ConfProp} text
  437.    * configuration property.
  438.    * 
  439.    * @param listener
  440.    * @param parent
  441.    * @param prop
  442.    * @return
  443.    */
  444.   private Text createConfText(ModifyListener listener, Composite parent,
  445.       ConfProp prop) {
  446.     Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
  447.     GridData data = new GridData(GridData.FILL_HORIZONTAL);
  448.     text.setLayoutData(data);
  449.     text.setData("hProp", prop);
  450.     text.setText(location.getConfProp(prop));
  451.     text.addModifyListener(listener);
  452.     return text;
  453.   }
  454.   /**
  455.    * Create a SWT Checked Button component for the given {@link ConfProp}
  456.    * boolean configuration property.
  457.    * 
  458.    * @param listener
  459.    * @param parent
  460.    * @param prop
  461.    * @return
  462.    */
  463.   private Button createConfCheckButton(SelectionListener listener,
  464.       Composite parent, ConfProp prop, String text) {
  465.     Button button = new Button(parent, SWT.CHECK);
  466.     button.setText(text);
  467.     button.setData("hProp", prop);
  468.     button.setSelection(location.getConfProp(prop).equalsIgnoreCase("yes"));
  469.     button.addSelectionListener(listener);
  470.     return button;
  471.   }
  472.   /**
  473.    * Create editor entry for the given configuration property. The editor is
  474.    * a couple (Label, Text).
  475.    * 
  476.    * @param listener the listener to trigger on property change
  477.    * @param parent the SWT parent container
  478.    * @param prop the property to create an editor for
  479.    * @param labelText a label (null will defaults to the property name)
  480.    * 
  481.    * @return a SWT Text field
  482.    */
  483.   private Text createConfLabelText(ModifyListener listener,
  484.       Composite parent, ConfProp prop, String labelText) {
  485.     Label label = new Label(parent, SWT.NONE);
  486.     if (labelText == null)
  487.       labelText = prop.name;
  488.     label.setText(labelText);
  489.     return createConfText(listener, parent, prop);
  490.   }
  491.   /**
  492.    * Create an editor entry for the given configuration name
  493.    * 
  494.    * @param listener the listener to trigger on property change
  495.    * @param parent the SWT parent container
  496.    * @param propName the name of the property to create an editor for
  497.    * @param labelText a label (null will defaults to the property name)
  498.    * 
  499.    * @return a SWT Text field
  500.    */
  501.   private Text createConfNameEditor(ModifyListener listener,
  502.       Composite parent, String propName, String labelText) {
  503.     {
  504.       ConfProp prop = ConfProp.getByName(propName);
  505.       if (prop != null)
  506.         return createConfLabelText(listener, parent, prop, labelText);
  507.     }
  508.     Label label = new Label(parent, SWT.NONE);
  509.     if (labelText == null)
  510.       labelText = propName;
  511.     label.setText(labelText);
  512.     Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
  513.     GridData data = new GridData(GridData.FILL_HORIZONTAL);
  514.     text.setLayoutData(data);
  515.     text.setData("hPropName", propName);
  516.     text.setText(location.getConfProp(propName));
  517.     text.addModifyListener(listener);
  518.     return text;
  519.   }
  520.   /**
  521.    * Main parameters of the Hadoop location:
  522.    * <li> host and port of the Map/Reduce master (Job tracker)
  523.    * <li> host and port of the DFS master (Name node)
  524.    * <li> SOCKS proxy
  525.    */
  526.   private class TabMain implements TabListener, ModifyListener,
  527.       SelectionListener {
  528.     TabMediator mediator;
  529.     Text locationName;
  530.     Text textJTHost;
  531.     Text textNNHost;
  532.     Button colocateMasters;
  533.     Text textJTPort;
  534.     Text textNNPort;
  535.     Text userName;
  536.     Button useSocksProxy;
  537.     Text socksProxyHost;
  538.     Text socksProxyPort;
  539.     TabMain(TabMediator mediator) {
  540.       this.mediator = mediator;
  541.       TabItem tab = new TabItem(mediator.folder, SWT.NONE);
  542.       tab.setText("General");
  543.       tab.setToolTipText("General location parameters");
  544.       tab.setImage(circle);
  545.       tab.setControl(createControl(mediator.folder));
  546.     }
  547.     private Control createControl(Composite parent) {
  548.       Composite panel = new Composite(parent, SWT.FILL);
  549.       panel.setLayout(new GridLayout(2, false));
  550.       GridData data;
  551.       /*
  552.        * Location name
  553.        */
  554.       {
  555.         Composite subpanel = new Composite(panel, SWT.FILL);
  556.         subpanel.setLayout(new GridLayout(2, false));
  557.         data = new GridData();
  558.         data.horizontalSpan = 2;
  559.         data.horizontalAlignment = SWT.FILL;
  560.         subpanel.setLayoutData(data);
  561.         locationName =
  562.             createConfLabelText(this, subpanel, ConfProp.PI_LOCATION_NAME,
  563.                 "&Location name:");
  564.       }
  565.       /*
  566.        * Map/Reduce group
  567.        */
  568.       {
  569.         Group groupMR = new Group(panel, SWT.SHADOW_NONE);
  570.         groupMR.setText("Map/Reduce Master");
  571.         groupMR.setToolTipText("Address of the Map/Reduce master node "
  572.             + "(the Job Tracker).");
  573.         GridLayout layout = new GridLayout(2, false);
  574.         groupMR.setLayout(layout);
  575.         data = new GridData();
  576.         data.verticalAlignment = SWT.FILL;
  577.         data.horizontalAlignment = SWT.CENTER;
  578.         data.widthHint = 250;
  579.         groupMR.setLayoutData(data);
  580.         // Job Tracker host
  581.         Label label = new Label(groupMR, SWT.NONE);
  582.         label.setText("Host:");
  583.         data =
  584.             new GridData(GridData.BEGINNING, GridData.CENTER, false, true);
  585.         label.setLayoutData(data);
  586.         textJTHost =
  587.             createConfText(this, groupMR, ConfProp.PI_JOB_TRACKER_HOST);
  588.         data = new GridData(GridData.FILL, GridData.CENTER, true, true);
  589.         textJTHost.setLayoutData(data);
  590.         // Job Tracker port
  591.         label = new Label(groupMR, SWT.NONE);
  592.         label.setText("Port:");
  593.         data =
  594.             new GridData(GridData.BEGINNING, GridData.CENTER, false, true);
  595.         label.setLayoutData(data);
  596.         textJTPort =
  597.             createConfText(this, groupMR, ConfProp.PI_JOB_TRACKER_PORT);
  598.         data = new GridData(GridData.FILL, GridData.CENTER, true, true);
  599.         textJTPort.setLayoutData(data);
  600.       }
  601.       /*
  602.        * DFS group
  603.        */
  604.       {
  605.         Group groupDFS = new Group(panel, SWT.SHADOW_NONE);
  606.         groupDFS.setText("DFS Master");
  607.         groupDFS.setToolTipText("Address of the Distributed FileSystem "
  608.             + "master node (the Name Node).");
  609.         GridLayout layout = new GridLayout(2, false);
  610.         groupDFS.setLayout(layout);
  611.         data = new GridData();
  612.         data.horizontalAlignment = SWT.CENTER;
  613.         data.widthHint = 250;
  614.         groupDFS.setLayoutData(data);
  615.         colocateMasters =
  616.             createConfCheckButton(this, groupDFS,
  617.                 ConfProp.PI_COLOCATE_MASTERS, "Use M/R Master host");
  618.         data = new GridData();
  619.         data.horizontalSpan = 2;
  620.         colocateMasters.setLayoutData(data);
  621.         // Job Tracker host
  622.         Label label = new Label(groupDFS, SWT.NONE);
  623.         data = new GridData();
  624.         label.setText("Host:");
  625.         label.setLayoutData(data);
  626.         textNNHost =
  627.             createConfText(this, groupDFS, ConfProp.PI_NAME_NODE_HOST);
  628.         // Job Tracker port
  629.         label = new Label(groupDFS, SWT.NONE);
  630.         data = new GridData();
  631.         label.setText("Port:");
  632.         label.setLayoutData(data);
  633.         textNNPort =
  634.             createConfText(this, groupDFS, ConfProp.PI_NAME_NODE_PORT);
  635.       }
  636.       {
  637.         Composite subpanel = new Composite(panel, SWT.FILL);
  638.         subpanel.setLayout(new GridLayout(2, false));
  639.         data = new GridData();
  640.         data.horizontalSpan = 2;
  641.         data.horizontalAlignment = SWT.FILL;
  642.         subpanel.setLayoutData(data);
  643.         userName =
  644.             createConfLabelText(this, subpanel, ConfProp.PI_USER_NAME,
  645.                 "&User name:");
  646.       }
  647.       // SOCKS proxy group
  648.       {
  649.         Group groupSOCKS = new Group(panel, SWT.SHADOW_NONE);
  650.         groupSOCKS.setText("SOCKS proxy");
  651.         groupSOCKS.setToolTipText("Address of the SOCKS proxy to use "
  652.             + "to connect to the infrastructure.");
  653.         GridLayout layout = new GridLayout(2, false);
  654.         groupSOCKS.setLayout(layout);
  655.         data = new GridData();
  656.         data.horizontalAlignment = SWT.CENTER;
  657.         data.horizontalSpan = 2;
  658.         data.widthHint = 250;
  659.         groupSOCKS.setLayoutData(data);
  660.         useSocksProxy =
  661.             createConfCheckButton(this, groupSOCKS,
  662.                 ConfProp.PI_SOCKS_PROXY_ENABLE, "Enable SOCKS proxy");
  663.         data = new GridData();
  664.         data.horizontalSpan = 2;
  665.         useSocksProxy.setLayoutData(data);
  666.         // SOCKS proxy host
  667.         Label label = new Label(groupSOCKS, SWT.NONE);
  668.         data = new GridData();
  669.         label.setText("Host:");
  670.         label.setLayoutData(data);
  671.         socksProxyHost =
  672.             createConfText(this, groupSOCKS, ConfProp.PI_SOCKS_PROXY_HOST);
  673.         // SOCKS proxy port
  674.         label = new Label(groupSOCKS, SWT.NONE);
  675.         data = new GridData();
  676.         label.setText("Port:");
  677.         label.setLayoutData(data);
  678.         socksProxyPort =
  679.             createConfText(this, groupSOCKS, ConfProp.PI_SOCKS_PROXY_PORT);
  680.       }
  681.       // Update the state of all widgets according to the current values!
  682.       reloadConfProp(ConfProp.PI_COLOCATE_MASTERS);
  683.       reloadConfProp(ConfProp.PI_SOCKS_PROXY_ENABLE);
  684.       reloadConfProp(ConfProp.PI_JOB_TRACKER_HOST);
  685.       return panel;
  686.     }
  687.     /**
  688.      * Reload the given configuration property value
  689.      * 
  690.      * @param prop
  691.      */
  692.     private void reloadConfProp(ConfProp prop) {
  693.       this.notifyChange(prop, location.getConfProp(prop));
  694.     }
  695.     public void notifyChange(ConfProp prop, String propValue) {
  696.       switch (prop) {
  697.         case PI_JOB_TRACKER_HOST: {
  698.           textJTHost.setText(propValue);
  699.           break;
  700.         }
  701.         case PI_JOB_TRACKER_PORT: {
  702.           textJTPort.setText(propValue);
  703.           break;
  704.         }
  705.         case PI_LOCATION_NAME: {
  706.           locationName.setText(propValue);
  707.           break;
  708.         }
  709.         case PI_USER_NAME: {
  710.           userName.setText(propValue);
  711.           break;
  712.         }
  713.         case PI_COLOCATE_MASTERS: {
  714.           if (colocateMasters != null) {
  715.             boolean colocate = propValue.equalsIgnoreCase("yes");
  716.             colocateMasters.setSelection(colocate);
  717.             if (textNNHost != null) {
  718.               textNNHost.setEnabled(!colocate);
  719.             }
  720.           }
  721.           break;
  722.         }
  723.         case PI_NAME_NODE_HOST: {
  724.           textNNHost.setText(propValue);
  725.           break;
  726.         }
  727.         case PI_NAME_NODE_PORT: {
  728.           textNNPort.setText(propValue);
  729.           break;
  730.         }
  731.         case PI_SOCKS_PROXY_ENABLE: {
  732.           if (useSocksProxy != null) {
  733.             boolean useProxy = propValue.equalsIgnoreCase("yes");
  734.             useSocksProxy.setSelection(useProxy);
  735.             if (socksProxyHost != null)
  736.               socksProxyHost.setEnabled(useProxy);
  737.             if (socksProxyPort != null)
  738.               socksProxyPort.setEnabled(useProxy);
  739.           }
  740.           break;
  741.         }
  742.         case PI_SOCKS_PROXY_HOST: {
  743.           socksProxyHost.setText(propValue);
  744.           break;
  745.         }
  746.         case PI_SOCKS_PROXY_PORT: {
  747.           socksProxyPort.setText(propValue);
  748.           break;
  749.         }
  750.       }
  751.     }
  752.     /* @inheritDoc */
  753.     public void modifyText(ModifyEvent e) {
  754.       final Text text = (Text) e.widget;
  755.       final ConfProp prop = (ConfProp) text.getData("hProp");
  756.       Display.getDefault().syncExec(new Runnable() {
  757.         public void run() {
  758.           mediator.notifyChange(TabMain.this, prop, text.getText());
  759.         }
  760.       });
  761.     }
  762.     /* @inheritDoc */
  763.     public void widgetDefaultSelected(SelectionEvent e) {
  764.       this.widgetSelected(e);
  765.     }
  766.     /* @inheritDoc */
  767.     public void widgetSelected(SelectionEvent e) {
  768.       final Button button = (Button) e.widget;
  769.       final ConfProp prop = (ConfProp) button.getData("hProp");
  770.       Display.getDefault().syncExec(new Runnable() {
  771.         public void run() {
  772.           // We want to receive the update also!
  773.           mediator.notifyChange(null, prop, button.getSelection() ? "yes"
  774.               : "no");
  775.         }
  776.       });
  777.     }
  778.   }
  779.   private class TabAdvanced implements TabListener, ModifyListener {
  780.     TabMediator mediator;
  781.     private Composite panel;
  782.     private Map<String, Text> textMap = new TreeMap<String, Text>();
  783.     TabAdvanced(TabMediator mediator) {
  784.       this.mediator = mediator;
  785.       TabItem tab = new TabItem(mediator.folder, SWT.NONE);
  786.       tab.setText("Advanced parameters");
  787.       tab.setToolTipText("Access to advanced Hadoop parameters");
  788.       tab.setImage(circle);
  789.       tab.setControl(createControl(mediator.folder));
  790.     }
  791.     private Control createControl(Composite parent) {
  792.       ScrolledComposite sc =
  793.           new ScrolledComposite(parent, SWT.BORDER | SWT.H_SCROLL
  794.               | SWT.V_SCROLL);
  795.       panel = new Composite(sc, SWT.NONE);
  796.       sc.setContent(panel);
  797.       sc.setExpandHorizontal(true);
  798.       sc.setExpandVertical(true);
  799.       sc.setMinSize(640, 480);
  800.       GridLayout layout = new GridLayout();
  801.       layout.numColumns = 2;
  802.       layout.makeColumnsEqualWidth = false;
  803.       panel.setLayout(layout);
  804.       panel.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,
  805.           true, 1, 1));
  806.       // Sort by property name
  807.       Configuration config = location.getConfiguration();
  808.       SortedMap<String, String> map = new TreeMap<String, String>();
  809.       Iterator<Entry<String, String>> it = config.iterator();
  810.       while (it.hasNext()) {
  811.         Entry<String, String> entry = it.next();
  812.         map.put(entry.getKey(), entry.getValue());
  813.       }
  814.       for (Entry<String, String> entry : map.entrySet()) {
  815.         Text text = createConfNameEditor(this, panel, entry.getKey(), null);
  816.         textMap.put(entry.getKey(), text);
  817.       }
  818.       sc.setMinSize(panel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
  819.       return sc;
  820.     }
  821.     public void notifyChange(ConfProp prop, final String propValue) {
  822.       Text text = textMap.get(prop.name);
  823.       text.setText(propValue);
  824.     }
  825.     public void modifyText(ModifyEvent e) {
  826.       final Text text = (Text) e.widget;
  827.       Object hProp = text.getData("hProp");
  828.       final ConfProp prop = (hProp != null) ? (ConfProp) hProp : null;
  829.       Object hPropName = text.getData("hPropName");
  830.       final String propName =
  831.           (hPropName != null) ? (String) hPropName : null;
  832.       Display.getDefault().syncExec(new Runnable() {
  833.         public void run() {
  834.           if (prop != null)
  835.             mediator.notifyChange(TabAdvanced.this, prop, text.getText());
  836.           else
  837.             mediator
  838.                 .notifyChange(TabAdvanced.this, propName, text.getText());
  839.         }
  840.       });
  841.     }
  842.   }
  843. }