/* * Copyright 2008 the original author or authors. * * 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.rioproject.tools.ui; import com.sun.jini.config.Config; import net.jini.config.Configuration; import net.jini.config.ConfigurationException; import net.jini.config.ConfigurationProvider; import net.jini.config.NoSuchEntryException; import net.jini.core.discovery.LookupLocator; import net.jini.core.entry.Entry; import net.jini.core.lookup.ServiceID; import net.jini.core.lookup.ServiceItem; import net.jini.core.lookup.ServiceTemplate; import net.jini.discovery.DiscoveryGroupManagement; import net.jini.discovery.LookupDiscovery; import net.jini.discovery.LookupDiscoveryManager; import net.jini.id.Uuid; import net.jini.id.UuidFactory; import net.jini.io.MarshalledInstance; import net.jini.lease.LeaseRenewalManager; import net.jini.lookup.LookupCache; import net.jini.lookup.ServiceDiscoveryEvent; import net.jini.lookup.ServiceDiscoveryManager; import net.jini.lookup.entry.Host; import net.jini.lookup.entry.Name; import org.rioproject.cybernode.Cybernode; import org.rioproject.cybernode.CybernodeAdmin; import org.rioproject.deploy.DeployAdmin; import org.rioproject.deploy.ServiceBeanInstance; import org.rioproject.entry.OperationalStringEntry; import org.rioproject.event.RemoteServiceEventListener; import org.rioproject.eventcollector.api.EventCollector; import org.rioproject.impl.client.JiniClient; import org.rioproject.impl.client.ServiceDiscoveryAdapter; import org.rioproject.impl.discovery.RecordingDiscoveryListener; import org.rioproject.impl.event.BasicEventConsumer; import org.rioproject.impl.opstring.OpString; import org.rioproject.impl.util.ThrowableUtil; import org.rioproject.monitor.ProvisionMonitor; import org.rioproject.monitor.ProvisionMonitorEvent; import org.rioproject.opstring.*; import org.rioproject.system.ComputeResourceAdmin; import org.rioproject.system.ComputeResourceUtilization; import org.rioproject.tools.ui.browser.Browser; import org.rioproject.tools.ui.cybernodeutilization.CybernodeUtilizationPanel; import org.rioproject.tools.ui.discovery.GroupSelector; import org.rioproject.tools.ui.multicast.MulticastMonitor; import org.rioproject.tools.ui.prefs.PreferencesDialog; import org.rioproject.tools.ui.servicenotification.RemoteEventTable; import org.rioproject.tools.ui.serviceui.ServiceAdminManager; import org.rioproject.tools.ui.util.TabLabel; import org.rioproject.ui.GlassPaneContainer; import org.rioproject.ui.Util; import org.rioproject.url.artifact.ArtifactURLStreamHandlerFactory; import org.rioproject.util.RioHome; import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.rmi.RemoteException; import java.rmi.server.ExportException; import java.security.PrivilegedExceptionAction; import java.util.*; import java.util.List; import java.util.concurrent.*; /** * Displays deployed system status. * * @author Dennis Reedy */ @SuppressWarnings("PMD.ConstructorCallsOverridableMethod") public class Main extends JFrame { private final static long startTime = System.currentTimeMillis(); private File lastDir = new File(System.getProperty("user.dir")); private final Configuration config; /** A DiscoveryListener that will record lookup service discovery/discard times */ private RecordingDiscoveryListener recordingListener; /** LookupDiscovery for discovering all groups */ private LookupDiscovery lookupDiscovery; private static JiniClient jiniClient; private ServiceDiscoveryManager sdm; private final CybernodeUtilizationPanel cup; /** A task to control ComputeResourceUtilization refreshes */ private ComputeResourceUtilizationTask cruTask; /** Scheduler for Cybernode utilization gathering */ private ScheduledExecutorService scheduler; private ExecutorService service; private LookupCache monitorCache; /*private JButton deploy;*/ //private final GraphView graphView; private final Main frame; private final ColorManager colorManager; private final UtilizationColumnManager utilizationColumnManager; private int cybernodeRefreshRate; private String lastArtifact = null; private BasicEventConsumer clientEventConsumer; final String AS_SERVICE_UI = "as.service.ui"; private final RemoteEventTable remoteEventTable; private final Map<String, ImageIcon> toolBarImageMap = new HashMap<String, ImageIcon>(); private final JTabbedPane monitorTabs = new JTabbedPane(); private final JTabbedPane mainTabs = new JTabbedPane(); private final Map<ProvisionMonitor, ProvisionMonitorPanel> monitorPanelMap = new ConcurrentHashMap<ProvisionMonitor, ProvisionMonitorPanel>(); private int orientation; private final ProgressPanel progressPanel; private final JComponent glassPaneComponent; public Main(final Configuration config, final boolean exitOnClose, final Properties startupProps) throws ExportException, ConfigurationException { this.config = config; progressPanel = new ProgressPanel(config); glassPaneComponent = new GlassPaneContainer(progressPanel); String lastArtifactName = startupProps.getProperty(Constants.LAST_ARTIFACT); if(lastArtifactName!=null) lastArtifact = lastArtifactName; String lastDirName = startupProps.getProperty(Constants.LAST_DIRECTORY); if(lastDirName!=null) lastDir = new File(lastDirName); ServiceAdminManager.getInstance().setAdminFrameProperties(startupProps); colorManager = new ColorManager(startupProps); utilizationColumnManager = new UtilizationColumnManager(startupProps); orientation = Integer.parseInt(startupProps.getProperty(Constants.GRAPH_ORIENTATION, Constants.GRAPH_ORIENTATION_WEST)); String defaultRefreshRate = Integer.toString(Constants.DEFAULT_CYBERNODE_REFRESH_RATE); String refreshRate = startupProps.getProperty(Constants.CYBERNODE_REFRESH_RATE, defaultRefreshRate); cybernodeRefreshRate = Integer.parseInt(refreshRate); try { String title = (String)config.getEntry(Constants.COMPONENT, "title", String.class, null); if(title!=null) setTitle(title); } catch (ConfigurationException e) { e.printStackTrace(); } frame = this; toolBarImageMap.put("refreshIcon", Util.getImageIcon("org/rioproject/tools/ui/images/view-refresh.png")); toolBarImageMap.put("fitIcon", Util.getImageIcon("org/rioproject/tools/ui/images/view-fullscreen.png")); toolBarImageMap.put("westIcon", Util.getScaledImageIcon("org/rioproject/tools/ui/images/west.png", 22, 22)); toolBarImageMap.put("westSelectedIcon", Util.getScaledImageIcon("org/rioproject/tools/ui/images/west-selected.png", 22, 22)); toolBarImageMap.put("northIcon", Util.getScaledImageIcon("org/rioproject/tools/ui/images/north.png", 22, 22)); toolBarImageMap.put("northSelectedIcon", Util.getScaledImageIcon("org/rioproject/tools/ui/images/north-selected.png", 22, 22)); final JButton colorChooser = new JButton("Color ..."); colorChooser.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { JColorChooser.showDialog(colorChooser, "Colors", colorChooser.getForeground()); } }); try { String bannerIcon = (String)config.getEntry(Constants.COMPONENT, "bannerIcon", String.class, null); if(bannerIcon!=null) { ImageIcon icon = Util.getImageIcon(bannerIcon); if(icon!=null) { setIconImage(icon.getImage()); startupProps.setProperty("bannerIcon", bannerIcon); } } } catch (ConfigurationException e) { e.printStackTrace(); } cup = new CybernodeUtilizationPanel(new GraphViewAdapter(this), utilizationColumnManager.getSelectedColumns(), startupProps); cup.setPreferredSize(new Dimension(Integer.MAX_VALUE, 200)); UtilitiesPanel utilities = new UtilitiesPanel(cup); final JPanel utilitiesPanel = makeUtilitiesPanel(utilities); setJMenuBar(createMenu()); Container content = getContentPane(); mainTabs.add("Deployments", glassPaneComponent); mainTabs.add("Utilization", utilitiesPanel); remoteEventTable = new RemoteEventTable(config, startupProps); JLabel label = TabLabel.create("Service Event Notifications", remoteEventTable); mainTabs.addTab(null, remoteEventTable); mainTabs.setTabComponentAt(2, label); content.add(mainTabs); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { if (exitOnClose) terminateAndClose(); else terminate(); } }); progressPanel.showProgressPanel(); } void setStartupLocations(final Properties startupProps) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { remoteEventTable.init(startupProps); } }); } public UtilizationColumnManager getUtilizationColumnManager() { return utilizationColumnManager; } GraphView getGraphView() { if(monitorTabs.getTabCount()>0) return ((ProvisionMonitorPanel) monitorTabs.getSelectedComponent()).getGraphView(); return null; } Configuration getConfiguration() { return config; } private JPanel makeUtilitiesPanel(JComponent comp) { JPanel content = new JPanel(new BorderLayout()); JPanel bottom = new JPanel(new BorderLayout()); bottom.setBorder( BorderFactory.createEmptyBorder(2, 4, 4, 2)); content.add(bottom, BorderLayout.SOUTH); content.add(comp, BorderLayout.CENTER); content.add(new JLabel(""), BorderLayout.EAST); return content; } /** * Create a JMenuBar * * @return a JMenuBar */ JMenuBar createMenu() { JMenuBar menuBar = new JMenuBar(); menuBar.setLayout(new BoxLayout(menuBar, BoxLayout.X_AXIS)); JMenu fileMenu = null; if(!MacUIHelper.isMacOS()) { fileMenu = new JMenu("File"); JMenuItem preferencesMenuItem = fileMenu.add(new JMenuItem("Preferences")); preferencesMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PreferencesDialog prefs = new PreferencesDialog(frame, getGraphView(), cup); prefs.setVisible(true); } }); JMenuItem exitMenuItem = fileMenu.add(new JMenuItem("Exit")); exitMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { terminateAndClose(); } }); } JMenu discoMenu = new JMenu("Discovery"); JMenuItem groupSelector = discoMenu.add(new JMenuItem("Group Selector")); groupSelector.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { JDialog dialog = GroupSelector.getDialog(frame, sdm.getDiscoveryManager(), recordingListener); dialog.setVisible(true); } }); JMenuItem addLocator = discoMenu.add(new JMenuItem("Add Locator...")); addLocator.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { addLocator(); } }); JMenuItem remLocator = discoMenu.add(new JMenuItem("Remove Locator...")); remLocator.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { removeLocator(); } }); discoMenu.addSeparator(); //String[] gps = jiniClient.getRegistrarGroups(); JMenuItem addGroup = discoMenu.add(new JMenuItem("Add Group...")); //if (gps == null) // addGroup.setEnabled(false); addGroup.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { addGroup(); } }); JMenuItem remGroup = discoMenu.add(new JMenuItem("Remove Group...")); //if (gps == null) // remGroup.setEnabled(false); remGroup.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { removeGroup(); } }); JMenu toolsMenu = new JMenu("Tools"); JMenuItem multiCastMonitor = toolsMenu.add(new JMenuItem("Multicast Monitor...")); multiCastMonitor.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { JDialog dialog = MulticastMonitor.getDialog(frame); dialog.setVisible(true); } }); JMenuItem browserMenu = toolsMenu.add(new JMenuItem("Service Browser...")); final JFrame parent = this; browserMenu.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { try { Browser browser = new Browser(config, parent); browser.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); JMenu helpMenu = null; if(!MacUIHelper.isMacOS()) { helpMenu = new JMenu("Help"); helpMenu.setMnemonic('H'); JMenuItem about = helpMenu.add(new JMenuItem("About...")); about.setMnemonic('A'); about.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new RioAboutBox(frame); } }); } /*else { MacUIHelper.setUIHandler(this, getGraphView(), cup); }*/ if (fileMenu!=null) menuBar.add(fileMenu); menuBar.add(discoMenu); menuBar.add(toolsMenu); if (helpMenu!=null) { menuBar.add(Box.createGlue()); menuBar.add(helpMenu); } return (menuBar); } /** * Add a Jini Locator to locate a Jini Lookup service */ public void addLocator() { int port = 0; int portIndex; String input = JOptionPane.showInputDialog("Enter a Locator to Discover host[:port]"); if (input != null) { portIndex = input.indexOf(":"); if (portIndex == -1) port = 4160; if (input.startsWith("http://") || input.startsWith("jini://")) { String s = input.substring(0, 5); JOptionPane.showMessageDialog(this, "Remove the ["+s+ "] " + "and resubmit", "Locator Format Error", JOptionPane.ERROR_MESSAGE); return; } try { String host = (portIndex == -1 ? input : input.substring(0, portIndex)); if (portIndex != -1) { boolean portError = false; String errorReason = null; String p = input.substring(portIndex + 1, input.length()); try { port = Integer.parseInt(p); } catch (Throwable t) { portError = true; errorReason = "Not a valid number"; } if (port <= 0 || port >= 65536) { portError = true; errorReason = "port number out of range"; } if (portError) { JOptionPane.showMessageDialog(this, "The provided port is " + "invalid : " + errorReason, "Locator Port Error", JOptionPane.ERROR_MESSAGE); return; } } jiniClient.addLocator(host, port); } catch (Exception e) { JOptionPane.showMessageDialog(this, "Exception trying to add Locator [" + e.getClass().getName() + "]", "Locator Addition Error", JOptionPane.ERROR_MESSAGE); } } } /** * Remove a Jini Locator that is being used to locate a Jini Lookup service */ public void removeLocator() { LookupLocator[] locators = jiniClient.getLocators(); if (locators == null || locators.length == 0) { JOptionPane.showMessageDialog(this, "There are no locators to remove", "Zero Locator Error", JOptionPane.ERROR_MESSAGE); return; } LookupLocator selected = (LookupLocator) JOptionPane.showInputDialog(null, "Select a Locator to Remove", "Locator Removal Selector", JOptionPane.INFORMATION_MESSAGE, null, locators, locators[0]); if (selected == null) return; jiniClient.removeLocators(new LookupLocator[]{selected}); } /** * Add a Jini Group to use to discover a Jini Lookup service */ public void addGroup() { String group = JOptionPane.showInputDialog("Enter a Group to Discover"); if (group != null) { String[] groups = jiniClient.getRegistrarGroups(); if (groups != null && groups.length > 0) { for (String group1 : groups) { if (group1.equals(group)) { JOptionPane.showMessageDialog(this, "The [" + group + "] group is already " + "part of the discovery listener", "Group Addition Error", JOptionPane.ERROR_MESSAGE); return; } } } try { jiniClient.addRegistrarGroups(new String[]{group}); } catch (Exception e) { e.printStackTrace(); } } } /** * Remove a Jini Group that is being used to discover a Jini Lookup service */ public void removeGroup() { String[] groups = jiniClient.getRegistrarGroups(); if (groups == null || groups.length == 0) { JOptionPane.showMessageDialog(this, "There are no groups to remove", "Zero Group Error", JOptionPane.ERROR_MESSAGE); return; } String selected = (String)JOptionPane.showInputDialog(null, "Select a Group to Remove", "Group Removal Selector", JOptionPane.INFORMATION_MESSAGE, null, groups, groups[0]); if (selected == null) return; jiniClient.removeRegistrarGroups(new String[]{selected}); } /** * Terminate the utility */ public void terminate() { if(lookupDiscovery!=null) lookupDiscovery.terminate(); if(sdm != null) sdm.terminate(); if(jiniClient != null) jiniClient.terminate(); if(scheduler!=null) scheduler.shutdownNow(); if(service!=null) service.shutdownNow(); remoteEventTable.terminate(); Dimension dim = getSize(); Point point = getLocation(); Properties props = new Properties(); props.put(Constants.USE_EVENT_COLLECTOR, Boolean.toString(remoteEventTable.getUseEventCollector())); props.put(Constants.EVENTS_DIVIDER, Integer.toString(remoteEventTable.getDividerLocation())); props.put(Constants.FRAME_HEIGHT, Integer.toString(dim.height)); props.put(Constants.FRAME_WIDTH, Integer.toString(dim.width)); props.put(Constants.FRAME_X_POS, Double.toString(point.getX())); props.put(Constants.FRAME_Y_POS, Double.toString(point.getY())); props.put(Constants.TREE_TABLE_AUTO_EXPAND, Boolean.toString(cup.getExpandAll())); if(lastArtifact!=null) props.put(Constants.LAST_ARTIFACT, lastArtifact); props.put(Constants.LAST_DIRECTORY, lastDir.getAbsolutePath()); props.put(Constants.FAILURE_COLOR, Integer.toString(colorManager.getFailureColor().getRGB())); props.put(Constants.OKAY_COLOR, Integer.toString(colorManager.getOkayColor().getRGB())); props.put(Constants.WARNING_COLOR, Integer.toString(colorManager.getWarningColor().getRGB())); props.put(Constants.UNMANAGED_COLOR, Integer.toString(colorManager.getUnManagedColor().getRGB())); dim = ServiceAdminManager.getInstance().getLastAdminFrameSize(); if(dim!=null) { props.put(Constants.ADMIN_FRAME_HEIGHT, Integer.toString(dim.height)); props.put(Constants.ADMIN_FRAME_WIDTH, Integer.toString(dim.width)); } point = ServiceAdminManager.getInstance().getLastAdminFrameLocation(); if(point!=null) { props.put(Constants.ADMIN_FRAME_X_POS, Double.toString(point.getX())); props.put(Constants.ADMIN_FRAME_Y_POS, Double.toString(point.getY())); } String lastAdminWindowLayout = ServiceAdminManager.getInstance().getLastAdminWindowLayout(); props.put(Constants.ADMIN_FRAME_WINDOW_LAYOUT, lastAdminWindowLayout); if(getGraphView()!=null) props.put(Constants.GRAPH_ORIENTATION, Integer.toString(getGraphView().getOrientation())); props.put(Constants.CYBERNODE_REFRESH_RATE, Integer.toString(getCybernodeRefreshRate())); String[] cols = utilizationColumnManager.getSelectedColumns(); for(int i=0; i<cols.length; i++) { props.put(cols[i], Integer.toString(i+1)); } try { saveProperties(props, Constants.UI_PROPS); } catch (IOException e) { e.printStackTrace(); } } /** * Load properties from ${user.home}/.rio * * @param filename The name of the properties file to load * * @return A Properties object loaded from the system * @throws IOException If there are exceptions accessing the file system */ private static Properties loadProperties(String filename) throws IOException { File rioHomeDir = new File(System.getProperty("user.home") +File.separator +".rio"); Properties props = new Properties(); if (!rioHomeDir.exists()) return (props); File propFile = new File(rioHomeDir, filename); props.load(new FileInputStream(propFile)); return (props); } /** * Save properties to a file stored in ${user.home}/.rio * * @param props The Properties object to save, must not be null * @param filename The file name to save the Properties to * * @throws IOException If there are exceptions accessing the file system */ private void saveProperties(final Properties props, final String filename) throws IOException { if (props == null) throw new IllegalArgumentException("props is null"); File userRioDir = new File(System.getProperty("user.home"), ".rio"); if (!userRioDir.exists()) { if(userRioDir.mkdir()) { System.err.println("Created: "+userRioDir.getPath()); } } File propFile = new File(userRioDir, filename); props.store(new FileOutputStream(propFile), "Generated"); } /** * Terminate the utility */ public void terminateAndClose() { terminate(); if(System.getProperty(AS_SERVICE_UI)==null) System.exit(0); } public int getCybernodeRefreshRate() { return cybernodeRefreshRate; } public void setCybernodeRefreshRate(int rate) { if(rate!=cybernodeRefreshRate) { cybernodeRefreshRate = rate; scheduleComputeResourceUtilizationTask(); } } void scheduleComputeResourceUtilizationTask() { if(scheduler!=null) { if(cruTask!=null) cruTask.cancel(); cruTask = new ComputeResourceUtilizationTask(); scheduler.scheduleAtFixedRate(cruTask, 0, cybernodeRefreshRate, TimeUnit.SECONDS); } else { cruTask = new ComputeResourceUtilizationTask(); long initialDelay = 2; scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(cruTask, initialDelay, cybernodeRefreshRate, TimeUnit.SECONDS); } } void refreshCybernodeTable() { if(cruTask!=null) { if(cup.getCount()>0) { try { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); cruTask.run(); } finally { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } } } public void startDiscovery() throws Exception { lookupDiscovery = new LookupDiscovery(DiscoveryGroupManagement.ALL_GROUPS, config); recordingListener = new RecordingDiscoveryListener(lookupDiscovery); lookupDiscovery.addDiscoveryListener(recordingListener); int threadPoolSize = Config.getIntEntry(config, Constants.COMPONENT, Constants.THREAD_POOL_SIZE_KEY, Constants.DEFAULT_THREAD_POOL_SIZE, Constants.MIN_THREAD_POOL_SIZE, Constants.MAX_THREAD_POOL_SIZE); service = Executors.newCachedThreadPool(); for(int i=0; i<threadPoolSize; i++) { service.submit(new ServiceItemFetcher()); service.submit(new ExternalServiceHandler()); } scheduleComputeResourceUtilizationTask(); String[] defaultGroups = JiniClient.parseGroups(System.getProperty(org.rioproject.config.Constants.GROUPS_PROPERTY_NAME, "all")); /* Get group values, default to all groups */ String[] groups = (String[]) config.getEntry(Constants.COMPONENT, "initialLookupGroups", String[].class, defaultGroups); LookupLocator[] locators = null; try { LookupLocator[] defaultLocators = JiniClient.parseLocators(System.getProperty(org.rioproject.config.Constants.LOCATOR_PROPERTY_NAME)); /* Get LookupLocator values */ locators = (LookupLocator[]) config.getEntry(Constants.COMPONENT, "initialLookupLocators", LookupLocator[].class, defaultLocators); } catch (MalformedURLException e) { JOptionPane.showMessageDialog(this, "<html>" + "The lookup locators provided in the<br>" + "configuration file or by using the<br>" + "<tt>locators</tt> option are formatted<br>" + "incorrectly.<br><br>" + "<p>The UI will continue initialization<br>" + "and ignore this setting. Check the<br>" + "log file for details.</html>", "Locators Incorrect", JOptionPane.WARNING_MESSAGE); } jiniClient = new JiniClient(new LookupDiscoveryManager(groups, locators, null, config)); ServiceTemplate monitors = new ServiceTemplate(null, new Class[]{ProvisionMonitor.class}, null); ServiceTemplate cybernodes = new ServiceTemplate(null, new Class[]{Cybernode.class}, null); ServiceTemplate eventCollectors = new ServiceTemplate(null, new Class[]{EventCollector.class}, new Entry[]{new OperationalStringEntry(org.rioproject.config.Constants.CORE_OPSTRING)}); ServiceTemplate all = new ServiceTemplate(null, null, null); sdm = new ServiceDiscoveryManager(jiniClient.getDiscoveryManager(), new LeaseRenewalManager(), config); ServiceWatcher watcher = new ServiceWatcher(); ProvisionClientEventConsumer provisionClientEventConsumer = new ProvisionClientEventConsumer(); monitorCache = sdm.createLookupCache(monitors, null, watcher); sdm.createLookupCache(cybernodes, null, watcher); sdm.createLookupCache(eventCollectors, null, watcher); clientEventConsumer = new BasicEventConsumer(ProvisionMonitorEvent.getEventDescriptor(), provisionClientEventConsumer, config); /*sdm.createLookupCache(all, new ServiceItemFilter() { @Override public boolean check(ServiceItem item) { boolean external = true; for (Entry e : item.attributeSets) { if (e instanceof OperationalStringEntry) { external = false; break; } } return !(item.service instanceof ServiceRegistrar) && external; } }, new AllServiceWatcher());*/ remoteEventTable.setDiscoveryManagement(jiniClient.getDiscoveryManager()); } void addProvisionMonitor(ServiceItem item) throws RemoteException, OperationalStringException { progressPanel.systemUp(); ProvisionMonitor monitor = (ProvisionMonitor) item.service; ProvisionMonitorPanel pmp = addProvisionMonitorPanel(item); clientEventConsumer.register(item); //failureEventConsumer.register(item); DeployAdmin da = (DeployAdmin)monitor.getAdmin(); OperationalStringManager[] opStringMgrs = da.getOperationalStringManagers(); if (opStringMgrs == null || opStringMgrs.length == 0) { return; } for (OperationalStringManager opStringMgr : opStringMgrs) { OperationalString ops = opStringMgr.getOperationalString(); if(getGraphView().getOpStringNode(ops.getName())!=null) return; getGraphView().addOpString(ops); ServiceElement[] elems = ops.getServices(); for(ServiceElement elem : elems) { ServiceBeanInstance[] instances = opStringMgr.getServiceBeanInstances(elem); for(ServiceBeanInstance instance : instances) { GraphNode node = getGraphView().serviceUp(elem, instance); if(node!=null) RequestQueues.write(node, pmp.getGraphView()); else { System.err.println("### Cant get GraphNode for ["+elem.getName()+"], " + "instance ["+instance.getServiceBeanConfig().getInstanceID()+"]"); } } } getGraphView().setOpStringState(ops.getName()); } } private ProvisionMonitorPanel addProvisionMonitorPanel(ServiceItem item) { ProvisionMonitor monitor = (ProvisionMonitor) item.service; ProvisionMonitorPanel pmp = null; if(monitorPanelMap.get(monitor)==null) { pmp = new ProvisionMonitorPanel(monitor, frame, colorManager, toolBarImageMap, config, orientation); String host = "<unknown>"; for(Entry entry : item.attributeSets) { if(entry instanceof Host) { host = ((Host)entry).hostName; break; } } monitorPanelMap.put(monitor, pmp); monitorTabs.addTab(host, pmp); if (mainTabs.getComponentAt(0).equals(glassPaneComponent)) { progressPanel.systemUp(); mainTabs.setComponentAt(0, monitorTabs); monitorTabs.setSelectedIndex(0); } } return pmp; } /** * ServiceDiscoveryListener for all services */ class AllServiceWatcher extends ServiceDiscoveryAdapter { public void serviceAdded(ServiceDiscoveryEvent sdEvent) { ServiceItem item = sdEvent.getPostEventServiceItem(); RequestQueues.write(new RequestQueues.ExternalServiceRequest(item)); } public void serviceRemoved(ServiceDiscoveryEvent sdEvent) { ServiceItem item = sdEvent.getPreEventServiceItem(); RequestQueues.write(new RequestQueues.ExternalServiceRequest(item, true)); } } /** * Add external services */ class ExternalServiceHandler implements Runnable { public void run() { long id = Thread.currentThread().getId(); while (true) { RequestQueues.ExternalServiceRequest request; try { request = RequestQueues.takeExternalServiceRequest(); ServiceItem item = request.item; ServiceElement service = serviceElementFromServiceItem(item); Uuid uuid = UuidFactory.create(item.serviceID.getMostSignificantBits(), item.serviceID.getLeastSignificantBits()); ServiceBeanInstance instance = new ServiceBeanInstance(uuid, new MarshalledInstance(item.service), service.getServiceBeanConfig(), null, null, null); if(getGraphViews().isEmpty()) { Thread.sleep(100); } GraphNode opStringNode = getExternal(); OpString opString = (OpString) opStringNode.getOpString(); if(!request.removed) { GraphNode elementNode = getGraphView().getServiceElementNode(service); if (elementNode == null) { opStringNode.getOpString().addService(service); for(GraphView graphView : getGraphViews()) graphView.addServiceElement(service); } else { service = increment(service); for(GraphView graphView : getGraphViews()) graphView.serviceIncrement(service); } opString.removeService(service); opString.addService(service); for(GraphView graphView : getGraphViews()) { GraphNode serviceNode = graphView.serviceUp(service, instance); graphView.setGraphNodeServiceItem(serviceNode, item); } updateOpStrings(opString); } else { boolean remove = false; for(ServiceElement s : opStringNode.getOpString().getServices()) { if(s.getName().equals(service.getName())) { System.err.println("===> "+s.getName()+" service count: "+s.getActual()); if(s.getActual()==1) { remove = true; break; } } } if(remove) { int beforeCount = opString.getServices().length; opString.removeService(service); opStringNode.setOpString(opString); System.err.println("===> "+opString.getName()+" service count before: "+beforeCount+", after: "+opString.getServices().length); if(opString.getServices().length==0) { for(GraphView graphView : getGraphViews()) graphView.removeOpString(opString.getName()); } else { for(GraphView graphView : getGraphViews()) graphView.removeServiceElement(service); } } else { service.setPlanned(service.getPlanned()-1); //service.setActual(service.getActual()-1); opString.removeService(service); opString.addService(service); updateOpStrings(opString); for(GraphView graphView : getGraphViews()) graphView.serviceDecrement(service, instance); } } } catch (InterruptedException e) { System.err.println("ServiceItemFetcher ["+id+"] InterruptedException, exiting"); break; } catch(Throwable t) { t.printStackTrace(); } } } void updateOpStrings(OperationalString opString) { for(GraphView graphView : getGraphViews()) { GraphNode osn = graphView.getOpStringNode(Constants.UNMANAGED); if (osn != null) osn.setOpString(opString); } } Collection<GraphView> getGraphViews() { while(getGraphView()==null) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } List<GraphView> graphViews = new ArrayList<GraphView>(); //graphViews.add(getGraphView()); for(int i=0; i<monitorTabs.getTabCount(); i++) { ProvisionMonitorPanel provisionMonitorPanel = (ProvisionMonitorPanel) monitorTabs.getTabComponentAt(i); if(provisionMonitorPanel!=null) graphViews.add(provisionMonitorPanel.getGraphView()); } return graphViews; } GraphNode getExternal() { OperationalString operationalString = new OpString(Constants.UNMANAGED, null); return getGraphView().addOpString(operationalString); } ServiceElement serviceElementFromServiceItem(ServiceItem item) { ServiceElement element = new ServiceElement(); element.setPlanned(1); element.setActual(1); Name name = getName(item.attributeSets); ServiceBeanConfig serviceBeanConfig = new ServiceBeanConfig(); serviceBeanConfig.setName(name.name); serviceBeanConfig.setOperationalStringName(Constants.UNMANAGED); Map<String, Object> configParms = serviceBeanConfig.getConfigurationParameters(); configParms.put(ServiceBeanConfig.INSTANCE_ID, 1l); serviceBeanConfig.setConfigurationParameters(configParms); element.setServiceBeanConfig(serviceBeanConfig); return element; } ServiceElement increment(ServiceElement element) { ServiceBeanConfig serviceBeanConfig = element.getServiceBeanConfig(); Map<String, Object> configParms = serviceBeanConfig.getConfigurationParameters(); Long current = (Long) configParms.get(ServiceBeanConfig.INSTANCE_ID); configParms.put(ServiceBeanConfig.INSTANCE_ID, current+1); serviceBeanConfig.setConfigurationParameters(configParms); element.setServiceBeanConfig(serviceBeanConfig); element.setPlanned(element.getPlanned()+1); element.setActual(element.getActual()+1); return element; } } /** * ServiceDiscoveryListener for Cybernodes and ProvisionMonitors */ class ServiceWatcher extends ServiceDiscoveryAdapter { public void serviceAdded(ServiceDiscoveryEvent sdEvent) { try { ServiceItem item = sdEvent.getPostEventServiceItem(); if(item.service instanceof EventCollector) { try { remoteEventTable.addEventCollector((EventCollector) item.service); } catch(Exception e) { Util.showError(e, frame, "Cannot add Event Collector"); } } if(item.service instanceof ProvisionMonitor) { ProvisionMonitor monitor = (ProvisionMonitor) item.service; ProvisionMonitorPanel pmp = addProvisionMonitorPanel(item); if(pmp==null) return; clientEventConsumer.register(item); //failureEventConsumer.register(item); DeployAdmin da = (DeployAdmin)monitor.getAdmin(); OperationalStringManager[] opStringMgrs = da.getOperationalStringManagers(); if (opStringMgrs.length == 0) { return; } for (OperationalStringManager opStringMgr : opStringMgrs) { OperationalString ops = opStringMgr.getOperationalString(); if(pmp.getGraphView().getOpStringNode(ops.getName())!=null) return; pmp.getGraphView().addOpString(ops); ServiceElement[] elems = ops.getServices(); for(ServiceElement elem : elems) { ServiceBeanInstance[] instances = opStringMgr.getServiceBeanInstances(elem); for(ServiceBeanInstance instance : instances) { GraphNode node = pmp.getGraphView().serviceUp(elem, instance); if(node!=null) RequestQueues.write(node, pmp.getGraphView()); else { System.err.println("### Cant get GraphNode " + "for ["+elem.getName()+"], " + "instance ["+instance.getServiceBeanConfig().getInstanceID()+"]"); } } } pmp.getGraphView().setOpStringState(ops.getName()); } } else if(item.service instanceof Cybernode) { Cybernode c = (Cybernode)item.service; CybernodeAdmin cAdmin; try { cAdmin = (CybernodeAdmin)c.getAdmin(); cup.addCybernode(item, cAdmin, getComputeResourceUtilization(cAdmin, item), utilizationColumnManager); cruTask.addCybernode(item); } catch (RemoteException e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } } public void serviceRemoved(ServiceDiscoveryEvent sdEvent) { ServiceItem item = sdEvent.getPreEventServiceItem(); if(item.service instanceof ProvisionMonitor) { monitorCache.discard(item.service); ProvisionMonitorPanel pmp = monitorPanelMap.get(item.service); int ndx = monitorTabs.indexOfComponent(pmp); if(ndx<0) return; monitorTabs.removeTabAt(ndx); if(monitorCache.lookup(null, Integer.MAX_VALUE).length==0) { progressPanel.systemDown(); mainTabs.setComponentAt(0, glassPaneComponent); mainTabs.repaint(); } } if(item.service instanceof Cybernode) { cup.removeCybernode((Cybernode)item.service); } if(item.service instanceof EventCollector) { remoteEventTable.removeEventCollector((EventCollector)item.service); } } } Name getName(Entry[] entries) { Name name = null; for(Entry e : entries) { if(e instanceof Name) { name = (Name)e; break; } } return name; } ComputeResourceUtilization getComputeResourceUtilization(ComputeResourceAdmin crAdmin, ServiceItem item) throws Exception { ComputeResourceUtilization cru=null; try { cru = crAdmin.getComputeResourceUtilization(); } catch(Exception e) { if(ThrowableUtil.isRetryable(e)) { /* Rio 3.2 does not have the getComputeResourceUtilization method */ for(Entry entry : item.attributeSets) { if(entry instanceof ComputeResourceUtilization) { cru = (ComputeResourceUtilization)entry; break; } } } else throw e; } return(cru); } /** * Handler for ProvisionMonitorEvent utilities */ class ProvisionClientEventConsumer implements RemoteServiceEventListener<ProvisionMonitorEvent> { final List<ProvisionMonitorEvent> eventQ = new LinkedList<ProvisionMonitorEvent>(); public void notify(ProvisionMonitorEvent pme) { ProvisionMonitorEvent.Action action = pme.getAction(); ProvisionMonitor monitor = (ProvisionMonitor)pme.getSource(); GraphView graphView = monitorPanelMap.get(monitor).getGraphView(); switch (action) { case SERVICE_ELEMENT_UPDATED: case SERVICE_BEAN_INCREMENTED: graphView.serviceIncrement(pme.getServiceElement()); processQueued(pme.getOperationalStringName(), graphView); break; case SERVICE_BEAN_DECREMENTED: graphView.serviceDecrement(pme.getServiceElement(), pme.getServiceBeanInstance()); refreshCybernodes(pme); break; case SERVICE_ELEMENT_ADDED: if(pme.getServiceElement()==null) { System.err.println("Unable to add ServiceElement, " + "ServiceElement property in ProvisionMonitorEvent is null"); break; } graphView.addServiceElement(pme.getServiceElement()); processQueued(pme.getOperationalStringName(), graphView); break; case SERVICE_ELEMENT_REMOVED: if(pme.getServiceElement()==null) { System.err.println("Unable to remove ServiceElement, " + "ServiceElement property in ProvisionMonitorEvent is null"); break; } graphView.removeServiceElement(pme.getServiceElement()); break; case OPSTRING_UPDATED: graphView.updateOpString(pme.getOperationalString()); graphView.setOpStringState(pme.getOperationalString().getName()); break; case OPSTRING_DEPLOYED: graphView.addOpString(pme.getOperationalString()); processQueued(pme.getOperationalStringName(), graphView); graphView.setOpStringState(pme.getOperationalStringName()); break; case OPSTRING_UNDEPLOYED: graphView.removeOpString(pme.getOperationalStringName()); break; case SERVICE_PROVISIONED: case EXTERNAL_SERVICE_DISCOVERED: handleServiceProvisioned(pme, graphView); graphView.setOpStringState(pme.getOperationalStringName()); refreshCybernodes(pme); break; case SERVICE_FAILED: case SERVICE_TERMINATED: graphView.serviceDown(pme.getServiceElement(), pme.getServiceBeanInstance()); graphView.setOpStringState(pme.getOperationalStringName()); refreshCybernodes(pme); break; } } void handleServiceProvisioned(ProvisionMonitorEvent pme, GraphView graphView) { if(graphView.getOpStringNode(pme.getOperationalStringName())==null) { eventQ.add(pme); } else { GraphNode node = null; try { node = graphView.serviceUp(pme.getServiceElement(), pme.getServiceBeanInstance()); if(node==null) eventQ.add(pme); } finally { RequestQueues.write(node, graphView); } } } void processQueued(String opStringName, GraphView graphView) { ProvisionMonitorEvent[] events = getEvents(opStringName); for(ProvisionMonitorEvent e : events) { handleServiceProvisioned(e, graphView); } } ProvisionMonitorEvent[] getEvents(String opStringName) { ProvisionMonitorEvent[] events; List<ProvisionMonitorEvent> list = new LinkedList<ProvisionMonitorEvent>(); synchronized(eventQ) { events = eventQ.toArray(new ProvisionMonitorEvent[eventQ.size()]); } for(ProvisionMonitorEvent event : events) { if(event.getOperationalStringName().equals(opStringName)) { synchronized(eventQ) { eventQ.remove(event); } list.add(event); } } return(list.toArray(new ProvisionMonitorEvent[list.size()])); } void refreshCybernodes(ProvisionMonitorEvent pme) { if (pme == null) { System.err.println("refreshCybernodes(): Null ProvisionMonitorEvent!!"); } else if (pme.getServiceBeanInstance() == null) { System.err.println("refreshCybernodes(): Can't fetch ServiceBeanInstance from ProvisionMonitorEvent"); } else { cup.updateCybernodesAt(pme.getServiceBeanInstance().getHostAddress()); } } } /** * Update the compute resource utilization with a scheduled task */ class ComputeResourceUtilizationTask implements Runnable { final Map<ServiceItem, CybernodeAdmin> adminTable = new HashMap<ServiceItem, CybernodeAdmin>(); final List<ServiceItem> removals = new ArrayList<ServiceItem>(); private boolean cancelled = false; void addCybernode(ServiceItem item) { try { Cybernode proxy = (Cybernode)item.service; CybernodeAdmin cAdmin = (CybernodeAdmin)proxy.getAdmin(); synchronized(adminTable) { adminTable.put(item, cAdmin); } } catch (RemoteException e) { e.printStackTrace(); } } void cancel() { cancelled = true; } public void run() { if(cancelled) return; Set<Map.Entry<ServiceItem,CybernodeAdmin>> tableSet; synchronized(adminTable) { tableSet = adminTable.entrySet(); } for (Map.Entry<ServiceItem, CybernodeAdmin> mapEntry : tableSet) { ServiceItem item = mapEntry.getKey(); Cybernode cybernode = (Cybernode)item.service; CybernodeAdmin cAdmin = mapEntry.getValue(); try { ComputeResourceUtilization cru = getComputeResourceUtilization(cAdmin, item); cup.update(item, cAdmin, cru, utilizationColumnManager); } catch (Throwable e) { if(!ThrowableUtil.isRetryable(e) && !(e instanceof NullPointerException)) { removals.add(item); cup.removeCybernode(cybernode); System.err.println(e.getClass().getName()+": "+e.getMessage()+", remove Cybernode from table"); } } } for(ServiceItem item : removals) { adminTable.remove(item); } removals.clear(); } } /** * Fetch ServiceItems */ class ServiceItemFetcher implements Runnable { public void run() { long id = Thread.currentThread().getId(); while (true) { RequestQueues.Request request; try { request = RequestQueues.take(); GraphNode node = request.node; if(node.getInstance()!=null) { Uuid uuid = node.getInstance().getServiceBeanID(); ServiceID serviceID = new ServiceID(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); ServiceTemplate template = new ServiceTemplate(serviceID, null, null); ServiceItem item = sdm.lookup(template, null, 1000); if(item!=null) { request.graphView.setGraphNodeServiceItem(node, item); } else { RequestQueues.write(request); } } else { RequestQueues.write(request); } } catch (InterruptedException e) { System.err.println("ServiceItemFetcher ["+id+"] InterruptedException, exiting"); break; } catch(Throwable t) { t.printStackTrace(); } } } } public static void redirect() { String rioHome = System.getProperty("rio.home"); if(rioHome == null) { rioHome = RioHome.get(); } String logDirPath = System.getProperty(Constants.COMPONENT+".logDir", rioHome+File.separator+"logs"); File logDir = new File(logDirPath); if(!logDir.exists()) logDir.mkdirs(); File rioUILog = new File(logDir, "rio-ui.log"); if(rioUILog.exists()) { rioUILog.delete(); } System.out.println("Creating log file in "+rioUILog.getAbsolutePath()); try { System.setErr(new PrintStream(new FileOutputStream(rioUILog))); } catch(FileNotFoundException e) { e.printStackTrace(); } System.err.println("==============================================="); System.err.println("Rio Monitor UI\n"+ "Log creation : "+new Date(startTime).toString()+"\n"+ "Operator : "+System.getProperty("user.name")); System.err.println("==============================================="); } private static String generateGroovyOverride(long multicastAnnouncementInterval) throws IOException { String[] lines = new String[] { "import org.rioproject.config.Component\n", "@Component('net.jini.discovery.LookupDiscovery')\n", "class DiscoveryConfig {\n", " long multicastAnnouncementInterval = "+multicastAnnouncementInterval+"\n", "}" }; File tmp = File.createTempFile("tmp", ".groovy"); tmp.deleteOnExit(); BufferedWriter out = null; try { out = new BufferedWriter(new FileWriter(tmp)); for (String line : lines) { out.write(line); } } finally { if (out != null) out.close(); } return tmp.getCanonicalPath(); } private static String generateJiniOverride(long multicastAnnouncementInterval) { String lookupComponent = "net.jini.discovery.LookupDiscovery"; return lookupComponent+".multicastAnnouncementInterval="+multicastAnnouncementInterval; } @SuppressWarnings("unchecked") public static void main(final String[] args) { try { Main frame; final LinkedList<String> commandArgs = new LinkedList<String>(); commandArgs.addAll(Arrays.asList(args)); for(String arg : args) { if (arg.startsWith("groups")) { String[] values = arg.split("="); String groupsArg = values[1].trim(); String s = System.getProperty(org.rioproject.config.Constants.GROUPS_PROPERTY_NAME); groupsArg = s!=null? s+","+groupsArg : groupsArg; System.setProperty(org.rioproject.config.Constants.GROUPS_PROPERTY_NAME, groupsArg); commandArgs.remove(arg); } else if (arg.startsWith("locators")) { String[] values = arg.split("="); String locatorsArg = values[1].trim(); String[] locators = locatorsArg.split(","); StringBuilder sb = new StringBuilder(); int i=0; for(String locator : locators) { if(!locator.startsWith("jini://")) locator = "jini://"+locator; if(i>0) sb.append(","); sb.append(locator); i++; } locatorsArg = sb.toString(); String s = System.getProperty(org.rioproject.config.Constants.LOCATOR_PROPERTY_NAME); locatorsArg = s!=null? s+","+locatorsArg : locatorsArg; System.setProperty(org.rioproject.config.Constants.LOCATOR_PROPERTY_NAME, locatorsArg); commandArgs.remove(arg); } } /* Set the interval to wait for multicast announcements to 5 seconds */ long multicastAnnouncementInterval = 5000; String override; /* Add the interval to wait for multicast announcements as an override */ if(commandArgs.isEmpty()) { override = generateGroovyOverride(multicastAnnouncementInterval); } else { if(commandArgs.get(0).endsWith(".groovy")) { override = generateGroovyOverride(multicastAnnouncementInterval); } else { override = generateJiniOverride(multicastAnnouncementInterval); } } commandArgs.add(override); String[] newArgs = commandArgs.toArray(new String[commandArgs.size()]); final Configuration config = ConfigurationProvider.getInstance(newArgs); final Properties props = new Properties(); try { props.putAll(loadProperties(Constants.UI_PROPS)); } catch(IOException e) { // } PrivilegedExceptionAction<Main> createViewer = new PrivilegedExceptionAction<Main>() { public Main run() throws Exception { System.setSecurityManager(new SecurityManager()); /* Set properties for execution on a Mac client */ if(MacUIHelper.isMacOS()) { MacUIHelper.setSystemProperties(); } /* If the artifact URL has not been configured, set it up */ try { new URL("artifact:foo"); } catch (MalformedURLException e) { URL.setURLStreamHandlerFactory(new ArtifactURLStreamHandlerFactory()); } Main.redirect(); //Installer.install(); return new Main(config, true, props); } }; try { LoginContext loginContext = (LoginContext) Config.getNonNullEntry(config, Constants.COMPONENT, "loginContext", LoginContext.class); loginContext.login(); frame = Subject.doAsPrivileged(loginContext.getSubject(), createViewer, null); } catch(NoSuchEntryException e) { frame = createViewer.run(); } final Main mainUI = frame; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { mainUI.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); mainUI.pack(); String s = props.getProperty(Constants.FRAME_WIDTH); int width = (s == null ? 700 : Integer.parseInt(s)); s = props.getProperty(Constants.FRAME_HEIGHT); int height = (s == null ? 690 : Integer.parseInt(s)); mainUI.setSize(new Dimension(width, height)); s = props.getProperty(Constants.FRAME_X_POS); if (s != null) { double xPos = Double.parseDouble(s); double yPos = Double.parseDouble(props.getProperty(Constants.FRAME_Y_POS)); mainUI.setLocation((int) xPos, (int) yPos); } mainUI.setVisible(true); mainUI.setStartupLocations(props); try { mainUI.startDiscovery(); } catch(Exception e) { e.printStackTrace(); } }}); } catch(Exception e) { e.printStackTrace(); System.exit(1); } } }