Java tutorial
/* * 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; } }