Package org.nebulaframework.ui.swing.cluster

Source Code of org.nebulaframework.ui.swing.cluster.ClusterMainUI

/*
* Copyright (C) 2008 Yohan Liyanage.
*
* Licensed 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.nebulaframework.ui.swing.cluster;

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextPane;
import javax.swing.JWindow;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nebulaframework.core.job.GridJob;
import org.nebulaframework.core.job.GridJobState;
import org.nebulaframework.core.job.GridJobStateListener;
import org.nebulaframework.core.job.splitaggregate.SplitAggregateGridJob;
import org.nebulaframework.core.job.unbounded.UnboundedGridJob;
import org.nebulaframework.grid.Grid;
import org.nebulaframework.grid.cluster.manager.ClusterManager;
import org.nebulaframework.grid.cluster.manager.services.jobs.GridJobProfile;
import org.nebulaframework.grid.cluster.manager.services.jobs.InternalClusterJobService;
import org.nebulaframework.grid.cluster.node.delegate.GridNodeDelegate;
import org.nebulaframework.grid.service.event.ServiceEventsSupport;
import org.nebulaframework.grid.service.event.ServiceHookCallback;
import org.nebulaframework.grid.service.message.ServiceMessage;
import org.nebulaframework.grid.service.message.ServiceMessageType;
import org.nebulaframework.ui.swing.AboutDialog;
import org.nebulaframework.ui.swing.UISupport;
import org.nebulaframework.util.log4j.JLabelAppender;
import org.nebulaframework.util.log4j.JTextPaneAppender;
import org.nebulaframework.util.profiling.TimeUtils;
import org.springframework.util.StringUtils;

/**
* The Swing UI for the ClusterManager.
* This UI exposes basic functionality of ClusterManager,
* and allows users to easily manage the Cluster.
* <p>
* However, for more advanced uses, such as embedding
* ClusterManager, consider using the API.
*
* @author Yohan Liyanage
* @version 1.0
*/
public class ClusterMainUI extends JFrame {

  private static Log log = LogFactory.getLog(ClusterMainUI.class);
 
  private static final int WIDTH = 600;
  private static final int HEIGHT = 475;

  private static final long serialVersionUID = 8992643609753054554L;
  private static Map<String, JComponent> components = new HashMap<String, JComponent>();

  private TrayIcon trayIcon;
 
  private Image idleIcon;
  private Image activeIcon;
 
  /**
   * Constructs the UI for ClusterManager.
   * Note that to construct the UI, the Grid should be
   * started and ClusterManager should be running.
   *
   * @throws HeadlessException if UI not supported
   * @throws IllegalStateException if ClusterManager is not running
   */
  public ClusterMainUI() throws HeadlessException, IllegalStateException {
    super();
   
    if (!Grid.isClusterManager()) {
      throw new IllegalStateException("ClusterManager is not running");
    }
    setupUI();
    showClusterInfo();
  }

 
  /**
   * Primary UI Setup Operations
   */
  private void setupUI() {

    setTitle("Nebula Grid - Cluster Manager");
    setSize(WIDTH, HEIGHT);

    /* -- Menu Bar -- */
    setJMenuBar(setupMenu());

    /* -- Content -- */

    setLayout(new BorderLayout());

    JPanel centerPanel = new JPanel();
   
    add(centerPanel, BorderLayout.CENTER);
   

    /* -- Setup Tabs -- */
    centerPanel.setLayout(new BorderLayout());
    JTabbedPane tabs = new JTabbedPane();
    tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
    centerPanel.add(tabs);
    addUIElement("tabs",tabs)// Add to components map
   
    // General Tab
    tabs.addTab("General", setupGeneralTab());
   
    setupTrayIcon(this);
   
   
    // Create Job Start Hook
    ServiceEventsSupport.addServiceHook(new ServiceHookCallback() {
      public void onServiceEvent(final ServiceMessage message) {
        createJobTab(message.getMessage());
      }
    },ServiceMessageType.JOB_START);
  }


  /**
   * System Tray Icon setup
   * @param frame owner JFrame
   */
  private void setupTrayIcon(final JFrame frame) {
   
    // Idle Icon
    idleIcon = Toolkit.getDefaultToolkit()
      .getImage(ClassLoader.getSystemResource("META-INF/resources/cluster_inactive.png"));
   
    // Active Icon
    activeIcon = Toolkit.getDefaultToolkit()
      .getImage(ClassLoader.getSystemResource("META-INF/resources/cluster_active.png"));
   
    frame.setIconImage(idleIcon);
   
    // If system tray is supported by OS
    if (SystemTray.isSupported()) {
     
      // Set Icon
      trayIcon = new TrayIcon(idleIcon,"Nebula Grid Cluster", createTrayPopup());
      trayIcon.setImageAutoSize(true);
      trayIcon.addMouseListener(new MouseAdapter() {

        @Override
        public void mouseClicked(MouseEvent e) {
          if (e.getButton()==MouseEvent.BUTTON1) {
            if (!frame.isVisible()) {
              frame.setVisible(true);
            }
           
            frame.setExtendedState(JFrame.NORMAL);
            frame.requestFocus();
            frame.toFront();
          }
        }
       
      });
     
      try {
        SystemTray.getSystemTray().add(trayIcon);
      } catch (AWTException ae) {
        log.debug("[UI] Unable to Initialize Tray Icon");
        return;
      }
     
      frame.addWindowListener(new WindowAdapter() {

        @Override
        public void windowIconified(WindowEvent e) {
          // Hide (can be shown using tray icon)
          frame.setVisible(false);
        }
       
      });
    }
 
  }

