|
Advanced Console Customization
|
This section describes:
This section includes guidelines as they apply to Static and Dynamic Menus and other general information. These general guidelines also apply to Cell Editors and the Configurable Details Window Interface. Specific requirements and exceptions are listed in the individual sections.
Note - If the user application crashes due to a runtime exception, the console will crash as well.
Exiting Applications Launched from Static and Dynamic Menus
Do not use calls to System.exit() to exit the program. If you do, the entire console window will exit, as well as the integrated package. To exit, make the following calls for the appropriate frames:
- frame.setVisible(false);
- frame.dispose();
Launching a Java Program from Multiple Places in Modules
Note - This section does not apply to "Configurable Details Window Interface."
If it is necessary for the Java program to be aware of where it was launched, then specify a unique argument for each of the following consoleHints:
- For Dynamic Menus:
- consoleHint:tableMenuGenerator
- consoleHint:columnHeaderMenuGenerator
- For Static Menus:
- consoleHint:commandSpec (cmd)
Note - Note that args can be used to allow different places in the program to specify the same Java file with different arguments to let the Java program know it was called from a different place. For examples of how to define args, refer to the following sections: "To Add Additional Popup Menu Options at the Module or Managed Object Level", "To Add Menu Choices At the Table Level", "To Specify New Dynamic Menu choice(s) Over a Table Cell", "To Specify New Dynamic Menu Choice(s) Over a Table Column Header", "To Specify a Custom Cell Editor".
General Integration Guidelines
The following are general integration guidelines for both static and dynamic menus.
- All class files and properties files associated with the user application to be integrated must be placed on the Sun Management Center server in the directory:
/<SUNWsymon_Installation_Directory>/SUNWsymon/apps/classes
|
- The classes may be packed into a .jar file, or left as separate .class files.
- It is necessary to stop and restart the console after making any changes to the Java code that is placed in the /opt/SUNWsymon/apps/classes directory. Note that the Sun Management Center infrastructure manages setting the Java CLASSPATH environment variable to properly access any jar files that are placed in this directory. For a sample of how to stop and restart the console, refer to the section, "To Test Popup Menus and See the Changes".
- It is also necessary stop and restart the agent if any agent module file is changed.
Static Menus provides a method for customizing popup menus in the Browser tab accessed from the Host Details window.
When a user right clicks the mouse over an object in a module, the Sun Management Center displays a popup menu. Developers can add their own choices to the menu at the following places:
- over the module itself
- over a manged property (or folder)
- over a table (but not over the table column header)
Customizing Static Popup Menus
Developers specify the new menu options and associated launch commands in the Module Definition (-d.x) file and specify the Java class to be invoked when the new menu items are selected. This interface is called "Static" because the menu choices are hardcoded in the Module Definition (-d.x) file. In addition, developers may localize the menu items labels and use the provided SMHelpBrowser class to provide help for any new menu items.
The Java program that is invoked when the new menu items are selected must be placed in the following directory: /<Sun_Management_Center_installation_directory>/SUNWsymon/apps/classes.
The Java program is launched with the necessary contextual information so it can determine which object the mouse was over when the program was launched. For example, a menu choice could be added over a table. If a user brings the popup menu over a particular cell in the table and launches the Java program, the program can determine its cell value.
To define additional commands, the consoleHint:commands list indexes the set of available commands. The consoleHint:commandLabel(cmd) and consoleHint:commandSpec(cmd) define each command's information.
|
To Add Additional Popup Menu Options at the Module or Managed Object Level
|
 |
Add the following statements to the module definition file (this example adds two
additional menu choices):
consoleHint:commands = myapp1 myapp2
consoleHint:commandLabel(myapp1) = My First Application
consoleHint:commandSpec(myapp1) = launchApp acmecorp.MyApp arg1 arg2
consoleHint:commandLabel(myapp2) = My Second Application
consoleHint:commandSpec(myapp2) = launchApp acemecorp.SecondApp
|
|
_
|
|
Each command launches the custom application specified by its consoleHint:commandSpec() property. The arguments (arg1 arg2 ...) are passed to the application. These statements are placed in the agent file, for example acmemodule-d.x. When this module is subsequently loaded, two new menu items "My First Application" and "My Second Application" appear in the popup menu. |
Note - The particular location at which the popup menu choices are included in the Module Definition (-d.x) file determines where the menu choices will appear in the module.
|
To Add Menu Choices At the Table Level
|
 |
Include these statements for a table definition in the module file.
consoleHint:tableCommands = myapp
consoleHint:commandLabel(myapp) = My Application
consoleHint:commandSpec(myapp) = launchApp acmecorp.MyApp arg1 arg2
|
|
_
These lines are similar to the lines in the previous example, except that consoleHint:tableCommands is used instead of consoleHint:commands. Once added, the menu item "My Application" will appear in the popup menu.
Integration Guidelines and Notes for Static Menus
This section provides information and guidelines for performing the integration.
The following guidelines are applicable for the SMModApp or SMModAppAdapter.
- Make sure to implement a Java class that implements the interface SMModApp or extends the class SMModAppAdapter.
- Note that for Static menus, the SMModApp/SMModAppAdapter methods are called in the following order after the null constructor (a constructor with no arguments) is called:
- setRawDataRequest
- setAgentPort
- setAgentHost
- setAgentTopologyName
- setURL
- setArguments
- init
SMHelpBrowser
A standard Help class is provided to allow user-specific help text to be displayed using the Sun Management Center help system. You can invoke a Help class from a popup menu.
|
To Invoke a Help Class
|
 |
Include the following lines inside the module file:
consoleHint:commands = myhelp
consoleHint:commandLabel(myhelp) = My Help
consoleHint:commandSpec(myhelp) = launchApp\
com.sun.symon.apps.generic.help.SMHelpBrowser myhelpkey
|
|
_
where
- myhelpkey is either a full URL for an HTML file containing the help text, or a help key. If it is a help key, then the online help for the application must be integrated into the Sun Management Center. For more information on the help key, refer to "Help Key Usage".
Once done, the menu item, "My Help" appears in the popup menu. When this menu item is selected, the Sun Management Center help system will display the user-specified help text.
|
To Integrate the Online Help Mapping Key
|
In order to use a help key, integrate a mapping from the key to the HTML online help for the application into Sun Management Center.
 |
