/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 com.sun.jini.example.browser; import com.sun.jini.admin.DestroyAdmin; import com.sun.jini.config.Config; import com.sun.jini.logging.Levels; import com.sun.jini.proxy.BasicProxyTrustVerifier; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Frame; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.MalformedURLException; import java.rmi.server.ExportException; import java.util.StringTokenizer; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.tree.TreePath; import net.jini.admin.JoinAdmin; import net.jini.config.Configuration; import net.jini.config.ConfigurationException; import net.jini.core.discovery.LookupLocator; import net.jini.core.entry.Entry; import net.jini.core.event.EventRegistration; import net.jini.core.event.RemoteEvent; import net.jini.core.event.RemoteEventListener; import net.jini.core.lease.Lease; import net.jini.core.lookup.ServiceItem; import net.jini.core.lookup.ServiceRegistrar; import net.jini.core.lookup.ServiceTemplate; import net.jini.export.Exporter; import net.jini.jeri.BasicILFactory; import net.jini.jeri.BasicJeriExporter; import net.jini.jeri.tcp.TcpServerEndpoint; import net.jini.lease.LeaseListener; import net.jini.lease.LeaseRenewalEvent; import net.jini.lease.LeaseRenewalManager; import net.jini.lookup.DiscoveryAdmin; import net.jini.security.ProxyPreparer; import net.jini.security.TrustVerifier; import net.jini.security.proxytrust.ServerProxyTrust; /** * ServiceEditor is a gui-based utility to add/modify * attributes, groups and lookup locators. * And also supports some well known admin interfaces. * (DestroyAdmin, DiscoveryAdmin) * * <p> * current issues<br> * <ul> * <li> can't operate(add/remove/modify) array elements in an entry. * <li> does not support EntryBean. * <li> field modification is not based on EditableTree * </ul> * * @author Sun Microsystems, Inc. */ class ServiceEditor extends JFrame { private static final Logger logger = Browser.logger; private Browser browser; private ServiceItem item; private ServiceRegistrar registrar; protected Object admin; private ServiceTemplate stmpl; private NotifyReceiver receiver; private Lease elease = null; private long eventID = 0; private long seqNo = Long.MAX_VALUE; private AttributeTreePanel attrPanel; private final static int MINIMUM_WINDOW_WIDTH = 320; public ServiceEditor(ServiceItem item, Object admin, ServiceRegistrar registrar, Browser browser) { super("ServiceItem Editor"); this.item = item; this.admin = admin; this.registrar = registrar; this.browser = browser; // init main components attrPanel = new AttributeTreePanel(); // setup notify if(admin instanceof JoinAdmin) { try { stmpl = new ServiceTemplate(item.serviceID, new Class[] { item.service.getClass() }, new Entry[] {}); receiver = new NotifyReceiver(); setupNotify(); } catch (Throwable t) { logger.log(Level.INFO, "event registration failed", t); cancelNotify(); } } addWindowListener(browser.wrap(new WindowAdapter() { public void windowClosing(WindowEvent e) { cleanup(); } })); // add menu and attr panel getContentPane().setLayout(new BorderLayout()); getContentPane().add(new JoinMenuBar(), "North"); getContentPane().add(attrPanel, "Center"); validate(); pack(); setSize(((getSize().width < MINIMUM_WINDOW_WIDTH) ? MINIMUM_WINDOW_WIDTH : getSize().width), getSize().height); // center in parent frame Rectangle bounds = browser.getBounds(); Dimension dialogSize = getPreferredSize(); int xpos = bounds.x + (bounds.width - dialogSize.width)/ 2; int ypos = bounds.y + (bounds.height - dialogSize.height)/2; setLocation((xpos < 0) ? 0 : xpos, (ypos < 0) ? 0 : ypos); } void cleanup() { // cancel lease cancelNotify(); // release resources and close all child frames dispose(); receiver.unexport(); } protected void cancelNotify() { if(elease != null) { try { browser.leaseMgr.cancel(elease); } catch (Throwable t) { logger.log(Levels.HANDLED, "event cancellation failed", t); } elease = null; seqNo = Long.MAX_VALUE; } } protected void setupNotify() { if(registrar != null) { try { EventRegistration reg = registrar.notify(stmpl, ServiceRegistrar.TRANSITION_MATCH_NOMATCH | ServiceRegistrar.TRANSITION_NOMATCH_MATCH | ServiceRegistrar.TRANSITION_MATCH_MATCH, receiver.proxy, null, Lease.ANY); elease = (Lease) browser.leasePreparer.prepareProxy(reg.getLease()); browser.leaseMgr.renewUntil(elease, Lease.ANY, new Browser.LeaseNotify()); eventID = reg.getID(); seqNo = reg.getSequenceNumber(); } catch (Throwable t) { logger.log(Level.INFO, "event registration failed", t); } } } private class NotifyReceiver implements RemoteEventListener, ServerProxyTrust { private final Exporter exporter; final RemoteEventListener proxy; public NotifyReceiver() throws ConfigurationException, ExportException { exporter = (Exporter) Config.getNonNullEntry(browser.config, Browser.BROWSER, "listenerExporter", Exporter.class, new BasicJeriExporter( TcpServerEndpoint.getInstance(0), new BasicILFactory(), false, false)); proxy = (RemoteEventListener) exporter.export(this); } public void notify(final RemoteEvent ev) { SwingUtilities.invokeLater(browser.wrap(new Runnable() { public void run() { if (eventID == ev.getID() && seqNo < ev.getSequenceNumber()) { seqNo = ev.getSequenceNumber(); attrPanel.receiveNotify(); } } })); } public TrustVerifier getProxyVerifier() { return new BasicProxyTrustVerifier(proxy); } void unexport() { exporter.unexport(true); } } class JoinMenuBar extends JMenuBar { public JoinMenuBar() { JMenuItem mitem; // "File" Menu JMenu fileMenu = (JMenu) add(new JMenu("File")); mitem = (JMenuItem) fileMenu.add(new JMenuItem("Show Info")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { Class[] infs = Browser.getInterfaces(item.service.getClass()); String[] msg = new String[3 + infs.length]; msg[0] = "ServiceID: " + item.serviceID; msg[1] = "Service Instance: " + item.service.getClass().getName(); if(infs.length == 1) msg[2] = "Implemented Interface:"; else msg[2] = "Implemented Interfaces:"; for(int i = 0; i < infs.length; i++) msg[3 + i] = " " + infs[i].getName(); JOptionPane.showMessageDialog(ServiceEditor.this, msg, "ServiceItem Information", JOptionPane.INFORMATION_MESSAGE); } })); mitem = (JMenuItem) fileMenu.add(new JMenuItem("Refresh")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { attrPanel.refreshPanel(); } })); mitem = (JMenuItem) fileMenu.add(new JMenuItem("Close")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { cleanup(); } })); // "Edit" Menu JMenu editMenu = (JMenu) add(new JMenu("Edit")); mitem = (JMenuItem) editMenu.add(new JMenuItem("Add Attribute...")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { attrPanel.addAttr(); } })); if(! (admin instanceof JoinAdmin)) mitem.setEnabled(false); mitem = (JMenuItem) editMenu.add(new JMenuItem("Remove Attribute")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { attrPanel.removeAttr(); } })); if(! (admin instanceof JoinAdmin)) mitem.setEnabled(false); // "Admin" Menu JMenu adminMenu = (JMenu) add(new JMenu("Admin")); // Group (JoinAdmin) mitem = (JMenuItem) adminMenu.add(new JMenuItem("Joining groups...")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { new GroupLister("Joining Groups").showFrame(); } })); if(! (admin instanceof JoinAdmin)) mitem.setEnabled(false); // Locator (JoinAdmin) mitem = (JMenuItem) adminMenu.add(new JMenuItem("Joining locators...")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { new LocatorLister("Joining Locators").showFrame(); } })); if(! (admin instanceof JoinAdmin)) mitem.setEnabled(false); // separator adminMenu.addSeparator(); // Group (DiscoveryAdmin) mitem = (JMenuItem) adminMenu.add(new JMenuItem("Member groups...")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { new MemberGroupLister("Member Groups").showFrame(); } })); if(! (admin instanceof DiscoveryAdmin)) mitem.setEnabled(false); // Unicast port (DiscoveryAdmin) mitem = (JMenuItem) adminMenu.add(new JMenuItem("Unicast port...")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { try { String[] msg = { "Current port is " + ((DiscoveryAdmin) admin).getUnicastPort(), "Input a new value" }; String result = JOptionPane.showInputDialog(ServiceEditor.this, msg, "Unicast Port", JOptionPane.QUESTION_MESSAGE); if(result == null) return; try { int port = Integer.parseInt(result); ((DiscoveryAdmin) admin).setUnicastPort(port); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(ServiceEditor.this, result + " is not acceptable.", "Error", JOptionPane.ERROR_MESSAGE); } catch (Throwable t) { logger.log(Level.INFO, "setting unicast port failed", t); JOptionPane.showMessageDialog(ServiceEditor.this, t.getMessage(), t.getClass().getName(), JOptionPane.ERROR_MESSAGE); } } catch (Throwable t) { logger.log(Level.INFO, "getting unicast port failed", t); JOptionPane.showMessageDialog(ServiceEditor.this, t.getMessage(), t.getClass().getName(), JOptionPane.ERROR_MESSAGE); } } })); if(! (admin instanceof DiscoveryAdmin)) mitem.setEnabled(false); // separator adminMenu.addSeparator(); // DestroyAdmin mitem = (JMenuItem) adminMenu.add(new JMenuItem("Destroy")); mitem.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { if(JOptionPane.showConfirmDialog(ServiceEditor.this, "Are you sure to destroy this service?", "Query", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) try { ((DestroyAdmin) admin).destroy(); cleanup(); } catch (Throwable t) { logger.log(Level.INFO, "service destroy failed", t); JOptionPane.showMessageDialog(ServiceEditor.this, t.getMessage(), t.getClass().getName(), JOptionPane.ERROR_MESSAGE); } } })); if(! (admin instanceof DestroyAdmin)) mitem.setEnabled(false); } } class AttributeTreePanel extends EntryTreePanel { public AttributeTreePanel() { super(admin instanceof JoinAdmin); if(admin instanceof JoinAdmin) { tree.addMouseListener(browser.wrap(new DoubleClicker(this))); } refreshPanel(); } protected Entry[] getEntryArray() { if(admin instanceof JoinAdmin) { try { return ((JoinAdmin) admin).getLookupAttributes(); } catch (Throwable t) { logger.log(Level.INFO, "obtaining attributes failed", t); return null; } } return item.attributeSets; } protected void receiveNotify() { String[] msg = {"Attributes have been modified by another client or service provider itself.", "Do you want refresh attributes ?"}; int result = JOptionPane.showConfirmDialog(AttributeTreePanel.this, msg, "Query", JOptionPane.YES_NO_OPTION); if(result == JOptionPane.YES_OPTION) refreshPanel(); } public void editField(ObjectNode node) { String result = JOptionPane.showInputDialog(this, "Input a new value", "Modify a field", JOptionPane.QUESTION_MESSAGE); if(result == null){ } else { // Save current value as template Entry template = cloneEntry((Entry) node.getEntryTop()); Object oldVal = null; if(result.length() == 0){ oldVal = node.setValue(null); } else { oldVal = node.setValue(result); } // modifyAttribute try { node.setObjectRecursive(); Entry attr = (Entry) node.getEntryTop(); //Entry template = (Entry) generateTemplate(attr); // cancel notify while adding an attribute cancelNotify(); ((JoinAdmin) admin).modifyLookupAttributes( new Entry[] { template }, new Entry[] { attr }); setupNotify(); // Redraw node value model.nodeChanged(node); } catch (Throwable t) { logger.log(Level.INFO, "attribute modification failed", t); // recover tree node try { node.setValue(oldVal); node.setObjectRecursive(); } catch (Throwable tt) { logger.log(Levels.HANDLED, "node reset failed", tt); } model.nodeChanged(node); //model.nodeStructureChanged(node); // show dialog JOptionPane.showMessageDialog(AttributeTreePanel.this, t.getMessage(), t.getClass().getName(), JOptionPane.ERROR_MESSAGE); } } } public void addAttr() { String result = JOptionPane.showInputDialog(this, "Input an entry class name", "Add an attribute", JOptionPane.QUESTION_MESSAGE); if(result == null || result.length() == 0){ } else { try { Class clazz = Class.forName(result); Object attr = clazz.newInstance(); if(! (attr instanceof Entry)){ JOptionPane.showMessageDialog(AttributeTreePanel.this, "Does not implement Entry interface", "Unacceptable Class", JOptionPane.WARNING_MESSAGE); } else if(attr instanceof net.jini.lookup.entry.ServiceControlled){ JOptionPane.showMessageDialog(AttributeTreePanel.this, "Implements ServiceControlled interface", "Unacceptable Class", JOptionPane.WARNING_MESSAGE); } else { // cancel notify while adding an attribute cancelNotify(); ((JoinAdmin) admin).addLookupAttributes( new Entry[] { (Entry) attr }); // add node of this attribute ObjectNode node = new ObjectNode(attr, true); root.add(node); recursiveObjectTree(node); // setupNotify(); // refresh view model.nodesWereInserted(root, new int[] { model.getIndexOfChild(root, node) }); } } catch (ClassNotFoundException e) { JOptionPane.showMessageDialog(AttributeTreePanel.this, e.getMessage(), "Class Not Found", JOptionPane.WARNING_MESSAGE); } catch (Throwable t) { logger.log(Level.INFO, "adding attribute failed", t); JOptionPane.showMessageDialog(AttributeTreePanel.this, t.getMessage(), t.getClass().getName(), JOptionPane.WARNING_MESSAGE); } } } public void removeAttr() { ObjectNode node = (ObjectNode) tree.getLastSelectedPathComponent(); if(node == null){ JOptionPane.showMessageDialog(AttributeTreePanel.this, "Select an attribute folder to remove.", "Warning", JOptionPane.WARNING_MESSAGE); return; } else if(! node.isControllable()){ JOptionPane.showMessageDialog(AttributeTreePanel.this, "This attribute is under service provider's control.", "Warning", JOptionPane.WARNING_MESSAGE); return; } else if(! node.isEntryTop()){ JOptionPane.showMessageDialog(AttributeTreePanel.this, "Select a top of attribute folder.", "Warning", JOptionPane.WARNING_MESSAGE); return; } Entry target = (Entry) node.getObject(); int result = JOptionPane.showConfirmDialog(AttributeTreePanel.this, new String[] {"Remove attribute:", target.toString() }, "Query", JOptionPane.YES_NO_OPTION); if(result == JOptionPane.YES_OPTION){ // Remote Attribute try { // cancel notify while adding an attribute cancelNotify(); ((JoinAdmin) admin).modifyLookupAttributes( new Entry[] { target }, new Entry[] { null }); // setupNotify(); int index = root.getIndex(node); root.remove(node); model.nodesWereRemoved(root, new int[] {index}, new Object[] {node}); node = null; } catch (Throwable t) { logger.log(Level.INFO, "attribute removal failed", t); JOptionPane.showMessageDialog(AttributeTreePanel.this, t.getMessage(), t.getClass().getName(), JOptionPane.ERROR_MESSAGE); } } } private Entry cloneEntry(Entry attr) { try { Class realClass = attr.getClass(); Entry template = (Entry) realClass.newInstance(); Field[] f = realClass.getFields(); for(int i = 0; i < f.length; i++) { if(! usableField(f[i])) continue; f[i].set(template, f[i].get(attr)); } return template; } catch (Throwable t) { logger.log(Level.INFO, "duplicating entry failed", t); } return null; } // from EntryRep private boolean usableField(Field field) { Class desc = field.getDeclaringClass(); if(desc.isPrimitive()) { throw new IllegalArgumentException("primitive types not allowed in an Entry"); } // skip anything that isn't a public per-object mutable field int mods = field.getModifiers(); return (0 == (mods & (Modifier.TRANSIENT | Modifier.STATIC | Modifier.FINAL))); } private Entry generateTemplate(Entry attr) { try { Class realClass = attr.getClass(); Entry template = (Entry) realClass.newInstance(); Field[] f = realClass.getFields(); for(int i = 0; i < f.length; i++) f[i].set(template, null); return template; } catch (Throwable t) { logger.log(Level.INFO, "instantiating template failed", t); } return null; } class DoubleClicker extends MouseAdapter { AttributeTreePanel parent; public DoubleClicker(AttributeTreePanel parent){ this.parent = parent; } public void mouseClicked(MouseEvent ev){ if(ev.getClickCount() >= 2){ JTree tree = (JTree) ev.getSource(); TreePath path = tree.getPathForLocation(ev.getX(), ev.getY()); if(path == null) return; ObjectNode node = (ObjectNode) path.getLastPathComponent(); if(node.isLeaf()){ if(! node.isControllable()){ JOptionPane.showMessageDialog(AttributeTreePanel.this, "This attribute is under service provider's control.", "Warning", JOptionPane.WARNING_MESSAGE); } else if(node.isEditable() && ((ObjectNode) node.getParent()).isEntryTop()) { parent.editField(node); } else { JOptionPane.showMessageDialog(AttributeTreePanel.this, "This field is not editable.", "Warning", JOptionPane.WARNING_MESSAGE); } } tree.scrollPathToVisible(path); } } } } abstract class ListerFrame extends JFrame { private JList listBox; private JScrollPane scrollPane; protected DefaultListModel model = new DefaultListModel(); private DefaultListModel dummyModel = new DefaultListModel(); // to keep away from Swing's bug private JButton addButton; private JButton removeButton; private JButton closeButton; public ListerFrame(String title) { super(title); getContentPane().setLayout(new BorderLayout()); // create the initial list listBox = new JList(model); listBox.setFixedCellHeight(20); scrollPane = new JScrollPane(listBox); getContentPane().add(scrollPane, "Center"); //resetListModel(); // Create the controls JPanel buttonPanel = new JPanel(); addButton = new JButton("Add"); addButton.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { String result = JOptionPane.showInputDialog(ListerFrame.this, getAddMessage()); if(result != null){ StringTokenizer st = new StringTokenizer(result); String[] tokens = new String[st.countTokens()]; for(int i = 0; i < tokens.length; i++) tokens[i] = st.nextToken().trim(); addItems(tokens); resetListModel(); scrollPane.validate(); } } })); buttonPanel.add(addButton); removeButton = new JButton("Remove"); removeButton.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { Object[] selected = listBox.getSelectedValues(); if(selected == null || selected.length == 0){ // no items are selected JOptionPane.showMessageDialog(ListerFrame.this, "No items are selected", "Warning", JOptionPane.WARNING_MESSAGE); return; } int result = JOptionPane.showConfirmDialog(ListerFrame.this, getRemoveMessage(selected), "Query", JOptionPane.YES_NO_OPTION); if(result == JOptionPane.YES_OPTION){ removeItems(selected); resetListModel(); scrollPane.validate(); } } })); buttonPanel.add(removeButton); closeButton = new JButton("Close"); closeButton.addActionListener(browser.wrap(new ActionListener() { public void actionPerformed(ActionEvent ev) { setVisible(false); } })); buttonPanel.add(closeButton); getContentPane().add(buttonPanel, "South"); pack(); } public void showFrame() { // init list data resetListModel(); // center in parent frame Rectangle bounds = ServiceEditor.this.getBounds(); Dimension dialogSize = getPreferredSize(); setLocation(bounds.x + (bounds.width - dialogSize.width)/ 2, bounds.y + (bounds.height - dialogSize.height)/2); setVisible(true); } private void resetListModel() { //listBox.setModel(null); listBox.setModel(dummyModel); // to keep away from NullException (Swing's bug) model.removeAllElements(); initListModel(); listBox.setModel(model); listBox.clearSelection(); listBox.ensureIndexIsVisible(0); listBox.repaint(); listBox.revalidate(); } protected abstract void initListModel(); protected abstract String getAddMessage(); protected abstract String getRemoveMessage(Object[] items); protected abstract void addItems(String[] items); protected abstract void removeItems(Object[] items); } class GroupLister extends ListerFrame { public GroupLister(String title) { super(title); } protected void initListModel() { try { String[] groups = ((JoinAdmin) admin).getLookupGroups(); for(int i = 0; i < groups.length; i++) { model.addElement(new GroupItem(groups[i])); } } catch (Throwable t) { logger.log(Level.INFO, "obtaining groups failed", t); } } protected String getAddMessage() { return "Enter adding group(s)"; } protected String getRemoveMessage(Object[] items) { StringBuffer msg = new StringBuffer(); if(items.length > 1) msg.append("Remove these groups : "); else msg.append("Remove a group : "); for(int i = 0; i < items.length; i++) { if(i != 0) msg.append(", "); msg.append(((GroupItem) items[i]).toString()); } return msg.toString(); } protected void addItems(String[] items) { // check "public" String[] grps = new String[items.length]; for(int i = 0; i < items.length; i++) grps[i] = new GroupItem(items[i]).group; try { ((JoinAdmin) admin).addLookupGroups(grps); } catch (Throwable t) { logger.log(Level.INFO, "adding groups failed", t); } } protected void removeItems(Object[] items) { String[] grps = new String[items.length]; for(int i = 0; i < items.length; i++) grps[i] = ((GroupItem) items[i]).group; try { ((JoinAdmin) admin).removeLookupGroups(grps); } catch (Throwable t) { logger.log(Level.INFO, "removing groups failed", t); } } } class MemberGroupLister extends ListerFrame { public MemberGroupLister(String title) { super(title); } protected void initListModel() { try { String[] groups = ((DiscoveryAdmin) admin).getMemberGroups(); for(int i = 0; i < groups.length; i++) { model.addElement(new GroupItem(groups[i])); } } catch (Throwable t) { logger.log(Level.INFO, "obtaining groups failed", t); } } protected String getAddMessage() { return "Enter adding group(s)"; } protected String getRemoveMessage(Object[] items) { StringBuffer msg = new StringBuffer(); if(items.length > 1) msg.append("Remove these groups : "); else msg.append("Remove a group : "); for(int i = 0; i < items.length; i++) { if(i != 0) msg.append(", "); msg.append(((GroupItem) items[i]).toString()); } return msg.toString(); } protected void addItems(String[] items) { // check "public" String[] grps = new String[items.length]; for(int i = 0; i < items.length; i++) grps[i] = new GroupItem(items[i]).group; try { ((DiscoveryAdmin) admin).addMemberGroups(grps); } catch (Throwable t) { logger.log(Level.INFO, "adding groups failed", t); } } protected void removeItems(Object[] items) { String[] grps = new String[items.length]; for(int i = 0; i < items.length; i++) grps[i] = ((GroupItem) items[i]).group; try { ((DiscoveryAdmin) admin).removeMemberGroups(grps); } catch (Throwable t){ logger.log(Level.INFO, "removing groups failed", t); } } } class GroupItem { public String group; public GroupItem(String group) { if(group.equals("public")) this.group = ""; else this.group = group; } public String toString() { if("".equals(group)) return "public"; else return group; } } class LocatorLister extends ListerFrame { public LocatorLister(String title) { super(title); } protected void initListModel() { try { LookupLocator[] locators = ((JoinAdmin) admin).getLookupLocators(); for(int i = 0; i < locators.length; i++) { model.addElement(locators[i]); } } catch (Throwable t) { logger.log(Level.INFO, "obtaining locators failed", t); } } protected String getAddMessage() { return "Enter a new locator's URL"; } protected String getRemoveMessage(Object[] items) { StringBuffer msg = new StringBuffer(); if(items.length > 1) msg.append("Remove these locators : "); else msg.append("Remove a locator : "); for(int i = 0; i < items.length; i++) { if(i != 0) msg.append(", "); msg.append(items[i].toString()); } return msg.toString(); } protected void addItems(String[] items) { LookupLocator[] locs = new LookupLocator[items.length]; for(int i = 0; i < items.length; i++) { try { locs[i] = new LookupLocator(items[i]); } catch (MalformedURLException e) { JOptionPane.showMessageDialog(LocatorLister.this, "\"" + items[i] + "\": " + e.getMessage(), "Bad Locator", JOptionPane.WARNING_MESSAGE); return; } } try { ((JoinAdmin) admin).addLookupLocators(locs); } catch (Throwable t){ logger.log(Level.INFO, "adding locators failed", t); } } protected void removeItems(Object[] items) { LookupLocator[] locs = new LookupLocator[items.length]; for(int i = 0; i < items.length; i++) locs[i] = (LookupLocator) items[i]; try { ((JoinAdmin) admin).removeLookupLocators(locs); } catch (Throwable t) { logger.log(Level.INFO, "removing locators failed", t); } } } }