  /**
   * Creates the Pop-up menu for System Tray Icon
   *
   * @return PopupMenu
   */
  private PopupMenu createTrayPopup() {
   
   
    PopupMenu trayPopup = new PopupMenu();

    // About
    MenuItem aboutItem = new MenuItem("About");
    aboutItem.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        showAbout();
      }
     
    });
    trayPopup.add(aboutItem);
   
    trayPopup.addSeparator();
   
    // Shutdown
    MenuItem shutdownItem = new MenuItem("Shutdown");
    shutdownItem.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        doShutdownCluster();
      }
     
    });
    trayPopup.add(shutdownItem);
   
    return trayPopup;
  }

  /**
   * Displays the Busy Icon on SystemTray
   */
  private void showBusyIcon() {
    if (trayIcon!=null) trayIcon.setImage(activeIcon);
  }
 
  /**
   * Displays the Idle icon on SystemTray
   */
  private void showIdleIcon() {
    if (trayIcon!=null) trayIcon.setImage(idleIcon);
  }

  /**
   * Removes System Tray icon.
   */
  private void removeIcon() {
    if (SystemTray.isSupported()) {
      SystemTray.getSystemTray().remove(trayIcon);
    }
  }
 
  /**
   * Setups the Menu Bar
   * @return
   */
  private JMenuBar setupMenu() {
    JMenuBar menuBar = new JMenuBar();

    /* -- Cluster Menu -- */
    JMenu clusterMenu = new JMenu("Cluster");
    clusterMenu.setMnemonic(KeyEvent.VK_C);
    menuBar.add(clusterMenu);

   
    // Discover Submenu
    JMenu clusterDiscoverMenu = new JMenu("Disover Peers");
    clusterDiscoverMenu.setMnemonic(KeyEvent.VK_D);
    clusterMenu.add(clusterDiscoverMenu);
   
    // Discover -> Multicast
    JMenuItem clusterDiscoverMulticast = new JMenuItem("Multicast");
    clusterDiscoverMulticast.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F9,0));
    clusterDiscoverMulticast.setEnabled(false);
    clusterDiscoverMulticast.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        doDiscoverMulticast();
      }
    });
    clusterDiscoverMenu.add(clusterDiscoverMulticast);
    addUIElement("menu.cluster.discover.multicast", clusterDiscoverMulticast)// Add to components map
   
    // Discover -> WS
    JMenuItem clusterDiscoverWS = new JMenuItem("Colombus Web Service");
    clusterDiscoverWS.setEnabled(false);
    clusterDiscoverWS.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F10,0));
    clusterDiscoverWS.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        doDiscoverWS();
      }
    });
    clusterDiscoverMenu.add(clusterDiscoverWS);
    addUIElement("menu.cluster.discover.ws",clusterDiscoverWS)// Add to components map
   
    clusterMenu.addSeparator();

    // Cluster-> Shutdown
    JMenuItem clusterShutdownItem = new JMenuItem("Shutdown", 'u');
    clusterShutdownItem.setAccelerator(KeyStroke
        .getKeyStroke(KeyEvent.VK_F6, 0));
    clusterShutdownItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        doShutdownCluster();
      }
    });
    clusterMenu.add(clusterShutdownItem);
    addUIElement("menu.cluster.shutdown",clusterShutdownItem)// Add to components map
   
   
    /* -- Options Menu -- */
    JMenu optionsMenu = new JMenu("Options");
    optionsMenu.setMnemonic(KeyEvent.VK_O);
    menuBar.add(optionsMenu);
   
    // Configuration
    JMenuItem optionsConfigItem = new JMenuItem("Configuration...", 'C');
    optionsConfigItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        showConfiguration();
      }
    });
    optionsMenu.add(optionsConfigItem);
    optionsConfigItem.setEnabled(false)// TODO Create Configuration Options
   
   
    /* -- Help Menu -- */
    JMenu helpMenu = new JMenu("Help");
    helpMenu.setMnemonic(KeyEvent.VK_H);
    menuBar.add(helpMenu);
   
    // Help Contents
    JMenuItem helpContentsItem = new JMenuItem("Help Contents", 'H');
    helpContentsItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
    helpContentsItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        showHelp();
      }
    });
    helpMenu.add(helpContentsItem);
   
    helpMenu.addSeparator();
   
    JMenuItem helpAboutItem = new JMenuItem("About", 'A');
    helpAboutItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        showAbout();
      }
    });
    helpMenu.add(helpAboutItem);
   
    return menuBar;
  }


  /**
   * Setup the General Tab Pane
   *
   * @return JPanel for pane
   */
  private JPanel setupGeneralTab() {

    JPanel generalTab = new JPanel();
    generalTab.setLayout(new BorderLayout());

    /* -- Create Main Panels -- */

    JPanel centerPanel = new JPanel();
    JPanel northPanel = new JPanel();
    JPanel southPanel = new JPanel();
   
    generalTab.add(centerPanel, BorderLayout.CENTER);
    generalTab.add(northPanel, BorderLayout.NORTH);

    /* -- Create Center Contents -- */

    // Statistics Panel
    JPanel statsPanel = setupStatsPanel();

    // Log Panel
    JPanel logPanel = new JPanel();
    logPanel.setLayout(new BorderLayout());
    logPanel.setBorder(BorderFactory.createTitledBorder("Log Output"));
    JTextPane logTextPane = new JTextPane();
    logTextPane.setEditable(false);
    logTextPane.setBackground(Color.BLACK);
    logTextPane.setForeground(Color.WHITE);
   
    logPanel.add(new JScrollPane(logTextPane,
        ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
        ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
            BorderLayout.CENTER);
    addUIElement("general.log", logTextPane)// Add to component map
   
    JPanel logOptionsPanel = new JPanel();
    logPanel.add(logOptionsPanel, BorderLayout.SOUTH);
    logOptionsPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
   
    final JCheckBox logScrollCheckbox = new JCheckBox("Auto-Scroll Log");
    logScrollCheckbox.setSelected(true);
    logScrollCheckbox.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        JTextPaneAppender.setAutoScroll(logScrollCheckbox.isSelected());
      }
     
    });
    logOptionsPanel.add(logScrollCheckbox);
   
   
    // Enable Logging
    JTextPaneAppender.setTextPane(logTextPane);
   
    centerPanel.setLayout(new BorderLayout(10, 10));
    centerPanel.add(statsPanel, BorderLayout.NORTH);
    centerPanel.add(logPanel, BorderLayout.CENTER);

    /* -- Create Buttons (South) -- */
   
    generalTab.add(southPanel, BorderLayout.SOUTH);

    final JButton shutdownButton = new JButton("Shutdown");
    shutdownButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        doShutdownCluster();
      }
    });

    southPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 10));
    southPanel.add(shutdownButton);
    addUIElement("general.shutdown", shutdownButton)// Add to components map
   
    return generalTab;
  }

  /**
   * Setup the Statistics Panel of General Pane
   *
   * @return JPanel for Stats
   */
  private JPanel setupStatsPanel() {

    JPanel statPanel = new JPanel();
    statPanel.setLayout(new GridLayout(0, 2, 10, 10));

    JPanel clusterInfoPanel = new JPanel();
    clusterInfoPanel.setLayout(new GridLayout(0, 2, 10, 10));
    clusterInfoPanel.setBorder(BorderFactory
        .createTitledBorder("Cluster Information"));
    statPanel.add(clusterInfoPanel);

    JPanel gridInfoPanel = new JPanel();
    gridInfoPanel.setLayout(new GridLayout(0, 2, 10, 10));
    gridInfoPanel.setBorder(BorderFactory
        .createTitledBorder("Grid Information"));
    statPanel.add(gridInfoPanel);

    /* -- Cluster Information -- */

    // ClusterID
    JLabel clusterIDLabel = new JLabel("Cluster ID :");
    clusterInfoPanel.add(clusterIDLabel);
    JLabel clusterID = new JLabel("#clusterId#");
    clusterInfoPanel.add(clusterID);
    addUIElement("general.stats.clusterid", clusterID)// Add to components map
   
    // Host Information (ex. localhost:61616)
    JLabel hostInfoLabel = new JLabel("Host Information :");
    clusterInfoPanel.add(hostInfoLabel);
    JLabel hostInfo = new JLabel("#hostInfo#");
    clusterInfoPanel.add(hostInfo);
    addUIElement("general.stats.hostinfo", hostInfo)// Add to components map
   
    // Protocol Information
    JLabel protocolsLabel = new JLabel("Protocols :");
    clusterInfoPanel.add(protocolsLabel);
    JLabel protocols = new JLabel("#protocols#");
    clusterInfoPanel.add(protocols);
    addUIElement("general.stats.protocols", protocols)// Add to components map
   
    // Cluster Up Time
    JLabel upTimeLabel = new JLabel("Cluster Up Time :");
    clusterInfoPanel.add(upTimeLabel);
    JLabel upTime = new JLabel("#upTime#");
    clusterInfoPanel.add(upTime);
    addUIElement("general.stats.uptime", upTime)// Add to components map
   
    /* -- Grid Information -- */

    // Peer Cluster Count
    JLabel peerClustersLabel = new JLabel("Peer Clusters :");
    gridInfoPanel.add(peerClustersLabel);
    JLabel peerClusters = new JLabel("#peerClusters#");
    gridInfoPanel.add(peerClusters);
    addUIElement("general.stats.peerclusters", peerClusters)// Add to components map
   
    // Node Count
    JLabel nodesLabel = new JLabel("Nodes in Cluster :");
    gridInfoPanel.add(nodesLabel);
    JLabel nodes = new JLabel("#nodes#");
    gridInfoPanel.add(nodes);
    addUIElement("general.stats.nodes", nodes)// Add to components map
   
    // Jobs Done Count
    JLabel jobsDoneLabel = new JLabel("Executed Jobs :");
    gridInfoPanel.add(jobsDoneLabel);
    JLabel jobsDone = new JLabel("#jobsdone#");
    gridInfoPanel.add(jobsDone);
    addUIElement("general.stats.jobsdone", jobsDone)// Add to components map
   
    // Active Jobs
    JLabel activeJobsLabel = new JLabel("Active Jobs :");
    gridInfoPanel.add(activeJobsLabel);
    JLabel activeJobs = new JLabel("#activeJobs#");
    gridInfoPanel.add(activeJobs);
    addUIElement("general.stats.activejobs", activeJobs)// Add to components map
   
    return statPanel;
  }

  /**
   * Creates a tab pane for the given GridJob.
   *
   * @param jobId JobId
   */
  protected void createJobTab(final String jobId) {
   
   
    // Request Job Profile
    final InternalClusterJobService jobService = ClusterManager.getInstance().getJobService();
    final GridJobProfile profile = jobService.getProfile(jobId);
   
    // Job Start Time
    final long startTime = System.currentTimeMillis();
   
    final JPanel jobPanel = new JPanel();
    jobPanel.setLayout(new BorderLayout(10,10));
   
    // Progess Panel
    JPanel progressPanel = new JPanel();
    progressPanel.setLayout(new BorderLayout(10,10));
    progressPanel.setBorder(BorderFactory.createTitledBorder("Progress"));
    jobPanel.add(progressPanel, BorderLayout.NORTH);
   
    final JProgressBar progressBar = new JProgressBar();
    progressBar.setStringPainted(true);
    progressPanel.add(progressBar, BorderLayout.CENTER);
    addUIElement("jobs."+jobId+".progress", progressBar)// Add to components map
   
    // Buttons Panel
    JPanel buttonsPanel = new JPanel();
    jobPanel.add(buttonsPanel, BorderLayout.SOUTH);
    buttonsPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
   
    // Terminate Button
    JButton terminateButton = new JButton("Terminate");
    terminateButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        new Thread(new Runnable() {

          public void run() {

            // Job Name = Class Name
            String name = profile.getJob().getClass().getSimpleName();
           
            // Request user confirmation
            int option = JOptionPane.showConfirmDialog(ClusterMainUI.this,
                                                              "Are you sure to terminate GridJob "
                                                       + name + "?",
                                                       "Nebula - Terminate GridJob",
                                                       JOptionPane.YES_NO_OPTION);
           
            if (option == JOptionPane.NO_OPTION) return;
           
            // Attempt Cancel
            boolean result = profile.getFuture().cancel();
           
            // Notify results
            if (result) {
              JOptionPane.showMessageDialog(ClusterMainUI.this, "Grid Job '" +
                                            name +
                                            "terminated successfully.", "Nebula - Job Terminated",
                                            JOptionPane.INFORMATION_MESSAGE);
            }
            else {
              JOptionPane.showMessageDialog(ClusterMainUI.this, "Failed to terminate Grid Job '" +
                                            name
                                            , "Nebula - Job Termination Failed",
                                            JOptionPane.WARNING_MESSAGE);
            }           
          }
         
        }).start();
      }
    });
    buttonsPanel.add(terminateButton);
    addUIElement("jobs."+jobId+".terminate", terminateButton)// Add to components map
   
    // Close Tab Button
    JButton closeButton = new JButton("Close Tab");
    closeButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            removeJobTab(jobId);
          }
        });
      }
    });
    closeButton.setEnabled(false);
   
    buttonsPanel.add(closeButton);
    addUIElement("jobs."+jobId+".closetab", closeButton)// Add to components map
   
    JPanel centerPanel = new JPanel();
    centerPanel.setLayout(new GridBagLayout());
    jobPanel.add(centerPanel, BorderLayout.CENTER);
   
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.BOTH;
    c.weightx = 1.0;
    c.weightx = 1.0;
   
    /* -- Job Information -- */
   
    JPanel jobInfoPanel = new JPanel();
    jobInfoPanel.setBorder(BorderFactory.createTitledBorder("Job Information"));
    jobInfoPanel.setLayout(new GridBagLayout());
    c.gridy = 0;
    c.ipady = 30;
    centerPanel.add(jobInfoPanel, c);
   
    GridBagConstraints c1 = new GridBagConstraints();
    c1.fill = GridBagConstraints.BOTH;
    c1.weightx = 1;
    c1.weighty = 1;
   
    // Name
    jobInfoPanel.add(new JLabel("Name :"),c1);
    JLabel jobNameLabel = new JLabel();
    jobInfoPanel.add(jobNameLabel,c1);
    jobNameLabel.setText(profile.getJob().getClass().getSimpleName());
    addUIElement("jobs."+jobId+".job.name", jobNameLabel)// Add to components map
   
    // Gap
    jobInfoPanel.add(new JLabel(),c1);
   
    // Type
    jobInfoPanel.add(new JLabel("Type :"),c1);
    JLabel jobType = new JLabel();
    jobType.setText(getJobType(profile.getJob()));
    jobInfoPanel.add(jobType,c1);
    addUIElement("jobs."+jobId+".job.type", jobType )// Add to components map
   
    // Job Class Name
    c1.gridy = 1;
    c1.gridwidth = 1;
    jobInfoPanel.add(new JLabel("GridJob Class :"),c1);
    c1.gridwidth = GridBagConstraints.REMAINDER;
    JLabel jobClassLabel = new JLabel();
    jobClassLabel.setText(profile.getJob().getClass().getName());
    jobInfoPanel.add(jobClassLabel,c1);
    addUIElement("jobs."+jobId+".job.class", jobClassLabel)// Add to components map
   
   
   
    /* -- Execution Information -- */
   
    JPanel executionInfoPanel = new JPanel();
    executionInfoPanel.setBorder(BorderFactory.createTitledBorder("Execution Statistics"));
    executionInfoPanel.setLayout(new GridBagLayout());
    c.gridy = 1;
    c.ipady = 30;
    centerPanel.add(executionInfoPanel, c);
   
    GridBagConstraints c3 = new GridBagConstraints();
    c3.weightx = 1;
    c3.weighty = 1;
    c3.fill = GridBagConstraints.BOTH;
   
    // Start Time
    executionInfoPanel.add(new JLabel("Job Status :"),c3);
    final JLabel statusLabel = new JLabel("Initializing");
    executionInfoPanel.add(statusLabel,c3);
    addUIElement("jobs."+jobId+".execution.status", statusLabel)// Add to components map
   
    // Status Update Listener
    profile.getFuture().addGridJobStateListener(new GridJobStateListener() {
      public void stateChanged(final GridJobState newState) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            statusLabel.setText(StringUtils.capitalize(newState.toString().toLowerCase()));
          }
        });
      }
    });
   
    executionInfoPanel.add(new JLabel(),c3); // Space Holder
   
    // Percent Complete
    executionInfoPanel.add(new JLabel("Completed % :"),c3);
    final JLabel percentLabel = new JLabel("-N/A-");
    executionInfoPanel.add(percentLabel,c3);
    addUIElement("jobs."+jobId+".execution.percentage", percentLabel)// Add to components map
   
    c3.gridy = 1;
   
    // Start Time
    executionInfoPanel.add(new JLabel("Start Time :"),c3);
    JLabel startTimeLabel = new JLabel(DateFormat.getInstance().format(new Date(startTime)));
    executionInfoPanel.add(startTimeLabel,c3);
    addUIElement("jobs."+jobId+".execution.starttime", startTimeLabel)// Add to components map
   
    executionInfoPanel.add(new JLabel(),c3); // Space Holder
   
    // Elapsed Time
    executionInfoPanel.add(new JLabel("Elapsed Time :"),c3);
    JLabel elapsedTimeLabel = new JLabel("-N/A-");
    executionInfoPanel.add(elapsedTimeLabel,c3);
    addUIElement("jobs."+jobId+".execution.elapsedtime", elapsedTimeLabel)// Add to components map
   
    c3.gridy = 2;
   
    // Tasks Deployed (Count)
    executionInfoPanel.add(new JLabel("Tasks Deployed :"),c3);
    JLabel tasksDeployedLabel = new JLabel("-N/A-");
    executionInfoPanel.add(tasksDeployedLabel,c3);
    addUIElement("jobs."+jobId+".execution.tasks", tasksDeployedLabel)// Add to components map
   
    executionInfoPanel.add(new JLabel(),c3); // Space Holder
   
    // Results Collected (Count)
    executionInfoPanel.add(new JLabel("Results Collected :"),c3);
    JLabel resultsCollectedLabel = new JLabel("-N/A-");
    executionInfoPanel.add(resultsCollectedLabel,c3);
    addUIElement("jobs."+jobId+".execution.results", resultsCollectedLabel)// Add to components map
   
    c3.gridy = 3;
   
    // Remaining Tasks (Count)
    executionInfoPanel.add(new JLabel("Remaining Tasks :"),c3);
    JLabel remainingTasksLabel = new JLabel("-N/A-");
    executionInfoPanel.add(remainingTasksLabel,c3);
    addUIElement("jobs."+jobId+".execution.remaining", remainingTasksLabel)// Add to components map
   
    executionInfoPanel.add(new JLabel(),c3); // Space Holder
   
    // Failed Tasks (Count)
    executionInfoPanel.add(new JLabel("Failed Tasks :"),c3);
    JLabel failedTasksLabel = new JLabel("-N/A-");
    executionInfoPanel.add(failedTasksLabel,c3);
    addUIElement("jobs."+jobId+".execution.failed", failedTasksLabel)// Add to components map
   
    /* -- Submitter Information -- */
    UUID ownerId = profile.getOwner();
    GridNodeDelegate owner = ClusterManager.getInstance().getClusterRegistrationService().getGridNodeDelegate(ownerId);
   
    JPanel ownerInfoPanel = new JPanel();
    ownerInfoPanel.setBorder(BorderFactory.createTitledBorder("Owner Information"));
    ownerInfoPanel.setLayout(new GridBagLayout());
    c.gridy = 2;
    c.ipady = 10;
    centerPanel.add(ownerInfoPanel, c);
   
    GridBagConstraints c2 = new GridBagConstraints();
   
    c2.fill = GridBagConstraints.BOTH;
    c2.weightx = 1;
    c2.weighty = 1;

    // Host Name
    ownerInfoPanel.add(new JLabel("Host Name :"),c2);
    JLabel hostNameLabel = new JLabel(owner.getProfile().getName());
    ownerInfoPanel.add(hostNameLabel, c2);
    addUIElement("jobs."+jobId+".owner.hostname", hostNameLabel)// Add to components map
   
    // Gap
    ownerInfoPanel.add(new JLabel(), c2);
   
    // Host IP Address
    ownerInfoPanel.add(new JLabel("Host IP :"), c2);
    JLabel hostIPLabel = new JLabel(owner.getProfile().getIpAddress());
    ownerInfoPanel.add(hostIPLabel,c2);
    addUIElement("jobs."+jobId+".owner.hostip", hostIPLabel)// Add to components map
   
    // Owner UUID
    c2.gridy = 1;
    c2.gridx = 0;
    ownerInfoPanel.add(new JLabel("Owner ID :"),c2);
    JLabel ownerIdLabel = new JLabel(profile.getOwner().toString());
    c2.gridx = 1;
    c2.gridwidth = 4;
    ownerInfoPanel.add(ownerIdLabel,c2);
    addUIElement("jobs."+jobId+".owner.id", ownerIdLabel)// Add to components map
   

    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        // Create Tab
        addUIElement("jobs." + jobId, jobPanel);
        JTabbedPane tabs = getUIElement("tabs");
        tabs.addTab(profile.getJob().getClass().getSimpleName(), jobPanel);
        tabs.revalidate();
      }
    });

   
   
    // Execution Information Updater Thread
    new Thread(new Runnable() {
     
      boolean initialized = false;
      boolean unbounded = false;
     
      public void run() {

        // Unbounded, No Progress Supported
        if ((!initialized) && profile.getJob() instanceof UnboundedGridJob<?>) {
          SwingUtilities.invokeLater(new Runnable() {
            public void run() {
              progressBar.setIndeterminate(true);
              progressBar.setStringPainted(false);
             
              // Infinity Symbol
              percentLabel.setText(String.valueOf('\u221e'));
             
            }
          });
          initialized = true;
          unbounded = true;
        }
       
        // Update Job Info
        while(true) {
         
          try {
            // 500ms Interval
            Thread.sleep(500);
           
          } catch (InterruptedException e) {
            log.warn("Interrupted Progress Updater Thread",e);
          }
         
          final int totalCount = profile.getTotalTasks();
          final int tasksRem = profile.getTaskCount();
          final int resCount = profile.getResultCount();
          final int failCount = profile.getFailedCount();
         
          showBusyIcon();
         
          // Task Information
          JLabel totalTaskLabel = getUIElement("jobs."+jobId+".execution.tasks");
          totalTaskLabel.setText(String.valueOf(totalCount));
         
          // Result Count
          JLabel resCountLabel = getUIElement("jobs."+jobId+".execution.results");
          resCountLabel.setText(String.valueOf(resCount));
         
          // Remaining Task Count
          JLabel remLabel = getUIElement("jobs."+jobId+".execution.remaining");
          remLabel.setText(String.valueOf(tasksRem));
         
          // Failed Task Count
          JLabel failedLabel = getUIElement("jobs."+jobId+".execution.failed");
          failedLabel.setText(String.valueOf(failCount));
         
          // Elapsed Time
          JLabel elapsedLabel = getUIElement("jobs."+jobId+".execution.elapsedtime");
          elapsedLabel.setText(TimeUtils.timeDifference(startTime));
         
          // Job State
          final JLabel statusLabel = getUIElement("jobs."+jobId+".execution.status");
         
          // If not in Executing Mode
          if ((!profile.getFuture().isJobFinished())&&profile.getFuture().getState()!=GridJobState.EXECUTING) {
            SwingUtilities.invokeLater(new Runnable() {
              public void run() {
               
                // Progress Bar
                progressBar.setIndeterminate(true);
                progressBar.setStringPainted(false);
               
                // Status Text
                String state = profile.getFuture().getState().toString();
                statusLabel.setText(StringUtils.capitalize(state.toLowerCase()));
               
                // Percentage Label
                percentLabel.setText(String.valueOf('\u221e'));
              }
            });
          }
          else { // Executing Mode : Progress Information
           
            // Job Finished, Stop
            if (profile.getFuture().isJobFinished()) {
              showIdleIcon();
              return;
            }
           
            // Double check for status label
            if (!statusLabel.getText().equalsIgnoreCase("executing")) {
              SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                  String newstate = profile.getFuture().getState().toString();
                  statusLabel.setText(StringUtils.capitalize(newstate.toLowerCase()));
                }
               
              });
            }
           
            if (!unbounded) {
             
              final int percentage = (int) (profile.percentage() * 100);
             
              //final int failCount = profile.get
              SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                 
                  // If finished at this point, do not update
                  if (progressBar.getValue()==100) {
                    return;
                  }
                 
                  // If ProgressBar is in indeterminate
                  if (progressBar.isIndeterminate()) {
                    progressBar.setIndeterminate(false);
                    progressBar.setStringPainted(true);
                  }
                 
                  // Update Progress Bar / Percent Label
                  progressBar.setValue(percentage);
                  percentLabel.setText(percentage + " %");
                 
                }
              });
            }
          }

         
        }
      }
    }).start();
   
    // Job End Hook to Execute Job End Actions
    ServiceEventsSupport.addServiceHook(new ServiceHookCallback() {

      public void onServiceEvent(final ServiceMessage event) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
           
            JButton close = getUIElement("jobs."+jobId+".closetab");
            JButton terminate = getUIElement("jobs."+jobId+".terminate");
            terminate.setEnabled(false);
            close.setEnabled(true);
           
            JProgressBar progress = getUIElement("jobs."+jobId+".progress");
            JLabel percentage = getUIElement("jobs."+jobId+".execution.percentage");
           
            progress.setEnabled(false);
           
            // If Successfully Finished
            if (event.getType()==ServiceMessageType.JOB_END) {
             
             
              if (profile.getFuture().getState()!=GridJobState.FAILED) {
                // If Not Job Failed
                progress.setValue(100);
                percentage.setText("100 %");
              }
              else {
                // If Failed
                percentage.setText("N/A");
              }
             
              // Stop (if) Indeterminate Progress Bar
              if (progress.isIndeterminate()) {
                progress.setIndeterminate(false);
                progress.setStringPainted(true);
              }
            }
            else if (event.getType()==ServiceMessageType.JOB_CANCEL){
             
              if (progress.isIndeterminate()) {
                progress.setIndeterminate(false);
                progress.setStringPainted(false);
                percentage.setText("N/A");
              }
            }
           
            showIdleIcon();
          }
        });
      }
     
    }, jobId, ServiceMessageType.JOB_CANCEL, ServiceMessageType.JOB_END);
  }

  /**
   * Returns the Job Type Name for given Job
   *
   * @param job Job Instance
   *
   * @return String representation of Job Type
   */
  private String getJobType(GridJob<?, ?> job) {
    if (job instanceof SplitAggregateGridJob<?, ?>) {
      return "Split-Aggregate";
    }
    else if (job instanceof UnboundedGridJob<?>) {
      return "Unbounded";
    }
    else {
      return "Unknown";
    }
  }

  /**
   * Removes the given Job Tab Pane
   * @param jobId JobId of pane
   */
  protected void removeJobTab(String jobId) {
   
    // Detach Tab
    JTabbedPane tabs = getUIElement("tabs");
    tabs.remove(getUIElement("jobs." + jobId));
    tabs.revalidate();
   
    // Remove UI Elements
    removeUIElement("jobs."+jobId+".progress");
    removeUIElement("jobs."+jobId+".terminate");
    removeUIElement("jobs."+jobId+".closetab");
    removeUIElement("jobs."+jobId+".job.name");
    removeUIElement("jobs."+jobId+".job.type");
    removeUIElement("jobs."+jobId+".job.class");
    removeUIElement("jobs."+jobId+".execution.status");
    removeUIElement("jobs."+jobId+".execution.percentage");
    removeUIElement("jobs."+jobId+".execution.starttime");
    removeUIElement("jobs."+jobId+".execution.elapsedtime");
    removeUIElement("jobs."+jobId+".execution.tasks");
    removeUIElement("jobs."+jobId+".execution.results");
    removeUIElement("jobs."+jobId+".execution.remaining");
    removeUIElement("jobs."+jobId+".execution.failed");
    removeUIElement("jobs."+jobId+".owner.hostname");
    removeUIElement("jobs."+jobId+".owner.hostip");
    removeUIElement("jobs."+jobId+".owner.id");
    removeUIElement("jobs." + jobId);
  }
 
  /**
   * Invokes the Cluster Shutdown Operation
   */
  protected void doShutdownCluster() {

    // Consider different messages when there are active jobs
    String message = "Are you sure to shutdown the cluster ?";

    int response = JOptionPane
        .showConfirmDialog(this, message, "Shutdown Cluster",
                  JOptionPane.YES_NO_OPTION);
   
    // User chose 'No'
    if (response == JOptionPane.NO_OPTION) return;
    JButton shutdownButton = getUIElement("general.shutdown");
    shutdownButton.setEnabled(false);
   
    showBusyIcon();
   
    // Shutdown
    onShutdown();
  }

  /**
   * Displays About Dialog Box
   */
  protected void showAbout() {
    new AboutDialog(this);
  }

  /**
   * Displays Help Contents
   */
  protected void showHelp() {
    UISupport.displayHelp(this);
  }

  /**
   * Invokes Peer Discovery using Colombus Web Servers.
   */
  protected void doDiscoverWS() {
    // TODO Implement
    JOptionPane.showMessageDialog(this, "This feature is not implemented");
  }

  /**
   * Invokes Peer Discovery using Multicast.
   */
  protected void doDiscoverMulticast() {
    // TODO Implement
    JOptionPane.showMessageDialog(this, "This feature is not implemented");
  }

  /**
   * Displays Configuration Dialog Box.
   */
  protected void showConfiguration() {
    // TODO Implement
    JOptionPane.showMessageDialog(this, "This feature is not implemented");
  }
 
  /**
   * Requests Cluster Shutdown.
   */
  public void onShutdown() {

    removeIcon();
    new Thread(new Runnable() {

      @Override
      public void run() {
        // Forced Shutdown
       
        ClusterManager.getInstance().shutdown(true);
      }
     
    }).start();
  }

  /**
   * Updates UI and displays the Cluster Information.
   */
  private void showClusterInfo() {
    ClusterManager mgr = ClusterManager.getInstance();

    // ClusterID
    final JLabel clusterId = getUIElement("general.stats.clusterid");
    clusterId.setText(mgr.getClusterId().toString());
   
    // HostInfo
    JLabel hostInfo = getUIElement("general.stats.hostinfo");
    hostInfo.setText(mgr.getClusterInfo().getHostInfo());
   
    // Protocols
    JLabel protocols = getUIElement("general.stats.protocols");
    protocols.setText(mgr.getClusterInfo().getProtocolInfo());
   
    // Uptime Initial Value
    JLabel upTime = getUIElement("general.stats.uptime");
    upTime.setText("");
   
    // Peer Clusters
    final JLabel clusters = getUIElement("general.stats.peerclusters");
    clusters.setText("0");
   
    // Peer Clusters Update Hook
    ServiceEventsSupport.addServiceHook(new ServiceHookCallback() {
      public void onServiceEvent(ServiceMessage message) {
       
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            try {
              int peers = ClusterManager.getInstance().getPeerService().getPeerCount();
              clusters.setText(String.valueOf(peers))
            } catch (Exception e) {
              log.warn("[UI] Exception while accessing peer information",e);
            }
          }
        });
      }
    }, ServiceMessageType.PEER_CONNECTION, ServiceMessageType.PEER_DISCONNECTION);
   
    // Local Nodes
    final JLabel nodes = getUIElement("general.stats.nodes");
    nodes.setText(String.valueOf(ClusterManager.getInstance().getClusterRegistrationService().getNodeCount()));
   
   
    // Local Nodes Update Hook
    ServiceEventsSupport.addServiceHook(new ServiceHookCallback() {
      public void onServiceEvent(ServiceMessage message) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            int count = ClusterManager.getInstance().getClusterRegistrationService().getNodeCount();
            nodes.setText(String.valueOf(count));
          }
        });
      }
    }, ServiceMessageType.NODE_REGISTERED, ServiceMessageType.NODE_UNREGISTERED);
   
    // Completed Jobs
    final JLabel jobsdone = getUIElement("general.stats.jobsdone");
    jobsdone.setText("0");
   
    // Completed Jobs Update Hook
    ServiceEventsSupport.addServiceHook(new ServiceHookCallback() {
      public void onServiceEvent(ServiceMessage message) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            int count = ClusterManager.getInstance().getJobService().getFinishedJobCount();
            jobsdone.setText(String.valueOf(count));
          }
        });
      }
    }, ServiceMessageType.JOB_END, ServiceMessageType.JOB_CANCEL);
   
   
    // Active Jobs
    final JLabel activejobs = getUIElement("general.stats.activejobs");
    activejobs.setText(String.valueOf(ClusterManager.getInstance().getJobService().getActiveJobCount()));
   
    // Active Jobs Update Hook
    ServiceEventsSupport.addServiceHook(new ServiceHookCallback() {
      public void onServiceEvent(ServiceMessage message) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            int count = ClusterManager.getInstance().getJobService().getActiveJobCount();
            activejobs.setText(String.valueOf(count));
          }
        });
      }
    }, ServiceMessageType.JOB_START, ServiceMessageType.JOB_CANCEL, ServiceMessageType.JOB_END);
   
    // Start Up time Thread
    Thread t = new Thread(new Runnable() {
      public void run() {
       
        long start = System.currentTimeMillis();
       
        while (true) {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            log.warn("Interrupted Exception in Up Time Thread",e);
          }
         
         
          final String uptime = TimeUtils.timeDifference(start);
         
          SwingUtilities.invokeLater(new Runnable() {

            public void run() {
              JLabel upTime = getUIElement("general.stats.uptime");
              upTime.setText(uptime);
            }
           
          });
        }
       
      }
    });
    t.setDaemon(true);
    t.start();
  }


  /**
   * Adds a Component to the components map of this object.
   *
   * @param identifier Component Identifier
   * @param component Component
   */
  protected void addUIElement(String identifier, JComponent component) {
    components.put(identifier, component);
  }

  /**
   * Removes a Component from the components map of this object.
   *
   * @param identifier Component Identifier
   */
  protected void removeUIElement(String identifier) {
    components.remove(identifier);
  }

 
  /**
   * Returns the UI Element for given Identifier.
   *
   * @param <T> Expected Type of UI Element
   * @param identifier Element Identifier
   *
   * @return UI Element Instance
   *
   * @throws IllegalArgumentException if invalid identifier
   * @throws ClassCastException if invalid type
   */
  @SuppressWarnings("unchecked")
  protected <T extends JComponent> T getUIElement(String identifier) throws IllegalArgumentException, ClassCastException {
    if (! components.containsKey(identifier)) throw new IllegalArgumentException("Invalid Identifier");
    return (T) components.get(identifier);
  }

  /**
   * Displays Splash Screen
   *
   * @return Splash Screen Reference
   */
  public static JWindow showSplash() {
   
    JWindow splash = new JWindow();
    splash.setSize(400, 250);
    splash.setLayout(null);
   
    JLabel status = new JLabel("Developed by Yohan Liyanage, 2008");
    JLabelAppender.setLabel(status);
    status.setFont(new Font("sansserif", Font.PLAIN, 10));
    status.setSize(350, 30);
    status.setLocation(10, 220);
    splash.add(status);
   
    JLabel lbl = new JLabel(new ImageIcon(ClassLoader.getSystemResource("META-INF/resources/nebula-startup.png")));
    lbl.setSize(400, 250);
    lbl.setLocation(0, 0);
    splash.add(lbl);
   
    splash.setVisible(true);
    splash.setLocationRelativeTo(null);
   
    return splash;
  }
 
  /**
   * Creates the UI for ClusterManager,
   * and returns.
   *
   * @return UI reference
   */
  public static ClusterMainUI create() {
    final ClusterMainUI ui = new ClusterMainUI();
    ui.setLocationRelativeTo(null);

    ui.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
   
    // Close Handler
    ui.addWindowListener(new WindowAdapter() {

     
   

      @Override
      public void windowClosing(WindowEvent e) {
        ui.doShutdownCluster();
      }
     
    });
   
    return ui;
  }

}
TOP

Related Classes of org.nebulaframework.ui.swing.cluster.ClusterMainUI

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.