Run one of the following commands from the post-install and pre-remove scripts
of the server package for the application that you want to integrate:
es-chelp -a key file
es-chelp -d key
|
|
_
where
- -a and -d add and delete an entry, respectively, to and from the mapping.
- key is any unique user-specified name for the application.
- file is the name of the HTML file to display.
Note - The actual HTML help file for your application must be installed on the Sun Management Center help server.
For example:
es-chelp -a acmehelp ACME_module_help.html
es-chelp -d acmehelp
|
- In the first line, a new mapping is maps the key acmehelp to the HTML file ACME_module_help.html. The help key acmehelp can then be passed as an argument to SM Help Browser.
- In the second line, the mapping is deleted.
Note - For more information on the help key, refer to "Help Key Usage".
Troubleshooting for Static Menus
Sun Management Center errors or debugging messages at the console level.
Console Message Exceptions
- If the console messages includes the following exception:
java.lang.IllegalAccessException at java.lang.Class.newInstance0(Native Method)
|
- Make sure constructor of class being launched is public.
- If the console messages includes the following exception
java.lang.InstantiationException at java.lang.Class.newInstance0(Native Method)
|
- Make sure that all of the interface's methods are defined, if using the SMModApp interface. Another option is to extend the SMModAppAdapter instead.
Strange Behavior of Integrated Program if Invoked Multiple Times
If the integrated program acts strangely when it is invoked multiple times, you will see the following behavior:
- Changing information in one instance causes the state of other instances to change as well.
- It is only possible to exit one of the instances.
The solution is to only make sure that no classes or variables are defined as static in the integrated program.
New Menu Choices are Not Visible for Static Menus
If the new menu choice is not visible over the expected node, check the module-d.x file for the following:
- If the new menu choice is supposed to be displayed over a table, make sure this consoleHint is being used: consoleHint:tableCommands.
- If the new menu choice is supposed to be displayed over a module or a managed object, make sure that this consoleHint is being used: consoleHint:commands.
- Make sure that the consoleHints are defined within the proper section of the modules-d.x file:
- Define the consoleHints outside all curly braces "{ ... }" for the menu option to appear over the module.
- Define the consoleHints inside the managed object's curly braces to appear over the managed object.
- Define the consoleHints inside the table entry's object curly braces to appear over a table.
Example: staticmenu-version01-d.x
CODE EXAMPLE 17-1 staticmenu-version01-d.x
|
#Copyright 05/10/99 Sun Microsystems, Inc. All Rights Reserved.
#pragma ident "@(#)staticmenu-version01-d.x 1.3 99/05/10 Sun Microsystems"
[ use MANAGED-MODULE ]
[ requires template staticmenu-version01-models-d ]
#
# Tell that the following package is needed.
#
[ load staticmenu-version01-m.x ]
_services = { [ use SERVICE ]
sh = {
command = "pipe://localhost//bin/sh;transport=shell"
max = 1
}
}
refreshService = _internal
StaticMenuManagedObject = { [ use templates.staticmenu-version01-models-\
d.StaticMenuManagedObject ]
type = active
initInterval = 1
refreshService = _services.sh
refreshCommand = staticmenu-version01.sh
refreshInterval = 3600
# The following consoleHint adds the Context2 menu choice to the table.
#
consoleHint:commands = Context2
# Menu option = "Managed Object Context Example"
#
# The following two consoleHints specify the commandLabel (text label)
# and commandSpec (Java launch command) for the Context2 menu choice.
# Note that the program SMContextExample is called and is passed one
# argument ("Managed Object Level").
#
consoleHint:commandLabel(Context2) = Managed Object Context Example
consoleHint:commandSpec(Context2) = launchApp SMContextExample "Managed\
Object Level"
StaticMenuTable = {
StaticMenuEntry = {
# The following consoleHint adds the Context3 menu choice to the table.
#
consoleHint:tableCommands = Context3
# Menu option = "Table Context Example"
#
# The following two consoleHints specify the commandLabel (text label)
# and commandSpec (Java launch command) for the Context3 menu choice.
# Note that the program SMContextExample is called and is passed one
# argument ("Table Level").
#
consoleHint:commandLabel(Context3) = Table Context Example
consoleHint:commandSpec(Context3) = launchApp\
SMContextExample "Table Level"
}
}
}
# The following consoleHint adds Hello and Context1 menu choices to the module.
#
consoleHint:commands = Hello Context1
# Menu option = "StaticMenu Example!"
#
# The following two consoleHints specify the commandLabel (text label) and
# commandSpec (Java launch command) for the Hello menu choice.
# Note that the program SMHello is called and is passed no arguments.
#
consoleHint:commandLabel(Hello) = Static Menu Example!
consoleHint:commandSpec(Hello) = launchApp SMHello
# Menu option = "Module Context Example"
#
# The following two consoleHints specify the commandLabel (text label) and
# commandSpec (Java launch command) for the Context1 menu choice.
# Note that the program SMContextExample is called and is passed one
# argument ("Module Level").
#
consoleHint:commandLabel(Context1) = Module Context Example
consoleHint:commandSpec(Context1) = launchApp SMContextExample "Module Level"
|
Example: SMHello.java
SMHello.java shows how to launch a program from Sun Management Center. The launched program does not interact with Sun Management Center in any other way.
CODE EXAMPLE 17-2 SMHello.java
|
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class SMHello implements ActionListener {
JFrame frame;
JPanel panel;
// Constructor
//
public SMHello() {
frame = new JFrame("Hello World");
panel = new JPanel();
panel.setLayout(new BorderLayout());
}
// init - Build GUI and display.
//
public void init() {
JButton button = new JButton("Close");
panel.add(button, BorderLayout.SOUTH);
button.addActionListener(this);
panel.add(new JLabel("Hello World from Sun Management
Center!"),
BorderLayout.NORTH);
frame.getContentPane().add("Center", panel);
frame.pack();
frame.setVisible(true);
}
// actionPerformed - Exit program when Quit button is pressed.
//
public void actionPerformed(ActionEvent e) {
frame.setVisible(false);
frame.dispose();
}
// main - Program entry point.
//
public static void main(String argv[]) {
// Note that a call to the System.exit() method is not
// a valid way to exit programs that are integrated with
// Sun Management Center. This is the preferred method.
//
SMHello helloPanel = new SMHello();
helloPanel.init();
}
}
|
Example: SMContextExample.java
SMContextExample.java shows how to display contexual information in the launched program. The program shows the table cell value that the user's mouse was hovering over when they launched the application.
CODE EXAMPLE 17-3 SMContextExample.java
|
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.sun.symon.base.server.types.*;
import com.sun.symon.base.client.console.*;
import com.sun.symon.base.client.*;
public class SMContextExample implements ActionListener, SMModApp
{
JFrame frame;
JPanel panel;
SMRawDataRequest handle;
String hostName;
String topologyName;
SMUrlContext urlName;
String[] args;
int portNo;
// Constructor
//
public SMContextExample() {
frame = new JFrame("Context Example");
panel = new JPanel();
panel.setLayout(new BorderLayout());
}
// setAgentHost - Sets the agent host name.
//
public void setAgentHost(String hostInput) {
hostName = hostInput;
}
// setAgentName - Sets the topology node name.
//
public void setAgentName(String nameInput) {
topologyName = nameInput;
}
// setAgentPort - Sets the agent port number.
//
public void setAgentPort(int portInput) {
portNo = portInput;
}
// setRawDataRequestHandle - Sets the client API handle.
//
public void setRawDataRequestHandle(SMRawDataRequest\
handleInput) {
handle = handleInput;
}
// setUrlContext - Sets the object URL.
//
public void setUrlContext(SMUrlContext urlInput) {
urlName = urlInput;
}
// setArguments - Allows arguments specified in the launchApp
// command to be passed to the application.
//
public void setArguments(String[] argsInput) {
args = argsInput;
}
// init - This is an initialization method for third party
// applications that integrate into Sun Management
// Center. It gets called after all the set methods
// in the SMModApp interface get called.
//
public void init() {
JPanel gridPanel;
gridPanel = new JPanel();
JButton button = new JButton("Close");
button.addActionListener(this);
panel.add(button, BorderLayout.SOUTH);
try
{
// The gridPanel will have 2 rows for the host name
// and topology name. An additional row for each value
// in the args Array (in this example this value is 1).
//
int numRows = 2 + args.length;
// If the user launched this application from a
// table, then the 1st argument to this script
// will be the string "Table Level". In this case
// this program will retrieve the cell value
// associated with the cell the mouse was pointing.
//
// Must convert urlName variable into the "request"
// array of Strings, so we can call the getURLValue
// clientAPI method. This returns the value of the
// cell into the "urlValue" variable.
//
String [] request = new String[1];
StObject [][] urlValue = null;
if (args[0].compareTo("Table Level") == 0) {
String nodeUrl = "";
try {
nodeUrl = SMRawDataRequest.createURL(
urlName.getHost(), urlName.getAgentPort(),
urlName.getModuleId(), urlName.getInstance(),
urlName.getManagedObject(),
urlName.getProperty(),
urlName.getPropertyType(), "",
urlName.getPropertyInstance());
} catch (Exception ex) {
ex.printStackTrace();
}
request[0] = nodeUrl;
urlValue = handle.getURLValue(request);
// Add 1 row in the gridPanel for the value in
// the cell.
//
numRows++;
}
gridPanel.setLayout(new GridLayout(numRows, 2, 3, 3));
gridPanel.add(new JLabel("Host name:"));
gridPanel.add(new JLabel(hostName));
gridPanel.add(new JLabel("Topology name:"));
gridPanel.add(new JLabel(topologyName));
// Display list of arguments.
//
for (int i = 0; i < args.length; i++)
{
gridPanel.add(new JLabel("Argument:"));
gridPanel.add(new JLabel(args[i]));
}
// If this program was launched from a table, we
// retrieved the cell value above. Now display
// that value.
//
if (args[0].compareTo("Table Level") == 0)
{
gridPanel.add(new JLabel("Value:"));
gridPanel.add(new JLabel(urlValue[0][0].toString()));
}
}
// The getURLValue() method throws an exception. We will
// catch it here and display the error message to the
// gridPanel.
//
catch (Exception e)
{
gridPanel.setLayout(new GridLayout(1, 2, 3, 3));
gridPanel.add(new JLabel("Exception:"));
gridPanel.add(new JLabel(e.getMessage()));
}
panel.add(gridPanel, BorderLayout.NORTH);
frame.getContentPane().add("Center", panel);
frame.pack();
frame.setVisible(true);
}
// actionPerformed - Exit program when Close button is pressed.
//
public void actionPerformed(ActionEvent e)
{
// Note that a call to the System.exit() method is not
// a valid way to exit programs that are integrated with
// Sun Management Center. This is the preferred method.
//
frame.setVisible(false);
frame.dispose();
}
}
|
Dynamic Menus provide a method for customizing popup menus in the Browser tab accessed from the Host Details window.
When a user right clicks the mouse over an object in a module, the Sun Management Center displays a popup menu. Developers can add their own choices to the menu at the following places:
- table cells
- table column headers
- managed properties
Customizing Dynamic Popup Menus
Developers specify a Java class in the Module Definition (-d.x) file, which is invoked to build the new menu items. This interface is called "dynamic" because the menu choices are built dynamically at run time. Developers supply ActionListeners in the Java code, which get launched when a new menu item is selected. In addition, developers can localize the menu items labels.
The Java program that is invoked when the new menu items are selected must be placed in the following directory:
/<Sun_Management_Center_installation_directory>/SUNWsymon/apps/classes
|
The Java program is launched with the necessary contextual information so it can determine which object the mouse was over when the program was launched. For example, a menu choice can be added over a table. If you bring up the popup menu over a particular cell in the table and launch the Java program, the program can determine its cell value.
|
To Specify New Dynamic Menu choice(s) Over a Table Cell
|
 |
Implement the following consoleHint command for the table object in the module
definition (-d.x) file:
consoleHint:tableMenuGenerator = javaClass [ args ]
|
|
_
|
To Specify New Dynamic Menu Choice(s) Over a Table Column Header
|
 |
Implement the following consoleHint for the table column object in the module
definition (-d.x) file:
consoleHint:columnHeaderMenuGenerator = javaClass [ args ]
|
|
_
|
To Test Popup Menus and See the Changes
|
Note - The following procedure only applies if you change the module files.
|
1. |
Exit any Sun Management Center Host Detail screen. |
|
2. |
Restart the Sun Management Center agent. |
|
3. |
Bring back up the Sun Management Center host detail screen. |
You will see the changes that were added to the module definition (-d.x) file.
Note - It is necessary to stop and restart the console after making any changes to the Java code that is placed in the /opt/SUNWsymon/apps/classes directory.
Rules for Java Implementation for Dynamic Popup Menus
The java class specified in either the tableMenuGenerator or the columnHeaderMenuGenerator consoleHint must either implement:
com.sun.symon.base.client.console.SMMenuGenerator
|
or, extend:
com.sun.symon.base.client.console.SMMenuGeneratorAdapter
|
Internationalization for Dynamic Popup Menus
For information on how you can internationalize the menu choices displayed in the popup menu, refer to Chapter 19 and Chapter 20.
For example, you can enter the following in the Java implementation:
import com.sun.sytmon.base.utility.UcInternationalizer
[ ... ]
String menuChoice =
UcInternationalizer.translateKey("myPath.myResourceBundle:myMenuKey");
|
Troubleshooting (Dynamic Popup Menus)
The following sections provides solutions to some of the common problems.
To view errors or debugging messages, select the: "File -> Sun Management Center-Console Messages..." menu choice from the main Sun Management Center screen.
This section includes common errors and their solutions.
Console Message Exceptions
If the console message includes the following exception:
java.lang.IllegalAccessException at java.lang.Class.newInstance0(Native Method)
|
Make sure that the constructor of class being launched is public.
Strange Behavior of Integrated Program when Invoked Multiple Times
If the integrated program acts strangely when it is invoked multiple times, you will see the following behavior:
- Changing information in one instance causes the state of other instances to change as well.
- It is only possible to exit one of the instances.
- Each table and table column header keeps track of its own dynamic menu. Therefore, the SMMenuGenerator constructor and init() methods are only called the first time the dynamic menu is raised for a given table or table column header. However, the getMenuItems() method is called each time the popup is raised.
- Therefore, make sure that any data that needs to be unique each time the SMMenuGenerator menu is displayed is defined in the getMenuItems() method. Also, make sure that no classes or variables are defined as static in the implementation of SMMenuGenerator.
New Menu Choices Are Not Visible for Dynamic Popup Menus
|
1. |
Check the module realization (-d.x) File for the following: |
- If the new menu choice is to be displayed over a table, then use: consoleHint:tableMenuGenerator.
- If the new menu choice is to be displayed over a table column, then use: consoleHint:columnHeaderMenuGenerator.
|
2. |
Make sure that the consoleHints are defined within the proper section of the module realization (-d.x) file. |
Note - For more information on this topic, also refer to "New Menu Choices are Not Visible for Static Menus".
Example: Dynamic Menu
CODE EXAMPLE 17-4 dynamicmenu-version01-d.x
|
#Copyright 05/10/99 Sun Microsystems, Inc. All Rights Reserved.
#pragma ident "@(#)dynamicmenu-version01-d.x 1.3 99/05/10 Sun Microsystems"
[ use MANAGED-MODULE ]
[ requires template dynamicmenu-version01-models-d ]
#
# Tell that the following package is needed.
#
[ load dynamicmenu-version01-m.x ]
_services = { [ use SERVICE ]
sh = {
command = "pipe://localhost//bin/sh;transport=shell"
max = 1
}
}
refreshService = _internal
# EditCellManagedObject
#
# Displays examples of the various cell editors.
#
EditCellManagedObject = { [ use templates.dynamicmenu-version01-models-\
d.EditCellManagedObject ]
# Text Editor
#
EditCellTblCellText = {
type = passive
access = rw
consoleHint:editAccess = rw
}
# Integer Editor
#
EditCellTblCellInt = {
type = passive
access = rw
consoleHint:editAccess = rw
}
# Floating Point Number Editor
#
EditCellTblCellFloat = {
type = passive
access = rw
consoleHint:editAccess = rw
}
# Checkbox (Boolean) Editor
#
EditCellTblCellBool = {
type = passive
access = rw
consoleHint:editAccess = rw
consoleHint:customCellEditor =\
com.sun.symon.base.client.console.SMTblBooleanEditor
}
# Combo Box Editor
#
EditCellTblCellCombo = {
type = passive
access = rw
consoleHint:editAccess = rw
consoleHint:customCellEditor =\
com.sun.symon.base.client.console.SMTblComboBoxEditor
consoleHint:optionList = entry1 entry2 entry3
}
# Custom Editor - uses SMCustomCellEdit class provided with this
# example. Input must start with the letter A.
#
EditCellTblCellCustom = {
type = passive
access = rw
consoleHint:editAccess = rw
consoleHint:customCellEditor = SMCustomCellEdit
}
}
# DynamicMenuManagedObject
#
# Displays examples of the various dynamic menus.
#
DynamicMenuManagedObject = { [ use templates.dynamicmenu-version01-models-\
d.DynamicMenuManagedObject ]
DynamicMenuTable = {
type = active
initInterval = 1
refreshService = _services.sh
refreshCommand = dynamicmenu-version01.sh
refreshInterval = 3600
DynamicMenuEntry = {
# Table dynamic menu example.
#
consoleHint:tableMenuGenerator = SMDynamicMenu \
"arg one" "arg two"
DynamicMenuIndex = { [ use STRING MANAGED-PROPERTY ]
# Column Header dynamic menu example.
#
consoleHint:columnHeaderMenuGenerator = \
SMDynamicMenu "arg one" "arg two"
}
DynamicMenuTotalSize = { [ use INTHILO MANAGED-PROPERTY ]
# Column Header dynamic menu example.
#
consoleHint:columnHeaderMenuGenerator = SMDynamicMenu
}
DynamicMenuUsed = { [ use INTHILO MANAGED-PROPERTY ]
# Column Header dynamic menu example.
#
consoleHint:columnHeaderMenuGenerator = SMDynamicMenu
}
DynamicMenuAvailable = { [ use INTHILO MANAGED-PROPERTY ]
# Column Header dynamic menu example.
#
consoleHint:columnHeaderMenuGenerator = SMDynamicMenu
}
DynamicMenuCapacity = { [ use STRING MANAGED-PROPERTY ]
# Column Header dynamic menu example.
#
consoleHint:columnHeaderMenuGenerator = SMDynamicMenu
}
DynamicMenuMounted = { [ use STRING MANAGED-PROPERTY ]
# Column Header dynamic menu example.
#
consoleHint:columnHeaderMenuGenerator = SMDynamicMenu
}
}
}
}
|
Dynamic Menu Java Code
CODE EXAMPLE 17-5 SMDynamicMenu.java
|
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.sun.symon.base.client.console.SMMenuGenerator;
import com.sun.symon.base.client.console.SMContextPopupItem;
import com.sun.symon.base.client.console.SMContextPopupEvent;
import com.sun.symon.base.client.console.SMTblSelectionInfo;
import javax.swing.JSeparator;
import javax.swing.JMenuItem;
import java.awt.Point;
// SMDynamicMenu
//
// A definition of a dynamic menu.
//
public class SMDynamicMenu implements SMMenuGenerator {
private String[] args;
// It is recommended to implement any needed ActionListeners in
// a seperate class (like SMCustomPopup in this example). Note that
// the class that implements SMMenuGenerator is only instantiated
// once for each menu, and note that the getMenuItems method is
// called each time the menu must be displayed. Implementing the
// ActionListeners in a separate class reduces the possibility
// that there will be conflicts if multiple menu choices are
// running at the same time.
//
private SMCustomPopup customPopup;
// init - init the class, if necessary.
//
public void init(String[] argsIn) {
args = argsIn;
}
// getMenuItems - This method builds the menu choices that will be
// made available for the popup.
//
public SMContextPopupItem[] getMenuItems(SMContextPopupEvent ev) {
// The SMCustomPopup class implements the ActionListener for this
// example.
//
customPopup = new SMCustomPopup(args, ev);
SMContextPopupItem[] items = new SMContextPopupItem[5];
int j=1;
for (int i=0; i < 5; i++) {
if (i == 3) {
// Add a seperator at this position.
//
items[i] = new SMContextPopupItem(new JSeparator());
} else {
JMenuItem menuItem = new JMenuItem("Choice " +
String.valueOf(j));
j++;
// It is necessary to add ActionListeners for each menu
// choice in order for an action to be performed when the
// menu choice is selected.
//
menuItem.addActionListener(customPopup);
items[i] = new SMContextPopupItem(menuItem);
}
}
return items;
}
}
// SMCustomPopup
//
// The class that implements the ActionListener for this example.
//
class SMCustomPopup implements ActionListener {
private SMContextPopupEvent popupEvent;
private JFrame frame;
private String[] args;
// Constructor
//
public SMCustomPopup(String[] argsIn, SMContextPopupEvent pe) {
// Keep track of the popupevent information.
//
args = argsIn;
popupEvent = pe;
}
// actionPerformed - this method is called when the user selects
// the menu choice(s) associated with this class.
//
public void actionPerformed(ActionEvent e) {
// This example displays a popup that shows the contextual
// information about where the user brought up the pop-up
// menu.
//
JMenuItem source = (JMenuItem)e.getSource();
JPanel panel = new JPanel();
JPanel gridPanel = new JPanel();
JLabel selType = new JLabel();
int column = popupEvent.getColumn();
int rows[] = null;
int row = popupEvent.getRow();
frame = new JFrame("Dynamic Menu Example");
int gridRows = 9;
if (args != null) {
gridRows += args.length;
}
// Check to see if a row, column, or cell is selected. If so,
// then display information about the selection. Keep track of
// the number of rows in the gridPanel needed for each type of
// selection.
//
if (popupEvent.getCurrentSelectionInfo() == null) {
selType.setText("No Selection");
}
else {
int selectionType =
popupEvent.getCurrentSelectionInfo().getSelectionType();
if (selectionType == SMTblSelectionInfo.CELL_SELECTION) {
selType.setText("Cell Selection");
gridRows += 2;
}
else if (selectionType == SMTblSelectionInfo.COLUMN_SELECTION) {
selType.setText("Column Selection");
gridRows += 1;
}
else if (selectionType == SMTblSelectionInfo.ROW_SELECTION) {
selType.setText("Row Selection");
rows = popupEvent.getCurrentSelectionInfo().getSelectedRows();
if (rows == null) {
// To print "N/A" message.
//
gridRows += 1;
}
else {
gridRows += rows.length;
}
}
}
panel.setLayout(new BorderLayout());
gridPanel.setLayout(new GridLayout(gridRows, 2, 3, 3));
// Display information about where the user brought up the menu.
//
if (row == -1) {
gridPanel.add(new JLabel("User Clicked On"));
gridPanel.add(new JLabel("Column Header"));
}
else {
gridPanel.add(new JLabel("User Clicked On"));
gridPanel.add(new JLabel("Table Cell"));
}
gridPanel.add(new JLabel("Menu Choice"));
gridPanel.add(new JLabel(source.getText()));
if (args != null) {
for (int i=0; i < args.length; i++) {
gridPanel.add(new JLabel("Argument # " +
String.valueOf(i + 1)));
gridPanel.add(new JLabel(args[i]));
}
}
// Display information about the agent machine.
//
gridPanel.add(new JLabel("Agent Host"));
gridPanel.add(new JLabel(
popupEvent.getObjectDetailContext().getHost()));
gridPanel.add(new JLabel("Agent Node Name"));
gridPanel.add(new JLabel(
popupEvent.getObjectDetailContext().getNodeName()));
// Display information about what is selected, or that nothing is
// selected.
//
gridPanel.add(new JLabel("SelectionType"));
gridPanel.add(selType);
if (popupEvent.getCurrentSelectionInfo() != null) {
int selectionType =
popupEvent.getCurrentSelectionInfo().getSelectionType();
if (selectionType == SMTblSelectionInfo.COLUMN_SELECTION ||
selectionType == SMTblSelectionInfo.CELL_SELECTION) {
gridPanel.add(new JLabel("Selected Column"));
gridPanel.add(new JLabel(String.valueOf(
popupEvent.getCurrentSelectionInfo().getSelectedColumn())));
}
if (selectionType == SMTblSelectionInfo.CELL_SELECTION) {
gridPanel.add(new JLabel("Selected Row"));
gridPanel.add(new JLabel(String.valueOf(
popupEvent.getCurrentSelectionInfo().getSelectedRow())));
}
if (selectionType == SMTblSelectionInfo.ROW_SELECTION) {
if (rows == null) {
gridPanel.add(new JLabel("Selected Row # "));
gridPanel.add(new JLabel("N/A"));
}
else {
for (int i=0; i < rows.length; i++) {
gridPanel.add(new JLabel("Selected Row # " +
String.valueOf(i + 1)));
gridPanel.add(new JLabel(String.valueOf(rows[i])));
}
}
}
}
// Display the name of the column the user brought up the menu over.
//
gridPanel.add(new JLabel("Column Name"));
gridPanel.add(new JLabel(popupEvent.getColumnI18nName(column)));
// Display the column number that the user brought up the menu over.
//
gridPanel.add(new JLabel("Column"));
gridPanel.add(new JLabel(String.valueOf(column)));
// Display the row number that the user brought up the menu over.
//
gridPanel.add(new JLabel("Row"));
gridPanel.add(new JLabel(String.valueOf(row)));
// Display the data value that the user brought up the menu over.
//
gridPanel.add(new JLabel("Cell Value"));
gridPanel.add(new JLabel(popupEvent.getDataValue(row, column)));
// Finish building the popup.
//
panel.add(gridPanel, BorderLayout.NORTH);
// Define a close button so the popup can be closed.
//
JButton quitButton = new JButton("Close");
panel.add(quitButton, BorderLayout.SOUTH);
quitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
frame.setVisible(false);
frame.dispose();
}
});
frame.getContentPane().add("Center", panel);
frame.pack();
frame.setVisible(true);
}
}
|
Sun Management Center console developer can specify a cell editor for any table cell that appears under the "Browser" tab of the Sun Management Center Details window.
This section contains information on:
- Cell Editors that you can utilize in your modules to enter data values directly into a table without having to go into the Attribute Editor.
- How to create customized cell editors to meet specific needs.
This interface provides cell editors for any managed property.
You can extend the classes listed in the following table to define your own custom cell editor. When you click on an editable cell, the cell transforms into a widget allowing you to enter a value directly into the table:
TABLE 17-1 Classes Provided with the Core Application
SMTblCellEditor
| Base class for the other editors that does
no special error checking.
|
SMTblStringEditor
|
A text editor that allows you to enter any
valid text string.
|
SMTblIntEditor
|
An integer editor that allows you to enter
only valid integer values.
|
SMTblFloatEditor
|
A floating-point editor that editor allows
you to enter only valid floating point
values.
|
SMTblBooleanEditor
|
A boolean (checkbox) editor that cell editor
allows you to set a boolean value to true or
false with a standard Java checkbox widget.
|
SMTblComboBoxEditor
|
A combo-box cell editor that allows you to
select a choice from a standard Java pull
down combo box widget.
|
The application will beep and reject any invalid value.
All data types that can be defined in the module's module definition (-d.x) file automatically default to an editor that is appropriate for that data type. For example, a user can only enter integer values into a managed property defined to be of type INT in the module's Module Definition (-d.x) File.
Note - An agent object can augment the menu choices available in the table cell and table column header popup menus, but cannot alter or remove commands that have already been defined in the standard installation. Note also that integrated applications run in the same JVM as Sun Management Center.
|
To Specify that a Cell is Editable
|
The cell editor feature for a cell is automatically turned on for cells that are defined to be writable. Cells are defined to be writable with the access key being set to rw.
For more information on rw access, refer to "To Specify a Managed Property as Writable".
|
1. |
If you want a cell to be writable, but do not want the custom cell editor feature be turned on so that the cell can be editable when you run the console, the following consoleHint must be set in the module-definition (-d.x) file.
consoleHint:editAccess = ro
|
|
|
2. |
In addition to the consoleHint:editAccess, also specify the consoleHint:customCellEditor to make use of the Boolean (checkbox) and combo box cell editors. |
|
To Use the Boolean Editor
|
 |
Specify the following in the module's module definition (-d.x) file:
consoleHint:customCellEditor =
com.sun.symon.base.client.console.SMTblBooleanEditor
|
|
_
|
To Use the Combo Box Editor
|
 |
Specify the following in the module's module definition (-d.x) file:
consoleHint:customCellEditor =
com.sun.symon.base.client.console.SMTblComboBoxEditor
consoleHint:optionList = "combo option 1" "combo option 2" ...
|
|
_
The consoleHint:optionList specifies what choices are available in the combo box.
|
To Implement a Customized Cell Editor
|
|
1. |
Extending one of the provided classes. |
|
2. |
Define the consoleHint:customCellEditor appropriately as follows:
consoleHint:customCellEditor = MyCustomClass
|
|
|
To Specify a Custom Cell Editor
|
 |
Specify the following consoleHint inside the column definition for a table, or for
any managed property:
consoleHint:customCellEditor = javaClass [ args ]
|
|
_
Rules for Java Implementation of the Cell Editor
The java class specified in the customCellEditor consoleHint must extend one of the following:
com.sun.symon.base.client.console.SMTblCellEditor
com.sun.symon.base.client.console.SMTblBooleanEditor
com.sun.symon.base.client.console.SMTblComboBoxEditor
com.sun.symon.base.client.console.SMTblFloatEditor
com.sun.symon.base.client.console.SMTblIntEditor
com.sun.symon.base.client.console.SMTblStringEditor
|
All class files and properties files associated with the user application to be integrated should be placed on the Sun Management Center server in the directory:
/opt/SUNWsymon/apps/classes
|
The classes may be packed together into a .jar file, or left as separate .class files.
Arguments to the java class must be separated by a space. Quotes may be used to specify an argument that includes a space.
Internationalization of the Cell Editor
When using a Combo Box Cell Editor, it is possible to internationalize the combo box choices. For more information, refer to the section "Conforming to Internationalization and GUI Guidelines" and "Internationalize a Module".
|
To Internationalize Cell Editors
|
|
1. |
Define the following in MyModule-d.x file:
consoleHint:customCellEditor =
com.sun.symon.base.client.console.SMTblComboBoxEditor
consoleHint:optionList = base.modules.MyModule:MyComboKey1 \
base.modules.MyModule:MyComboKey2
|
|
|
2. |
Define the following in MyModule.properties file:
MyComboKey1=Choice 1
MyComboKey2=Choice 2
|
|
|
To Test Custom Cell Editors
|
|
1. |
Exit any Sun Management Center Host Detail screen. |
|
2. |
Restart the Sun Management Center agent. |
|
3. |
Bring back up the Sun Management Center Host Detail screen. |
|
4. |
Load the module that contains the cell editor, if necessary. |
|
|
The Cell Editor is now available in the module. |
Note - It is necessary to stop and restart the console after making any changes to the Java code that is placed in the /opt/SUNWsymon/apps/classes directory.
Example: Cell Editor
CODE EXAMPLE 17-6 Cell Editor Example Code
|
# EditCellManagedObject
#
# Displays examples of the various cell editors.
#
EditCellManagedObject = { [ use templates.dynamicmenu-version01\
-models-d.EditCellManagedObject ]
# Text Editor
#
EditCellTblCellText = {
type = passive
access = rw
consoleHint:editAccess = rw
}
# Integer Editor
#
EditCellTblCellInt = {
type = passive
access = rw
consoleHint:editAccess = rw
}
# Floating Point Number Editor
#
EditCellTblCellFloat = {
type = passive
access = rw
consoleHint:editAccess = rw
}
# Checkbox (Boolean) Editor
#
EditCellTblCellBool = {
type = passive
access = rw
consoleHint:editAccess = rw
consoleHint:customCellEditor =
com.sun.symon.base.client.console.SMTblBooleanEditor
}
# Combo Box Editor
#
EditCellTblCellCombo = {
type = passive
access = rw
consoleHint:editAccess = rw
consoleHint:customCellEditor = \
com.sun.symon.base.client.console.SMTblComboBoxEditor
consoleHint:optionList = entry1 entry2 entry3
}
# Custom Editor - uses SMCustomCellEdit class provided with this
# example. Input must start with the letter A.
#
EditCellTblCellCustom = {
type = passive
access = rw
consoleHint:editAccess = rw
consoleHint:customCellEditor = SMCustomCellEdit
}
}
|
Cell Editor Java Code
CODE EXAMPLE 17-7 SMCustomCellEdit.java
|
/*
* @(#)SMTblCellEditor.java 1.12 2000/01/31
*
* Copyright (c) 01/31/2000 Sun Inc. All Rights Reserved
*/
import java.awt.Toolkit;
import javax.swing.table.*;
import javax.swing.JTable;
import javax.swing.JTextField;
import java.awt.Component;
import com.sun.symon.base.client.console.SMTblCellEditor;
// SMCustomCellEdit
//
// Defines a custom cell editor that requires that the entry begin
// with the letter "A" (case-insensitive).
//
public class SMCustomCellEdit extends SMTblCellEditor {
// Constructor
//
public SMCustomCellEdit() {
super(new JTextField());
}
// getTableCellEditor
//
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
((JTextField)editorComponent).setText((String)value);
return editorComponent;
}
// getCellEditorValue
//
public Object getCellEditorValue() {
String returnValue = null;
String data = ((JTextField)editorComponent).getText();
if (data.toUpperCase().charAt(0) == `A') {
returnValue = data;
}
else {
Toolkit.getDefaultToolkit().beep();
}
return(returnValue);
}
}
|
Users can only run es-details for objects modeled with es-device.
es-details is used to specify the tabs that will be made available for a given Node_Object_Type. The Node_Object_Type must match the value that was entered into the es-device script.
es-details
es-details is used to specify which tabs will be displayed on the Sun Management Center Details window. These tabs include both the tabs provided with the Sun Management Center product and user-defined tabs.
Syntax
The es-details script uses the following syntax:
% es-details [ -a ] [ -f inputfile ] -n Node_Object_Type [ -o ] [ -u ]
|
where:
-a
|
All: All tabs provided by Sun Management
Center will be included.
|
-f inputfile
|
File: The name of the es-details input file
which contains a list of tabs to be used for
this object type.
|
-n Node_Object_Type
|
Node: Corresponds to the Node_Object_Type
entered in the es-device script. The tabs
will be modified for this object type.
|
-o
|
Overwrite: Allows the es-details script to
overwrite the output from a previous
execution of the es-details script. Only
meaningful when used with the -f option.
|
-u
|
Undo: Restores the object type to its
original state.
|
Note - In the above example, the -f and -u options are mutually exclusive.
Since the es-details script is only to be executed for Node_Object_Type values that are associated with Sun Management Center agents, the script validates that the Node_Object_Type corresponds to a Sun Management Center agent and will generate an error otherwise.
The es-details script is only to be executed for Node_Object_Type values that were added with the es-device script. Please ses Chapter 17 for more information about the es-device script. The es-details script will generate an error if the specified Node_Object_Type was not modelled with
es-device.
Adding Tabs Provided by Sun Management Center
The following syntax is used in the inputfile to specify which tabs provided by Sun Management Center that will be available for objects of Node_Object_Type:
INCLUDE SMC_TABNAME SMC_TABNAME ...
|
Where SMC_TABNAME can be one of the following choices:
- BROWSER
- ALARMS
- VIEWLOG
- APPLICATIONS
- HARDWARE
es-details generates an error message if you specify any other keyword for SMC_TABNAME.
The INFO tab must always be present on the Details screen and therefore is not a choice.
Even if you specify the tabs in any order in the inputfile, the tabs are always displayed in the same order in the Details Window. This order is, from left-to-right, INFO, BROWSER, ALARMS, VIEWLOG, APPLICATIONS, and HARDWARE.
Adding User-Defined Tabs
The following syntax is used in the inputfile to specify each user-defined tab that will be available for objects of Node_Object_Type:
APPEND TABNAME HELPKEY JAVACLASS
|
Where TABNAME is the name of the Tab to be added and JAVACLASS is the name of a user-provided Java class that meets the requirements in section 4.2: .
APPEND TABNAME HELPKEY JAVACLASS
|
The TABNAME must be entered in internationalized format and the associated property file must be properly installed. The format for the TABNAME value is as follows:
The format for the HELPKEY value is identical to the key:file or key:url format as specified for the "help" argument. For more information on the help key, refer to "Help Key Usage".
es-details generates an error message if the TABNAME, HELPKEY, or JAVACLASS arguments are not specified. The TABNAME and HELPKEY arguments must be in the correct format or an error message is generated.
Any user-defined tabs are placed to the right of the tabs that are provided by Sun Management Center. User-defined tabs will be ordered left-to-right in the order that they are defined in the inputfile.
Specifying an Open Default Tab when Launching Details Window
One tab can be specified as the tab that is open by default when the Details Window is launched. To specify this tab, specify the following line in the inputfile:
By default, the INFO tab is the default tab.
The specified default TABNAME must either be included in the inputfile or be included by using the es-details -a option, or an error message is generated. An error message will also be generated if you specify more than one default tab in the inputfile.
Example inputfile
The following is an example of an inputfile to the es-details program:
# es-details example input file.
# Include the following tabs provided by Sun Management Center
include browser alarms modules applications hardware
# Append a tab created by the user.
add SMTabHello:hellotab my-help:details.doc.html SMTabHello
# Specify the default tab to be the tab created by the user.
default SMTabHello:hellotab
|
Example: TabHello.java
CODE EXAMPLE 17-8 SMTabHello.java
|
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import com.sun.symon.base.client.SMRawDataRequest;
import com.sun.symon.base.client.console.SMAppBase;
public class SMTabHello extends SMAppBase implements
ActionListener {
private JLabel helloText; /* hello label */
private boolean state; /* hello state */
private int num_clicks; /* num of clicks */
private JLabel statusMsg; /* window status */
private int agentPort; /* agent port */
private String agentHost; /* agent host */
private SMRawDataRequest rawReq; /* raw data request\
handle */
// Constructor
//
public SMTabHello() {
state = false;
num_clicks = 0;
}
// init - Build GUI
//
public void init() {
setLayout(new BorderLayout());
helloText = new JLabel("Hello World...");
add(helloText, BorderLayout.NORTH);
JButton button = new JButton("Change Text");
add(button, BorderLayout.SOUTH);
button.addActionListener(this);
}
// destructService
//
public void destructService() {
}
// startRequest
//
public void startRequest() {
}
// stopRequest
//
public void stopRequest() {
}
// actionPerformed - Change the text in the helloText label.
//
public void actionPerformed(ActionEvent e) {
if (state == false) {
helloText.setText("...from " + agentHost + " " +
agentPort);
state = true;
} else {
helloText.setText("Hello World...");
state = false;
}
num_clicks++;
statusMsg.setText("You have pressed the button " +\
num_clicks + " times.");
}
// setRawDataRequestHandle
//
public void setRawDataRequestHandle(SMRawDataRequest handle) {
rawReq = handle;
}
// setAgentHost
//
public void setAgentHost(String host) {
agentHost = new String(host);
}
// setAgentPort
//
public void setAgentPort(int port) {
agentPort = port;
}
// setWindowStatusField
//
public void setWindowStatusField(Object statusField) {
statusMsg = (JLabel)statusField;
}
}
|
Removing Sun Management Center Default Tabs
To remove a tab normally included by Sun Management Center, do not specify it in the inputfile. If this is desired, then the es-details -a option must not be used.
Note - Removing the APPLICATIONS tab will cause any thrid-party applications that are integrated into this tab to be unavailable for machines of type, Node_Object_Type machines. It is not recommended that this tab be removed unless this behaviour is desired.
Re-Running es-details and Undo
 |
To re-run the es-details script as many times as desired for a given
Node_Object_Type, you must use the -o option to overwrite the previous settings.
|
_
Note - It is not necessary to use the -o option the first time that the es-details script is run for a given Node_Object_Type.
 |
To return the Node_Object_Type to its state before the es-details script was
executed the first time, use the -u option.
|
_
Note - The -u option stands for "undo".
Integration Guidelines and Notes
For more information, refer to "General Integration Guidelines".
Copyright © 2000 Sun Microsystems, Inc. All Rights Reserved.