river-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gtra...@apache.org
Subject [20/40] git commit: Ongoing work to add client profile and run browser inside it.
Date Mon, 13 Jan 2014 03:35:27 GMT
Ongoing work to add client profile and run browser inside it.

Project: http://git-wip-us.apache.org/repos/asf/river-container/repo
Commit: http://git-wip-us.apache.org/repos/asf/river-container/commit/7ff8b15a
Tree: http://git-wip-us.apache.org/repos/asf/river-container/tree/7ff8b15a
Diff: http://git-wip-us.apache.org/repos/asf/river-container/diff/7ff8b15a

Branch: refs/heads/master
Commit: 7ff8b15a8b1c851363791de88dc76c63e2c8ab40
Parents: b8f2c0c
Author: Greg Trasuk <gtrasuk@apache.org>
Authored: Tue Nov 19 11:47:55 2013 -0500
Committer: Greg Trasuk <gtrasuk@apache.org>
Committed: Tue Nov 19 11:47:55 2013 -0500

----------------------------------------------------------------------
 browser-module/pom.xml                          |   11 +-
 browser-module/src/assemble/module.xml          |   15 +-
 browser-module/src/main/root/browser.config     |    2 +-
 browser-module/src/main/root/start.properties   |    2 +-
 browser/pom.xml                                 |   44 +
 .../river/container/examples/browser/App.java   |   13 +
 .../container/examples/browser/Browser.java     | 1765 ++++++++++++++++++
 .../examples/browser/EntryTreePanel.java        |  292 +++
 .../examples/browser/Introspector.java          |  106 ++
 .../container/examples/browser/MetalIcons.java  |  348 ++++
 .../container/examples/browser/ObjectNode.java  |  316 ++++
 .../examples/browser/ServiceBrowser.java        |  282 +++
 .../examples/browser/ServiceEditor.java         | 1213 ++++++++++++
 .../container/examples/browser/package.html     |  787 ++++++++
 .../apache/river/container/browser/AppTest.java |   38 +
 pom.xml                                         |    3 +-
 .../deployer/StarterServiceDeployer.java        |   71 +-
 17 files changed, 5248 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/river-container/blob/7ff8b15a/browser-module/pom.xml
----------------------------------------------------------------------
diff --git a/browser-module/pom.xml b/browser-module/pom.xml
index 63e6d94..593d5ed 100644
--- a/browser-module/pom.xml
+++ b/browser-module/pom.xml
@@ -32,16 +32,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.river</groupId>
+            <groupId>org.apache.river.container</groupId>
             <artifactId>browser</artifactId>
-            <version>2.2.2</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.river</groupId>
-            <artifactId>browser-dl</artifactId>
-            <version>2.2.2</version>
+            <version>1.0-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
 

http://git-wip-us.apache.org/repos/asf/river-container/blob/7ff8b15a/browser-module/src/assemble/module.xml
----------------------------------------------------------------------
diff --git a/browser-module/src/assemble/module.xml b/browser-module/src/assemble/module.xml
index e85ea9b..a456cfd 100644
--- a/browser-module/src/assemble/module.xml
+++ b/browser-module/src/assemble/module.xml
@@ -27,7 +27,7 @@
     </formats>
     <includeBaseDirectory>false</includeBaseDirectory>
 
-  <fileSets>
+    <fileSets>
 
         <fileSet>
             <directory>${basedir}/src/main/root</directory>
@@ -38,24 +38,17 @@
             <outputDirectory>/</outputDirectory>
         </fileSet>
   
-  </fileSets>    
-  <dependencySets>
+    </fileSets>    
+    <dependencySets>
      
         <dependencySet>
             <useProjectArtifact>false</useProjectArtifact>
             <outputDirectory>/lib</outputDirectory>
             <includes>
-                <include>org.apache.river:browser</include>
+                <include>*:browser</include>
             </includes>
         </dependencySet>
         
-        <dependencySet>
-            <useProjectArtifact>false</useProjectArtifact>
-            <outputDirectory>/lib-dl</outputDirectory>
-            <includes>
-                <include>org.apache.river:browser-dl</include>
-            </includes>
-        </dependencySet>
     </dependencySets>
 
 </assembly>

http://git-wip-us.apache.org/repos/asf/river-container/blob/7ff8b15a/browser-module/src/main/root/browser.config
----------------------------------------------------------------------
diff --git a/browser-module/src/main/root/browser.config b/browser-module/src/main/root/browser.config
index b5fea76..b612279 100644
--- a/browser-module/src/main/root/browser.config
+++ b/browser-module/src/main/root/browser.config
@@ -6,7 +6,7 @@ import net.jini.jeri.BasicJeriExporter;
 import net.jini.jeri.tcp.TcpServerEndpoint;
 import net.jini.security.BasicProxyPreparer;
 
-com.sun.jini.example.browser {
+org.apache.river.container.examples.browser {
 	
     initialLookupGroups = new String[] {$discoveryGroup};
     initialMemberGroups = new String[] {$discoveryGroup};

http://git-wip-us.apache.org/repos/asf/river-container/blob/7ff8b15a/browser-module/src/main/root/start.properties
----------------------------------------------------------------------
diff --git a/browser-module/src/main/root/start.properties b/browser-module/src/main/root/start.properties
index f2d75ce..d62b147 100644
--- a/browser-module/src/main/root/start.properties
+++ b/browser-module/src/main/root/start.properties
@@ -16,5 +16,5 @@
  # limitations under the License.
  #
 
-startClass=com.sun.jini.example.browser.Browser
+startClass=org.apache.river.container.examples.browser.Browser
 startParameters=browser.config $*

http://git-wip-us.apache.org/repos/asf/river-container/blob/7ff8b15a/browser/pom.xml
----------------------------------------------------------------------
diff --git a/browser/pom.xml b/browser/pom.xml
new file mode 100644
index 0000000..8870fbe
--- /dev/null
+++ b/browser/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.river.container</groupId>
+        <artifactId>river-container</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.apache.river.container</groupId>
+    <artifactId>browser</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <name>browser</name>
+    <url>http://maven.apache.org</url>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.jini</groupId>
+            <artifactId>jsk-platform</artifactId>
+            <version>2.2.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.jini</groupId>
+            <artifactId>jsk-lib</artifactId>
+            <version>2.2.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.jini</groupId>
+            <artifactId>jsk-resources</artifactId>
+            <version>2.2.1</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/river-container/blob/7ff8b15a/browser/src/main/java/org/apache/river/container/examples/browser/App.java
----------------------------------------------------------------------
diff --git a/browser/src/main/java/org/apache/river/container/examples/browser/App.java b/browser/src/main/java/org/apache/river/container/examples/browser/App.java
new file mode 100644
index 0000000..0f7400f
--- /dev/null
+++ b/browser/src/main/java/org/apache/river/container/examples/browser/App.java
@@ -0,0 +1,13 @@
+package org.apache.river.container.examples.browser;
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}

http://git-wip-us.apache.org/repos/asf/river-container/blob/7ff8b15a/browser/src/main/java/org/apache/river/container/examples/browser/Browser.java
----------------------------------------------------------------------
diff --git a/browser/src/main/java/org/apache/river/container/examples/browser/Browser.java b/browser/src/main/java/org/apache/river/container/examples/browser/Browser.java
new file mode 100644
index 0000000..16933fb
--- /dev/null
+++ b/browser/src/main/java/org/apache/river/container/examples/browser/Browser.java
@@ -0,0 +1,1765 @@
+/*
+ * 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 org.apache.river.container.examples.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 com.sun.jini.start.LifeCycle;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Modifier;
+import java.net.MalformedURLException;
+import java.rmi.server.ExportException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.swing.BorderFactory;
+import javax.swing.DefaultListModel;
+import javax.swing.Icon;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+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.JPopupMenu;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.ListCellRenderer;
+import javax.swing.SwingUtilities;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+import net.jini.admin.Administrable;
+import net.jini.admin.JoinAdmin;
+import net.jini.config.Configuration;
+import net.jini.config.ConfigurationException;
+import net.jini.config.ConfigurationProvider;
+import net.jini.config.EmptyConfiguration;
+import net.jini.config.NoSuchEntryException;
+import net.jini.core.constraint.MethodConstraints;
+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.ServiceID;
+import net.jini.core.lookup.ServiceItem;
+import net.jini.core.lookup.ServiceMatches;
+import net.jini.core.lookup.ServiceRegistrar;
+import net.jini.core.lookup.ServiceTemplate;
+import net.jini.discovery.Constants;
+import net.jini.discovery.ConstrainableLookupLocator;
+import net.jini.discovery.DiscoveryEvent;
+import net.jini.discovery.DiscoveryGroupManagement;
+import net.jini.discovery.DiscoveryListener;
+import net.jini.discovery.DiscoveryLocatorManagement;
+import net.jini.discovery.DiscoveryManagement;
+import net.jini.discovery.LookupDiscoveryManager;
+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.lookup.ui.factory.JFrameFactory;
+import net.jini.lookup.entry.UIDescriptor;
+import net.jini.security.BasicProxyPreparer;
+import net.jini.security.ProxyPreparer;
+import net.jini.security.Security;
+import net.jini.security.SecurityContext;
+import net.jini.security.TrustVerifier;
+import net.jini.security.proxytrust.ServerProxyTrust;
+import net.jini.space.JavaSpace05;
+import net.jini.space.JavaSpace;
+
+/*
+ * This is not great user interface design. It was a quick-and-dirty hack
+ * and an experiment in on-the-fly menu construction, and it's still
+ * here because we've never had time to do anything better.
+ */
+/**
+ * Example service browser. See the package documentation for details.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+public class Browser extends JFrame {
+
+    static final String BROWSER = "org.apache.river.container.examples.browser";
+    static final Logger logger = Logger.getLogger(BROWSER);
+    private transient SecurityContext ctx;
+    private transient ClassLoader ccl;
+    transient Configuration config;
+    private transient DiscoveryGroupManagement disco;
+    private transient ServiceRegistrar lookup = null;
+    private transient Object eventSource = null;
+    private transient long eventID = 0;
+    private transient long seqNo = Long.MAX_VALUE;
+    private transient ActionListener exiter;
+    private transient ServiceTemplate tmpl;
+    private transient Listener listen;
+    private transient LookupListener adder;
+    private transient Lease elease = null;
+    transient ProxyPreparer leasePreparer;
+    transient ProxyPreparer servicePreparer;
+    transient ProxyPreparer adminPreparer;
+    private transient MethodConstraints locatorConstraints;
+    transient LeaseRenewalManager leaseMgr;
+    private transient LeaseListener lnotify;
+    private transient List ignoreInterfaces;
+    private transient JTextArea text;
+    private transient JMenu registrars;
+    private transient JCheckBoxMenuItem esuper;
+    private transient JCheckBoxMenuItem ssuper;
+    private transient JCheckBoxMenuItem sclass;
+    private transient boolean isAdmin;
+    private volatile transient boolean autoConfirm;
+    private transient JList list;
+    private transient DefaultListModel listModel;
+    private transient DefaultListModel dummyModel = new DefaultListModel();
+    private transient JScrollPane listScrollPane;
+
+    /**
+     * Creates an instance with the given action listener for the Exit menu item
+     * and the given configuration. The action listener defaults to an instance
+     * of {@link Exit Exit}. The action listener can be overridden by a
+     * configuration entry. The configuration defaults to an empty
+     * configuration.
+     *
+     * @param exiter the action listener, or <code>null</code>
+     * @param config the configuration, or <code>null</code>
+     */
+    public Browser(ActionListener exiter, Configuration config)
+            throws ConfigurationException, IOException {
+        if (exiter == null) {
+            exiter = new Exit();
+        }
+        if (config == null) {
+            config = EmptyConfiguration.INSTANCE;
+        }
+        init(exiter, config);
+    }
+
+    private void init(ActionListener exiter, Configuration config)
+            throws ConfigurationException, IOException {
+        exiter = wrap((ActionListener) Config.getNonNullEntry(config, BROWSER, "exitActionListener",
+                ActionListener.class, exiter));
+        this.exiter = exiter;
+        this.config = config;
+        ctx = Security.getContext();
+        ccl = Thread.currentThread().getContextClassLoader();
+        leaseMgr = (LeaseRenewalManager) Config.getNonNullEntry(config, BROWSER, "leaseManager",
+                LeaseRenewalManager.class,
+                new LeaseRenewalManager(config));
+        isAdmin = ((Boolean) config.getEntry(
+                BROWSER, "folderView",
+                boolean.class, Boolean.TRUE)).booleanValue();
+        leasePreparer = (ProxyPreparer) Config.getNonNullEntry(config, BROWSER, "leasePreparer",
+                ProxyPreparer.class,
+                new BasicProxyPreparer());
+        servicePreparer = (ProxyPreparer) Config.getNonNullEntry(config, BROWSER, "servicePreparer",
+                ProxyPreparer.class,
+                new BasicProxyPreparer());
+        adminPreparer = (ProxyPreparer) Config.getNonNullEntry(config, BROWSER, "adminPreparer",
+                ProxyPreparer.class,
+                new BasicProxyPreparer());
+        locatorConstraints = (MethodConstraints) config.getEntry(BROWSER, "locatorConstraints",
+                MethodConstraints.class, null);
+        ignoreInterfaces = Arrays.asList((String[]) Config.getNonNullEntry(config, BROWSER, "uninterestingInterfaces",
+                String[].class,
+                new String[]{
+            "java.io.Serializable",
+            "java.rmi.Remote",
+            "net.jini.admin.Administrable",
+            "net.jini.core.constraint.RemoteMethodControl",
+            "net.jini.id.ReferentUuid",
+            "net.jini.security.proxytrust.TrustEquivalence"}));
+        autoConfirm = ((Boolean) config.getEntry(
+                BROWSER, "autoConfirm", boolean.class,
+                Boolean.FALSE)).booleanValue();
+        listen = new Listener();
+        try {
+            DiscoveryManagement disco = (DiscoveryManagement) Config.getNonNullEntry(config, BROWSER, "discoveryManager",
+                    DiscoveryManagement.class);
+            if (!(disco instanceof DiscoveryGroupManagement)) {
+                throw new ConfigurationException(
+                        "discoveryManager does not "
+                        + " support DiscoveryGroupManagement");
+            } else if (!(disco instanceof DiscoveryLocatorManagement)) {
+                throw new ConfigurationException(
+                        "discoveryManager does not "
+                        + " support DiscoveryLocatorManagement");
+            }
+            this.disco = (DiscoveryGroupManagement) disco;
+            String[] groups = this.disco.getGroups();
+            if (groups == null || groups.length > 0) {
+                throw new ConfigurationException(
+                        "discoveryManager cannot have initial groups");
+            }
+            if (((DiscoveryLocatorManagement) disco).getLocators().length > 0) {
+                throw new ConfigurationException(
+                        "discoveryManager cannot have initial locators");
+            }
+        } catch (NoSuchEntryException e) {
+            disco = new LookupDiscoveryManager(new String[0],
+                    new LookupLocator[0], null,
+                    config);
+        }
+        disco.setGroups((String[]) config.getEntry(BROWSER,
+                "initialLookupGroups",
+                String[].class,
+                null));
+        ((DiscoveryLocatorManagement) disco).setLocators((LookupLocator[]) Config.getNonNullEntry(config, BROWSER, "initialLookupLocators",
+                LookupLocator[].class,
+                new LookupLocator[0]));
+        tmpl = new ServiceTemplate(null, new Class[0], new Entry[0]);
+        setTitle("Service Browser");
+        JMenuBar bar = new JMenuBar();
+        JMenu file = new JMenu("File");
+        JMenuItem allfind = new JMenuItem("Find All");
+        allfind.addActionListener(wrap(new AllFind()));
+        file.add(allfind);
+        JMenuItem pubfind = new JMenuItem("Find Public");
+        pubfind.addActionListener(wrap(new PubFind()));
+        file.add(pubfind);
+        JMenuItem multifind = new JMenuItem("Find By Group...");
+        multifind.addActionListener(wrap(new MultiFind()));
+        file.add(multifind);
+        JMenuItem unifind = new JMenuItem("Find By Address...");
+        unifind.addActionListener(wrap(new UniFind()));
+        file.add(unifind);
+        if (!isAdmin) {
+            JMenuItem show = new JMenuItem("Show Matches");
+            show.addActionListener(wrap(new Show()));
+            file.add(show);
+        }
+        JMenuItem reset = new JMenuItem("Reset");
+        reset.addActionListener(wrap(new Reset()));
+        file.add(reset);
+        JMenuItem exit = new JMenuItem("Exit");
+        exit.addActionListener(exiter);
+        file.add(exit);
+        bar.add(file);
+        addWindowListener(new Exiter());
+        registrars = new JMenu("Registrar");
+        addNone(registrars);
+        bar.add(registrars);
+        JMenu options = new JMenu("Options");
+        esuper = new JCheckBoxMenuItem("Attribute supertypes", false);
+        options.add(esuper);
+        ssuper = new JCheckBoxMenuItem("Service supertypes", false);
+        options.add(ssuper);
+        sclass = new JCheckBoxMenuItem("Service classes", false);
+        options.add(sclass);
+        bar.add(options);
+        JMenu services = new JMenu("Services");
+        services.addMenuListener(wrap(new Services(services)));
+        bar.add(services);
+        JMenu attrs = new JMenu("Attributes");
+        attrs.addMenuListener(wrap(new Entries(attrs)));
+        bar.add(attrs);
+        setJMenuBar(bar);
+
+        getContentPane().setLayout(new BorderLayout());
+        int textRows = 8;
+        if (isAdmin) {
+            textRows = 4;
+            JPanel bpanel = new JPanel();
+            bpanel.setLayout(new BorderLayout());
+
+            TitledBorder border = BorderFactory.createTitledBorder("Matching Services");
+            border.setTitlePosition(TitledBorder.TOP);
+            border.setTitleJustification(TitledBorder.LEFT);
+            bpanel.setBorder(border);
+
+            listModel = new DefaultListModel();
+            list = new JList(listModel);
+            list.setFixedCellHeight(20);
+            list.setCellRenderer((ListCellRenderer) wrap(new ServiceItemRenderer(), ListCellRenderer.class));
+            list.addMouseListener(
+                    wrap(new MouseReceiver(new ServiceListPopup())));
+            listScrollPane = new JScrollPane(list);
+            bpanel.add(listScrollPane, "Center");
+            getContentPane().add(bpanel, "South");
+        }
+        text = new JTextArea(genText(false), textRows, 40);
+        text.setEditable(false);
+        JScrollPane scroll = new JScrollPane(text);
+        getContentPane().add(scroll, "Center");
+
+        validate();
+        SwingUtilities.invokeLater(wrap(new Runnable() {
+            public void run() {
+                pack();
+                show();
+            }
+        }));
+        adder = new LookupListener();
+        lnotify = new LeaseNotify();
+        ((DiscoveryManagement) disco).addDiscoveryListener(adder);
+    }
+
+    /**
+     * Creates an instance with the given command line arguments and life cycle
+     * callback. See the package documentation for details of the command line
+     * arguments. The default action listener for the Exit menu item calls the
+     * {@link #dispose dispose} method of this instance, cancels any lookup
+     * service event registration lease, unexports any remote event listener,
+     * and calls the {@link LifeCycle#unregister unregister} method of the life
+     * cycle callback. The action listener can be overridden by a configuration
+     * entry.
+     *
+     * @param args command line arguments
+     * @param lc life cycle callback, or <code>null</code>.
+     */
+    public Browser(String[] args, final LifeCycle lc)
+            throws ConfigurationException, LoginException, IOException {
+        final ActionListener exiter = new ActionListener() {
+            public void actionPerformed(ActionEvent ev) {
+                Browser.this.dispose();
+                cancelLease();
+                listen.unexport();
+                if (lc != null) {
+                    lc.unregister(Browser.this);
+                }
+                System.exit(0);
+            }
+        };
+        final Configuration config =
+                ConfigurationProvider.getInstance(
+                args, Browser.class.getClassLoader());
+        LoginContext login =
+                (LoginContext) config.getEntry(BROWSER, "loginContext",
+                LoginContext.class, null);
+        if (login == null) {
+            init(exiter, config);
+        } else {
+            login.login();
+            try {
+                Subject.doAsPrivileged(
+                        login.getSubject(),
+                        new PrivilegedExceptionAction() {
+                    public Object run()
+                            throws ConfigurationException, IOException {
+                        init(exiter, config);
+                        return null;
+                    }
+                },
+                        null);
+            } catch (PrivilegedActionException pae) {
+                Exception e = pae.getException();
+                if (e instanceof ConfigurationException) {
+                    throw (ConfigurationException) e;
+                }
+                throw (IOException) e;
+            }
+        }
+    }
+
+    private static String typeName(Class type) {
+        String name = type.getName();
+        int i = name.lastIndexOf('.');
+        if (i >= 0) {
+            name = name.substring(i + 1);
+        }
+        return name;
+    }
+
+    private void setText(boolean match) {
+        text.setText(genText(match));
+    }
+
+    private String genText(boolean match) {
+        StringBuffer buf = new StringBuffer();
+        if (tmpl.serviceTypes.length > 0) {
+            for (int i = 0; i < tmpl.serviceTypes.length; i++) {
+                buf.append(tmpl.serviceTypes[i].getName());
+                buf.append("\n");
+            }
+        }
+        if (tmpl.attributeSetTemplates.length > 0) {
+            genEntries(buf, tmpl.attributeSetTemplates, false);
+        }
+        genMatches(buf, match);
+        return buf.toString();
+    }
+
+    private void genEntries(StringBuffer buf,
+            Entry[] entries,
+            boolean showNulls) {
+        for (int i = 0; i < entries.length; i++) {
+            Entry ent = entries[i];
+            if (ent == null) {
+                buf.append("null\n");
+                continue;
+            }
+            buf.append(typeName(ent.getClass()));
+            buf.append(": ");
+            try {
+                Field[] fields = ent.getClass().getFields();
+                for (int j = 0; j < fields.length; j++) {
+                    if (!valid(fields[j])) {
+                        continue;
+                    }
+                    Object val = fields[j].get(ent);
+                    if (val != null || showNulls) {
+                        buf.append(fields[j].getName());
+                        buf.append("=");
+                        buf.append(val);
+                        buf.append(" ");
+                    }
+                }
+            } catch (Exception e) {
+            }
+            buf.append("\n");
+        }
+    }
+
+    private static boolean valid(Field f) {
+        return (f.getModifiers() & (Modifier.STATIC | Modifier.FINAL)) == 0;
+    }
+
+    private void genMatches(StringBuffer buf, boolean match) {
+        if (isAdmin) {
+            list.setModel(dummyModel);	// to keep away from Swing's bug
+
+            listModel.removeAllElements();
+            list.clearSelection();
+            list.ensureIndexIsVisible(0);
+            list.repaint();
+            list.revalidate();
+            listScrollPane.validate();
+        }
+        if (lookup == null) {
+            String[] groups = disco.getGroups();
+            if (groups == null) {
+                buf.append("Groups: <all>\n");
+            } else if (groups.length > 0) {
+                buf.append("Groups:");
+                for (int i = 0; i < groups.length; i++) {
+                    String group = groups[i];
+                    if (group.length() == 0) {
+                        group = "public";
+                    }
+                    buf.append(" ");
+                    buf.append(group);
+                }
+                buf.append("\n");
+            }
+            LookupLocator[] locators =
+                    ((DiscoveryLocatorManagement) disco).getLocators();
+            if (locators.length > 0) {
+                buf.append("Addresses:");
+                for (int i = 0; i < locators.length; i++) {
+                    buf.append(" ");
+                    buf.append(locators[i].getHost());
+                    if (locators[i].getPort() != Constants.discoveryPort) {
+                        buf.append(":");
+                        buf.append(locators[i].getPort());
+                    }
+                }
+                buf.append("\n");
+            }
+            if (!(registrars.getMenuComponent(0) instanceof JRadioButtonMenuItem)) {
+                buf.append("No registrars to select");
+                return;
+            }
+            int n = registrars.getMenuComponentCount();
+            if (n == 1) {
+                buf.append("1 registrar, not selected");
+            } else {
+                buf.append(n);
+                buf.append(" registrars, none selected");
+            }
+            return;
+        }
+        ServiceMatches matches;
+        try {
+            matches = lookup.lookup(tmpl, (match || isAdmin) ? 1000 : 0);
+        } catch (Throwable t) {
+            logger.log(Level.INFO, "lookup failed", t);
+            return;
+        }
+
+        if (matches.items != null) {
+            for (int i = 0; i < matches.items.length; i++) {
+                if (matches.items[i].service != null) {
+                    try {
+                        matches.items[i].service =
+                                servicePreparer.prepareProxy(
+                                matches.items[i].service);
+                    } catch (Throwable t) {
+                        logger.log(Level.INFO, "proxy preparation failed", t);
+                        matches.items[i].service = null;
+                    }
+                }
+            }
+        }
+
+        if (isAdmin) {
+            for (int i = 0; i < matches.items.length; i++) {
+                listModel.addElement(new ServiceListItem(matches.items[i]));
+            }
+            list.setModel(listModel);
+            list.clearSelection();
+            list.ensureIndexIsVisible(0);
+            list.repaint();
+            list.revalidate();
+            listScrollPane.validate();
+        }
+
+        if (!match
+                && tmpl.serviceTypes.length == 0
+                && tmpl.attributeSetTemplates.length == 0) {
+            buf.append("Total services registered: ");
+            buf.append(matches.totalMatches);
+            return;
+        }
+        buf.append("\nMatching services: ");
+        buf.append(matches.totalMatches);
+
+        if (!isAdmin) {
+            if (!match) {
+                return;
+            }
+            buf.append("\n\n");
+            for (int i = 0; i < matches.items.length; i++) {
+                ServiceItem item = matches.items[i];
+                buf.append("Service ID: ");
+                buf.append(item.serviceID);
+                buf.append("\n");
+                buf.append("Service instance: ");
+                buf.append(item.service);
+                buf.append("\n");
+                genEntries(buf, item.attributeSets, true);
+                buf.append("\n");
+            }
+        }
+    }
+
+    private static void addNone(JMenu menu) {
+        JMenuItem item = new JMenuItem("(none)");
+        item.setEnabled(false);
+        menu.add(item);
+    }
+
+    private void addOne(ServiceRegistrar registrar) {
+        LookupLocator loc;
+        try {
+            loc = registrar.getLocator();
+        } catch (Throwable t) {
+            logger.log(Level.INFO, "obtaining locator failed", t);
+            return;
+        }
+        String host = loc.getHost();
+        if (loc.getPort() != Constants.discoveryPort) {
+            host += ":" + loc.getPort();
+        }
+        JRadioButtonMenuItem reg =
+                new RegistrarMenuItem(host, registrar.getServiceID());
+        reg.addActionListener(wrap(new Lookup(registrar)));
+        if (!(registrars.getMenuComponent(0) instanceof JRadioButtonMenuItem)) {
+            registrars.removeAll();
+        }
+        registrars.add(reg);
+    }
+
+    private static class RegistrarMenuItem extends JRadioButtonMenuItem {
+
+        ServiceID id;
+
+        RegistrarMenuItem(String host, ServiceID id) {
+            super(host);
+            this.id = id;
+        }
+    }
+
+    static Class[] getInterfaces(Class c) {
+        Set set = new HashSet();
+        for (; c != null; c = c.getSuperclass()) {
+            Class[] ifs = c.getInterfaces();
+            for (int i = ifs.length; --i >= 0;) {
+                set.add(ifs[i]);
+            }
+        }
+        return (Class[]) set.toArray(new Class[set.size()]);
+    }
+
+    private class Services implements MenuListener {
+
+        private JMenu menu;
+
+        public Services(JMenu menu) {
+            this.menu = menu;
+        }
+
+        public void menuSelected(MenuEvent ev) {
+            if (lookup == null) {
+                addNone(menu);
+                return;
+            }
+            Vector all = new Vector();
+            Class[] types = tmpl.serviceTypes;
+            for (int i = 0; i < types.length; i++) {
+                all.addElement(types[i]);
+                JCheckBoxMenuItem item =
+                        new JCheckBoxMenuItem(types[i].getName(), true);
+                item.addActionListener(wrap(new Service(types[i], i)));
+                menu.add(item);
+            }
+            try {
+                types = lookup.getServiceTypes(tmpl, "");
+            } catch (Throwable t) {
+                failure(t);
+                return;
+            }
+            if (types == null) {
+                if (all.isEmpty()) {
+                    addNone(menu);
+                }
+                return;
+            }
+            for (int i = 0; i < types.length; i++) {
+                Class[] stypes;
+                if (types[i] == null) {
+                    all.addElement(new JMenuItem("null"));
+                    continue;
+                }
+                if (types[i].isInterface() || sclass.getState()) {
+                    stypes = new Class[]{types[i]};
+                } else {
+                    stypes = getInterfaces(types[i]);
+                }
+                for (int j = 0; j < stypes.length; j++) {
+                    addType(stypes[j], all);
+                }
+            }
+        }
+
+        private void addType(Class type, Vector all) {
+            if (all.contains(type)) {
+                return;
+            }
+            all.addElement(type);
+            JCheckBoxMenuItem item =
+                    new JCheckBoxMenuItem(type.getName(), false);
+            item.addActionListener(wrap(new Service(type, -1)));
+            menu.add(item);
+            if (!ssuper.getState()) {
+                return;
+            }
+            if (sclass.getState() && type.getSuperclass() != null) {
+                addType(type.getSuperclass(), all);
+            }
+            Class[] stypes = type.getInterfaces();
+            for (int i = 0; i < stypes.length; i++) {
+                addType(stypes[i], all);
+            }
+        }
+
+        public void menuDeselected(MenuEvent ev) {
+            menu.removeAll();
+        }
+
+        public void menuCanceled(MenuEvent ev) {
+            menu.removeAll();
+        }
+    }
+
+    /**
+     * Indicates whether auto confirm is enabled to prevent from the user having
+     * to click the 'Yes' button in the a popup window to confirm a modification
+     * to the service browser pane is allowed to take place as result of a
+     * service being removed, or its lookup attributes being changed.
+     *
+     * @return <code>true</code> in case no popup is required to have the user
+     * confirm the modifications, <code>false</code> otherwise
+     */
+    boolean isAutoConfirm() {
+        return autoConfirm;
+    }
+
+    ActionListener wrap(ActionListener l) {
+        return (ActionListener) wrap((Object) l, ActionListener.class);
+    }
+
+    MenuListener wrap(MenuListener l) {
+        return (MenuListener) wrap((Object) l, MenuListener.class);
+    }
+
+    MouseListener wrap(MouseListener l) {
+        return (MouseListener) wrap((Object) l, MouseListener.class);
+    }
+
+    WindowListener wrap(WindowListener a) {
+        return (WindowListener) wrap((Object) a, WindowListener.class);
+    }
+
+    Runnable wrap(Runnable r) {
+        return (Runnable) wrap((Object) r, Runnable.class);
+    }
+
+    private Object wrap(Object obj, Class iface) {
+        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
+                new Class[]{iface}, new Handler(obj));
+    }
+
+    private class Handler implements InvocationHandler {
+
+        private final Object obj;
+
+        Handler(Object obj) {
+            this.obj = obj;
+        }
+
+        public Object invoke(Object proxy,
+                final Method method,
+                final Object[] args)
+                throws Throwable {
+            if (method.getDeclaringClass() == Object.class) {
+                if ("equals".equals(method.getName())) {
+                    return Boolean.valueOf(proxy == args[0]);
+                } else if ("hashCode".equals(method.getName())) {
+                    return new Integer(System.identityHashCode(proxy));
+                }
+            }
+            try {
+                return AccessController.doPrivileged(
+                        ctx.wrap(new PrivilegedExceptionAction() {
+                    public Object run() throws Exception {
+                        Thread t = Thread.currentThread();
+                        ClassLoader occl = t.getContextClassLoader();
+                        try {
+                            t.setContextClassLoader(ccl);
+                            try {
+                                return method.invoke(obj, args);
+                            } catch (InvocationTargetException e) {
+                                Throwable tt = e.getCause();
+                                if (tt instanceof Error) {
+                                    throw (Error) tt;
+                                }
+                                throw (Exception) tt;
+                            }
+                        } finally {
+                            t.setContextClassLoader(occl);
+                        }
+                    }
+                }), ctx.getAccessControlContext());
+            } catch (PrivilegedActionException e) {
+                throw e.getCause();
+            }
+        }
+    }
+
+    private class Show implements ActionListener {
+
+        public void actionPerformed(ActionEvent ev) {
+            setText(true);
+        }
+    }
+
+    private void resetTmpl() {
+        tmpl.serviceTypes = new Class[0];
+        tmpl.attributeSetTemplates = new Entry[0];
+        update();
+    }
+
+    private void reset() {
+        ssuper.setState(false);
+        esuper.setState(false);
+        sclass.setState(false);
+        resetTmpl();
+    }
+
+    private class Reset implements ActionListener {
+
+        public void actionPerformed(ActionEvent ev) {
+            reset();
+        }
+    }
+
+    private class Service implements ActionListener {
+
+        private Class type;
+        private int index;
+
+        public Service(Class type, int index) {
+            this.type = type;
+            this.index = index;
+        }
+
+        public void actionPerformed(ActionEvent ev) {
+            int z = tmpl.serviceTypes.length;
+            Class[] newTypes;
+            if (index < 0) {
+                newTypes = new Class[z + 1];
+                System.arraycopy(tmpl.serviceTypes, 0, newTypes, 0, z);
+                newTypes[z] = type;
+            } else {
+                newTypes = new Class[z - 1];
+                System.arraycopy(tmpl.serviceTypes, 0,
+                        newTypes, 0, index);
+                System.arraycopy(tmpl.serviceTypes, index + 1,
+                        newTypes, index, z - index - 1);
+            }
+            tmpl.serviceTypes = newTypes;
+            update();
+        }
+    }
+
+    private class Entries implements MenuListener {
+
+        private JMenu menu;
+
+        public Entries(JMenu menu) {
+            this.menu = menu;
+        }
+
+        public void menuSelected(MenuEvent ev) {
+            if (lookup == null) {
+                addNone(menu);
+                return;
+            }
+            Entry[] attrs = tmpl.attributeSetTemplates;
+            for (int i = 0; i < attrs.length; i++) {
+                Class type = attrs[i].getClass();
+                JMenu item = new JMenu(typeName(type));
+                item.addMenuListener(new Fields(item, i));
+                menu.add(item);
+            }
+            Class[] types;
+            try {
+                types = lookup.getEntryClasses(tmpl);
+            } catch (Throwable t) {
+                failure(t);
+                return;
+            }
+            if (types == null) {
+                if (attrs.length == 0) {
+                    addNone(menu);
+                }
+                return;
+            }
+            Vector all = new Vector();
+            for (int i = 0; i < types.length; i++) {
+                if (types[i] == null) {
+                    menu.add(new JMenuItem("null"));
+                } else {
+                    addType(types[i], all);
+                }
+            }
+        }
+
+        private void addType(Class type, Vector all) {
+            if (all.contains(type)) {
+                return;
+            }
+            all.addElement(type);
+            JCheckBoxMenuItem item =
+                    new JCheckBoxMenuItem(typeName(type), false);
+            item.addActionListener(wrap(new AttrSet(type)));
+            menu.add(item);
+            if (esuper.getState()
+                    && Entry.class.isAssignableFrom(type.getSuperclass())) {
+                addType(type.getSuperclass(), all);
+            }
+        }
+
+        public void menuDeselected(MenuEvent ev) {
+            menu.removeAll();
+        }
+
+        public void menuCanceled(MenuEvent ev) {
+            menu.removeAll();
+        }
+    }
+
+    private class AttrSet implements ActionListener {
+
+        private Class type;
+
+        public AttrSet(Class type) {
+            this.type = type;
+        }
+
+        public void actionPerformed(ActionEvent ev) {
+            Entry ent;
+            try {
+                ent = (Entry) type.newInstance();
+            } catch (Throwable t) {
+                logger.log(Level.INFO, "creating entry failed", t);
+                return;
+            }
+            int z = tmpl.attributeSetTemplates.length;
+            Entry[] newSets = new Entry[z + 1];
+            System.arraycopy(tmpl.attributeSetTemplates, 0, newSets, 0, z);
+            newSets[z] = ent;
+            tmpl.attributeSetTemplates = newSets;
+            update();
+        }
+    }
+
+    private class Fields implements MenuListener {
+
+        private JMenu menu;
+        private int index;
+
+        public Fields(JMenu menu, int index) {
+            this.menu = menu;
+            this.index = index;
+        }
+
+        public void menuSelected(MenuEvent ev) {
+            JRadioButtonMenuItem match = new JRadioButtonMenuItem("(match)");
+            match.setSelected(true);
+            match.addActionListener(wrap(new Unmatch(index)));
+            menu.add(match);
+            Entry ent = tmpl.attributeSetTemplates[index];
+            Field[] fields = ent.getClass().getFields();
+            for (int i = 0; i < fields.length; i++) {
+                Field field = fields[i];
+                if (!valid(field)) {
+                    continue;
+                }
+                try {
+                    if (field.get(ent) != null) {
+                        JCheckBoxMenuItem item =
+                                new JCheckBoxMenuItem(field.getName(), true);
+                        item.addActionListener(
+                                wrap(new Value(index, field, null)));
+                        menu.add(item);
+                    } else {
+                        JMenu item = new JMenu(field.getName());
+                        item.addMenuListener(
+                                wrap(new Values(item, index, field)));
+                        menu.add(item);
+                    }
+                } catch (Throwable t) {
+                    logger.log(Level.INFO, "getting fields failed", t);
+                }
+            }
+        }
+
+        public void menuDeselected(MenuEvent ev) {
+            menu.removeAll();
+        }
+
+        public void menuCanceled(MenuEvent ev) {
+            menu.removeAll();
+        }
+    }
+
+    private class Unmatch implements ActionListener {
+
+        private int index;
+
+        public Unmatch(int index) {
+            this.index = index;
+        }
+
+        public void actionPerformed(ActionEvent ev) {
+            int z = tmpl.attributeSetTemplates.length;
+            Entry[] newSets = new Entry[z - 1];
+            System.arraycopy(tmpl.attributeSetTemplates, 0,
+                    newSets, 0, index);
+            System.arraycopy(tmpl.attributeSetTemplates, index + 1,
+                    newSets, index, z - index - 1);
+            tmpl.attributeSetTemplates = newSets;
+            update();
+        }
+    }
+
+    private class Values implements MenuListener {
+
+        private JMenu menu;
+        private int index;
+        private Field field;
+
+        public Values(JMenu menu, int index, Field field) {
+            this.menu = menu;
+            this.index = index;
+            this.field = field;
+        }
+
+        public void menuSelected(MenuEvent ev) {
+            Object[] values;
+            try {
+                values = lookup.getFieldValues(tmpl, index, field.getName());
+            } catch (Throwable t) {
+                failure(t);
+                return;
+            }
+            if (values == null) {
+                addNone(menu);
+                return;
+            }
+            for (int i = 0; i < values.length; i++) {
+                JMenuItem item = new JMenuItem(values[i].toString());
+                item.addActionListener(
+                        wrap(new Value(index, field, values[i])));
+                menu.add(item);
+            }
+        }
+
+        public void menuDeselected(MenuEvent ev) {
+            menu.removeAll();
+        }
+
+        public void menuCanceled(MenuEvent ev) {
+            menu.removeAll();
+        }
+    }
+
+    private class Value implements ActionListener {
+
+        private int index;
+        private Field field;
+        private Object value;
+
+        public Value(int index, Field field, Object value) {
+            this.index = index;
+            this.field = field;
+            this.value = value;
+        }
+
+        public void actionPerformed(ActionEvent ev) {
+            try {
+                field.set(tmpl.attributeSetTemplates[index], value);
+            } catch (Throwable t) {
+                logger.log(Level.INFO, "setting attribute value failed", t);
+            }
+            update();
+        }
+    }
+
+    private class Listener implements RemoteEventListener, ServerProxyTrust {
+
+        private final Exporter exporter;
+        final RemoteEventListener proxy;
+
+        public Listener() throws ConfigurationException, ExportException {
+            exporter = (Exporter) Config.getNonNullEntry(config, 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(wrap(new Runnable() {
+                public void run() {
+                    if (eventID == ev.getID()
+                            && seqNo < ev.getSequenceNumber()
+                            && eventSource != null
+                            && eventSource.equals(ev.getSource())) {
+                        seqNo = ev.getSequenceNumber();
+                        setText(false);
+                    }
+                }
+            }));
+        }
+
+        public TrustVerifier getProxyVerifier() {
+            return new BasicProxyTrustVerifier(proxy);
+        }
+
+        void unexport() {
+            exporter.unexport(true);
+        }
+    }
+
+    private class LookupListener implements DiscoveryListener {
+
+        public void discovered(DiscoveryEvent e) {
+            final ServiceRegistrar[] newregs = e.getRegistrars();
+            SwingUtilities.invokeLater(wrap(new Runnable() {
+                public void run() {
+                    for (int i = 0; i < newregs.length; i++) {
+                        addOne(newregs[i]);
+                    }
+                    if (lookup == null) {
+                        setText(false);
+                    }
+                }
+            }));
+        }
+
+        public void discarded(DiscoveryEvent e) {
+            final ServiceRegistrar[] regs = e.getRegistrars();
+            SwingUtilities.invokeLater(wrap(new Runnable() {
+                public void run() {
+                    for (int i = 0; i < regs.length; i++) {
+                        ServiceID id = regs[i].getServiceID();
+                        if (lookup != null
+                                && id.equals(lookup.getServiceID())) {
+                            lookup = null;
+                            seqNo = Long.MAX_VALUE;
+                        }
+                        for (int j = 0;
+                                j < registrars.getMenuComponentCount();
+                                j++) {
+                            JMenuItem item =
+                                    (JMenuItem) registrars.getMenuComponent(j);
+                            if (item instanceof RegistrarMenuItem
+                                    && id.equals(((RegistrarMenuItem) item).id)) {
+                                item.setSelected(false);
+                                registrars.remove(item);
+                                if (registrars.getMenuComponentCount() == 0) {
+                                    addNone(registrars);
+                                }
+                                break;
+                            }
+                        }
+                    }
+                    if (lookup == null) {
+                        resetTmpl();
+                    }
+                }
+            }));
+        }
+    }
+
+    private void setGroups(String[] groups) {
+        ((DiscoveryLocatorManagement) disco).setLocators(new LookupLocator[0]);
+        try {
+            disco.setGroups(groups);
+        } catch (Throwable t) {
+            logger.log(Level.INFO, "setting groups failed", t);
+        }
+        resetTmpl();
+    }
+
+    private class AllFind implements ActionListener {
+
+        public void actionPerformed(ActionEvent ev) {
+            setGroups(null);
+        }
+    }
+
+    private class PubFind implements ActionListener {
+
+        public void actionPerformed(ActionEvent ev) {
+            setGroups(new String[]{""});
+        }
+    }
+
+    private class MultiFind implements ActionListener {
+
+        public void actionPerformed(ActionEvent ev) {
+            String names = JOptionPane.showInputDialog(Browser.this,
+                    "Enter group names");
+            if (names == null) {
+                return;
+            }
+            setGroups(parseList(names, true));
+        }
+    }
+
+    private class UniFind implements ActionListener {
+
+        public void actionPerformed(ActionEvent ev) {
+            String list =
+                    JOptionPane.showInputDialog(Browser.this,
+                    "Enter host[:port] addresses");
+            if (list == null) {
+                return;
+            }
+            String[] addrs = parseList(list, false);
+            LookupLocator[] locs = new LookupLocator[addrs.length];
+            for (int i = 0; i < addrs.length; i++) {
+                try {
+                    locs[i] = new ConstrainableLookupLocator(
+                            "jini://" + addrs[i], locatorConstraints);
+                } catch (MalformedURLException e) {
+                    JOptionPane.showMessageDialog(Browser.this,
+                            "\"" + addrs[i] + "\": "
+                            + e.getMessage(),
+                            "Bad Address",
+                            JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+            }
+            try {
+                disco.setGroups(new String[0]);
+            } catch (Throwable t) {
+                logger.log(Levels.HANDLED, "setting groups failed", t);
+            }
+            ((DiscoveryLocatorManagement) disco).setLocators(locs);
+            resetTmpl();
+        }
+    }
+
+    private class Lookup implements ActionListener {
+
+        private ServiceRegistrar registrar;
+
+        public Lookup(ServiceRegistrar registrar) {
+            this.registrar = registrar;
+        }
+
+        public void actionPerformed(ActionEvent ev) {
+            if (lookup == registrar) {
+                lookup = null;
+            } else {
+                lookup = registrar;
+            }
+            seqNo = Long.MAX_VALUE;
+            for (int i = 0; i < registrars.getMenuComponentCount(); i++) {
+                JMenuItem item = (JMenuItem) registrars.getMenuComponent(i);
+                if (item != ev.getSource()) {
+                    item.setSelected(false);
+                }
+            }
+            resetTmpl();
+        }
+    }
+
+    static class LeaseNotify implements LeaseListener {
+
+        public void notify(LeaseRenewalEvent ev) {
+            if (ev.getException() != null) {
+                logger.log(Level.INFO, "lease renewal failed",
+                        ev.getException());
+            } else {
+                logger.log(Level.INFO, "lease renewal failed");
+            }
+        }
+    }
+
+    private static String[] parseList(String names, boolean groups) {
+        StringTokenizer st = new StringTokenizer(names, " \t\n\r\f,");
+        String[] elts = new String[st.countTokens()];
+        for (int i = 0; st.hasMoreTokens(); i++) {
+            elts[i] = st.nextToken();
+            if (groups && elts[i].equalsIgnoreCase("public")) {
+                elts[i] = "";
+            }
+        }
+        return elts;
+    }
+
+    private void cancelLease() {
+        if (elease != null) {
+            try {
+                leaseMgr.cancel(elease);
+            } catch (Throwable t) {
+                logger.log(Levels.HANDLED, "lease cancellation failed", t);
+            }
+            elease = null;
+            eventSource = null;
+        }
+    }
+
+    private void update() {
+        setText(false);
+        cancelLease();
+        if (lookup == null) {
+            return;
+        }
+        try {
+            EventRegistration reg =
+                    lookup.notify(tmpl,
+                    ServiceRegistrar.TRANSITION_MATCH_NOMATCH
+                    | ServiceRegistrar.TRANSITION_NOMATCH_MATCH
+                    | ServiceRegistrar.TRANSITION_MATCH_MATCH,
+                    listen.proxy, null, Lease.ANY);
+            elease = (Lease) leasePreparer.prepareProxy(reg.getLease());
+            leaseMgr.renewUntil(elease, Lease.ANY, lnotify);
+            eventSource = reg.getSource();
+            eventID = reg.getID();
+            seqNo = reg.getSequenceNumber();
+        } catch (Throwable t) {
+            failure(t);
+        }
+    }
+
+    private void failure(Throwable t) {
+        logger.log(Level.INFO, "call to lookup service failed", t);
+        ((DiscoveryManagement) disco).discard(lookup);
+    }
+
+    class ServiceItemRenderer implements ListCellRenderer {
+
+        private JLabel label;
+
+        public ServiceItemRenderer() {
+            label = new JLabel();
+            label.setOpaque(true);
+        }
+
+        public Component getListCellRendererComponent(JList list,
+                Object value,
+                int index,
+                boolean isSelected,
+                boolean cellHasFocus) {
+            ServiceListItem item = null;
+            if (value instanceof ServiceListItem) {
+                item = (ServiceListItem) value;
+            }
+
+            label.setFont(list.getFont());
+
+            if (isSelected) {
+                label.setBackground(list.getSelectionBackground());
+                label.setForeground(list.getSelectionForeground());
+            } else {
+                label.setBackground(list.getBackground());
+                label.setForeground(list.getForeground());
+            }
+            if (item != null) {
+                // accessible check done in this method
+                label.setIcon(item.getIcon());
+                label.setText(item.getTitle());
+            } else {
+                label.setText(value.toString());
+            }
+
+            return label;
+        }
+    }
+    private static Icon[] icons = new Icon[3];
+
+    static {
+        // Administrable Service, Controllable Attribute
+        icons[0] = MetalIcons.getBlueFolderIcon();
+        // Non-administrable Service
+        icons[1] = MetalIcons.getGrayFolderIcon();
+        // "Connection Refused" Service
+        icons[2] = MetalIcons.getUnusableFolderIcon();
+    }
+
+    private class ServiceListItem {
+
+        private ServiceItem item;
+        private boolean isAccessible;
+        private Object admin = null;
+
+        public ServiceListItem(ServiceItem item) {
+            this.item = item;
+            isAccessible = (item.service != null);
+        }
+
+        public String getTitle() {
+            if (item.service == null) {
+                return "Unknown service";
+            }
+
+            HashSet set = new HashSet();
+            Class[] infs = getInterfaces(item.service.getClass());
+            for (int j = 0; j < infs.length; j++) {
+                set.add(infs[j].getName());
+            }
+
+            // remove known interfaces
+            set.removeAll(ignoreInterfaces);
+
+            String title = null;
+            if (set.size() == 1) {
+                Iterator iter = set.iterator();
+                title = (String) iter.next();
+            } else {
+                title = item.service.getClass().getName();
+                title += " [";
+                for (Iterator iter = set.iterator(); iter.hasNext();) {
+                    title += (String) iter.next();
+                    if (iter.hasNext()) {
+                        title += ", ";
+                    }
+                }
+                title += "]";
+            }
+            if (!isAccessible) {
+                title += " (Stale service)";
+            }
+            return title;
+        }
+
+        public boolean isAccessible() {
+            getAdmin();
+            return isAccessible;
+        }
+
+        public Object getAdmin() {
+            if (admin == null
+                    && isAccessible
+                    && item.service instanceof Administrable) {
+                try {
+                    admin = adminPreparer.prepareProxy(
+                            ((Administrable) item.service).getAdmin());
+                } catch (Throwable t) {
+                    logger.log(Levels.HANDLED, "failed to get admin proxy", t);
+                    isAccessible = false;
+                }
+            }
+            return admin;
+        }
+
+        public boolean isAdministrable() {
+            getAdmin();
+            return (admin instanceof DestroyAdmin
+                    || admin instanceof JoinAdmin
+                    || admin instanceof DiscoveryAdmin);
+        }
+
+        public boolean isSpaceBrowsable() {
+            return false;
+        }
+
+        private boolean isUI() {
+            Entry[] attrs = item.attributeSets;
+            if ((attrs != null) && (attrs.length != 0)) {
+                for (int i = 0; i < attrs.length; i++) {
+                    if (attrs[i] instanceof UIDescriptor) {
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        public ServiceItem getServiceItem() {
+            return item;
+        }
+
+        public Entry[] getAttributes() {
+            return item.attributeSets;
+        }
+
+        public Icon getIcon() {
+            if (!isAccessible()) {
+                return icons[2];
+            } else if (isAdministrable()) {
+                return icons[0];
+            } else {
+                return icons[1];
+            }
+        }
+
+        public String toString() {
+            return isAccessible()
+                    ? item.service.getClass().getName() : "Unknown service";
+        }
+    }
+
+    private class MouseReceiver extends MouseAdapter {
+
+        private ServiceListPopup popup;
+
+        public MouseReceiver(ServiceListPopup popup) {
+            this.popup = popup;
+        }
+
+        public void mouseClicked(MouseEvent ev) {
+            if (ev.getClickCount() >= 2) {
+                ServiceListItem listItem = getTargetListItem(ev);
+                if (listItem != null) {
+                    ServiceItem item = listItem.getServiceItem();
+                    if (listItem.isAdministrable()) {
+                        new ServiceEditor(item, listItem.getAdmin(), lookup,
+                                Browser.this).setVisible(true);
+                    } else if (listItem.isAccessible()) {
+                        new ServiceBrowser(item, lookup,
+                                Browser.this).setVisible(true);
+                    }
+                }
+            }
+        }
+
+        public void mouseReleased(MouseEvent ev) {
+            if (ev.isPopupTrigger() && (getTargetListItem(ev) != null)) {
+                popup.setServiceItem(getTargetListItem(ev));
+                popup.show(ev.getComponent(), ev.getX(), ev.getY());
+            }
+        }
+
+        public void mousePressed(MouseEvent ev) {
+            if (ev.isPopupTrigger() && (getTargetListItem(ev) != null)) {
+                popup.setServiceItem(getTargetListItem(ev));
+                popup.show(ev.getComponent(), ev.getX(), ev.getY());
+            }
+        }
+
+        private ServiceListItem getTargetListItem(MouseEvent ev) {
+            int index = list.locationToIndex(ev.getPoint());
+            if (index >= 0) {
+                return (ServiceListItem) listModel.getElementAt(index);
+            } else {
+                return null;
+            }
+        }
+    }
+
+    private class ServiceListPopup
+            extends JPopupMenu
+            implements ActionListener, PopupMenuListener {
+
+        protected JMenuItem infoItem;
+        protected JMenuItem browseItem;
+        protected JMenuItem adminItem;
+        protected JMenuItem spaceItem;
+        protected ServiceListItem listItem;
+        protected JMenuItem uiItem;
+        protected ServiceItem item;
+
+        public ServiceListPopup() {
+            super();
+
+            ActionListener me = wrap(this);
+            infoItem = new JMenuItem("Show Info");
+            infoItem.addActionListener(me);
+            infoItem.setActionCommand("showInfo");
+            add(infoItem);
+
+            browseItem = new JMenuItem("Browse Service");
+            browseItem.addActionListener(me);
+            browseItem.setActionCommand("browseService");
+            add(browseItem);
+
+            adminItem = new JMenuItem("Admin Service");
+            adminItem.addActionListener(me);
+            adminItem.setActionCommand("adminService");
+            add(adminItem);
+
+            spaceItem = new JMenuItem("Browse Entries");
+            spaceItem.addActionListener(me);
+            spaceItem.setActionCommand("browseEntry");
+            add(spaceItem);
+
+            uiItem = new JMenuItem("Show UI");
+            uiItem.addActionListener(me);
+            uiItem.setActionCommand("showUI");
+            add(uiItem);
+
+            addPopupMenuListener(this);
+            setOpaque(true);
+            setLightWeightPopupEnabled(true);
+        }
+
+        public void setServiceItem(ServiceListItem listItem) {
+            this.listItem = listItem;
+            item = listItem.getServiceItem();
+            infoItem.setEnabled(listItem.isAccessible());
+            browseItem.setEnabled(listItem.isAccessible());
+            adminItem.setEnabled(listItem.isAdministrable());
+            spaceItem.setEnabled(listItem.isSpaceBrowsable());
+            uiItem.setEnabled(listItem.isUI());
+        }
+
+        public void actionPerformed(ActionEvent ev) {
+            String command = ev.getActionCommand();
+
+            if (command.equals("showInfo")) {
+                Class[] infs = 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(Browser.this,
+                        msg,
+                        "ServiceItem Information",
+                        JOptionPane.INFORMATION_MESSAGE);
+            } else if (command.equals("browseService")) {
+                new ServiceBrowser(item, lookup,
+                        Browser.this).setVisible(true);
+            } else if (command.equals("adminService")) {
+                new ServiceEditor(item, listItem.getAdmin(),
+                        lookup, Browser.this).setVisible(true);
+            } else if (command.equals("browseEntry")) {
+                // Not supported at the present time.
+            } else if (command.equals("showUI")) {
+                UIDescriptor uiDescriptor = getSelectedUIDescriptor();
+
+                if (uiDescriptor == null) {
+                    return;
+                }
+
+                try {
+                    JFrameFactory uiFactory = (JFrameFactory) uiDescriptor.getUIFactory(
+                            Thread.currentThread().getContextClassLoader());
+                    JFrame frame = uiFactory.getJFrame(item);
+
+                    frame.validate();
+                    frame.setVisible(true);
+                } catch (Exception e) {
+                    logger.log(Level.INFO, "show ui failed", e);
+                    JOptionPane.showMessageDialog(Browser.this,
+                            e.getMessage(),
+                            e.getClass().getName(),
+                            JOptionPane.WARNING_MESSAGE);
+                    return;
+                }
+            }
+        }
+
+        public void popupMenuWillBecomeVisible(PopupMenuEvent ev) {
+        }
+
+        public void popupMenuWillBecomeInvisible(PopupMenuEvent ev) {
+        }
+
+        public void popupMenuCanceled(PopupMenuEvent ev) {
+        }
+
+        private UIDescriptor getSelectedUIDescriptor() {
+
+            if (!(new ServiceListItem(item)).isUI()) {
+                return null;
+            }
+
+            Entry[] attrs = item.attributeSets;
+            if ((attrs != null) && (attrs.length != 0)) {
+                for (int i = 0; i < attrs.length; i++) {
+                    if (attrs[i] instanceof UIDescriptor) {
+                        UIDescriptor desc = (UIDescriptor) attrs[i];
+                        if (!"javax.swing".equals(desc.toolkit)) {
+                            continue;
+                        }
+                        return desc;
+                    }
+                }
+            }
+            return null;
+        }
+    }
+
+    private class Exiter extends WindowAdapter {
+
+        public void windowClosing(WindowEvent e) {
+            Browser.this.exiter.actionPerformed(
+                    new ActionEvent(e.getSource(), e.getID(),
+                    "Exit", System.currentTimeMillis(), 0));
+        }
+    }
+
+    /**
+     * An action listener that cancels any lookup service event registration
+     * lease and then calls {@link System#exit System.exit}.
+     */
+    public static class Exit implements ActionListener {
+
+        /**
+         * Cancels any lookup service event registration lease and calls {@link System#exit System.exit}
+         * <code>(0)</code>.
+         */
+        public void actionPerformed(ActionEvent ev) {
+            Object src = ev.getSource();
+            while (!(src instanceof Browser) && src instanceof Component) {
+                if (src instanceof JPopupMenu) {
+                    src = ((JPopupMenu) src).getInvoker();
+                } else {
+                    src = ((Component) src).getParent();
+                }
+            }
+            if (src instanceof Browser) {
+                try {
+                    ((Browser) src).cancelLease();
+                } catch (Throwable t) {
+                    t.printStackTrace();
+                }
+            }
+            System.exit(0);
+        }
+    }
+
+    /**
+     * Runs the service browser. See the package documentation for details.
+     *
+     * @param args command line arguments
+     */
+    public static void main(String[] args) {
+        if (System.getSecurityManager() == null) {
+            System.setSecurityManager(new SecurityManager());
+        }
+        try {
+            final Configuration config =
+                    ConfigurationProvider.getInstance(
+                    args, Browser.class.getClassLoader());
+            LoginContext login =
+                    (LoginContext) config.getEntry(BROWSER, "loginContext",
+                    LoginContext.class, null);
+            if (login != null) {
+                login.login();
+            }
+            PrivilegedExceptionAction action =
+                    new PrivilegedExceptionAction() {
+                public Object run() throws Exception {
+                    return new Browser(null, config);
+                }
+            };
+            if (login != null) {
+                Subject.doAsPrivileged(login.getSubject(), action, null);
+            } else {
+                action.run();
+            }
+        } catch (Throwable t) {
+            if (t instanceof PrivilegedActionException) {
+                t = t.getCause();
+            }
+            logger.log(Level.SEVERE, "browser initialization failed", t);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/river-container/blob/7ff8b15a/browser/src/main/java/org/apache/river/container/examples/browser/EntryTreePanel.java
----------------------------------------------------------------------
diff --git a/browser/src/main/java/org/apache/river/container/examples/browser/EntryTreePanel.java b/browser/src/main/java/org/apache/river/container/examples/browser/EntryTreePanel.java
new file mode 100644
index 0000000..95ff9f6
--- /dev/null
+++ b/browser/src/main/java/org/apache/river/container/examples/browser/EntryTreePanel.java
@@ -0,0 +1,292 @@
+/*
+ * 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 org.apache.river.container.examples.browser;
+
+import net.jini.core.entry.Entry;
+import java.lang.reflect.Field;
+import java.lang.reflect.Array;
+import java.awt.Component;
+import java.awt.BorderLayout;
+import java.util.logging.Level;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.JLabel;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeCellRenderer;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+
+/**
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ * @version 0.2 06/04/98
+ *
+ */
+abstract class EntryTreePanel extends JPanel {
+  /**
+   * running mode. 
+   *
+   * @serial
+   */
+  private boolean isControllable;
+
+
+  /**
+   * @serial
+   */
+
+  private JScrollPane scrollPane;
+
+  /**
+   * @serial
+   */
+  protected JTree tree;
+
+  /**
+   * @serial
+   */
+  protected ObjectNode root;
+
+  /**
+   * @serial
+   */
+  protected DefaultTreeModel model;
+
+  /**
+   * @serial
+   */
+  private boolean showModifier = false;
+
+  /**
+   * @serial
+   */
+  private boolean showPackage = false;
+
+
+  public EntryTreePanel(boolean isControllable) {
+    this.isControllable = isControllable;
+
+    // Init this panel
+    setLayout(new BorderLayout());
+
+    // Init tree node and model (attribute tree nodes)
+    root = new ObjectNode(isControllable);
+    //initTree();
+    model = new DefaultTreeModel(root);
+
+    // Init tree view
+    tree = new JTree(model);
+    //tree.addMouseListener(new DoubleClicker(this));
+    tree.setRootVisible(false);
+    ObjectNodeRenderer renderer = new ObjectNodeRenderer();
+    tree.setCellRenderer(renderer);
+    tree.setRowHeight(0);	// let the renderer handle it
+    scrollPane = new JScrollPane(tree);
+    add(scrollPane, "Center");
+
+    tree.validate();
+    scrollPane.validate();
+  }
+
+  protected abstract Entry[] getEntryArray();
+
+
+  protected void initTree() {
+    Entry[] entries = getEntryArray();
+    if(entries == null)
+      entries = new Entry[0];
+
+    for(int i = 0; i < entries.length; i++){
+      // check controllability
+      boolean nodeControllable = false;
+      if(isControllable && ! (entries[i] instanceof net.jini.lookup.entry.ServiceControlled)) {
+	nodeControllable = true;
+      }
+
+      ObjectNode node = new ObjectNode(entries[i], nodeControllable);
+      root.add(node);
+      try {
+	recursiveObjectTree(node);
+      } catch(IllegalAccessException e){
+	Browser.logger.log(Level.INFO, "entry access failed", e);
+      }
+    }
+  }
+
+  public void refreshPanel() {
+    // reconstruct nodes
+    root.removeAllChildren();
+    initTree();
+    
+    model.nodeStructureChanged(root);
+
+    tree.validate();
+    scrollPane.validate();
+  }
+
+  protected void recursiveObjectTree(ObjectNode node)
+    throws IllegalArgumentException, IllegalAccessException {
+
+    Object obj = node.getObject();
+    if(obj == null)
+      return;
+    //Field[] fields = obj.getClass().getDeclaredFields();
+    Field[] fields = obj.getClass().getFields();
+
+    for(int i = 0; i < fields.length; i++){
+      Field f = fields[i];
+
+      if(Introspector.isHidden(f))
+	continue;
+
+      Class clazz = f.getType();
+      ObjectNode child = null;
+      String fname = f.getName();
+      if(clazz.isPrimitive()){
+	String clazzName = clazz.toString();
+	Object fobj = null;
+	if("int".equals(clazzName)){
+	  fobj = new Integer(f.getInt(obj));
+	} else if("boolean".equals(clazzName)){
+	  fobj = new Boolean(f.getBoolean(obj));
+	} else if("byte".equals(clazzName)){
+	  fobj = new Byte(f.getByte(obj));
+	} else if("char".equals(clazzName)){
+	  fobj = new Character(f.getChar(obj));
+	} else if("double".equals(clazzName)){
+	  fobj = new Double(f.getDouble(obj));
+	} else if("float".equals(clazzName)){
+	  fobj = new Float(f.getFloat(obj));
+	} else if("long".equals(clazzName)){
+	  fobj = new Long(f.getLong(obj));
+	}
+
+	child = new ObjectNode(fobj, clazz, fname, true);
+      } else if(Introspector.isWrapper(clazz) || Introspector.isString(clazz)) {
+	child = new ObjectNode(f.get(obj), clazz, fname, true);
+      } else if(clazz.isArray()){
+	child = new ObjectNode(f.get(obj), clazz, fname, false);
+	child.setAdministrable(node.isAdministrable());
+	child.setControllable(node.isControllable());
+	recursiveArrayTree(child, f);
+      } else {
+	// unknown type
+	Object subobj = f.get(obj);
+
+	// check if sub object has a viewable members.
+	if(countViewableFields(clazz) > 0){
+	  child = new ObjectNode(subobj, clazz, fname, false);
+	  child.setAdministrable(node.isAdministrable());
+	  child.setControllable(node.isControllable());
+	  recursiveObjectTree(child);
+	} else {
+	  child = new ObjectNode(subobj, clazz, fname, true);
+	}
+      }
+      node.add(child);
+    }
+  }
+
+  private int countViewableFields(Class clazz) {
+
+    int count = 0;
+    //Field[] fields = obj.getClass().getDeclaredFields();
+    //Field[] fields = obj.getClass().getFields();
+    Field[] fields = clazz.getFields();
+    for(int i = 0; i < fields.length; i++){
+      Field f = fields[i];
+
+      if(Introspector.isHidden(f))
+	continue;
+
+      count++;
+    }
+
+    return count;
+  }
+
+  private void recursiveArrayTree(ObjectNode node, Field f)
+    throws IllegalArgumentException, IllegalAccessException {
+
+    String name = node.getFieldName();
+    Object aobj = node.getObject();
+
+    int length = Array.getLength(aobj);
+
+    Class clazz = f.getType().getComponentType();
+
+    if(clazz.isPrimitive() || Introspector.isWrapper(clazz) || Introspector.isString(clazz)){
+      // primitive, wrapper objects, string array
+      for(int i = 0; i < length; i++){
+	Object elem = Array.get(aobj, i);
+	//String fname = name + "[" + i + "]"; 
+	ObjectNode child = new ObjectNode(elem, clazz, name, i, true);
+	node.add(child);
+      }
+    } else {
+      // Object or Array (*sigh*)
+      for(int i = 0; i < length; i++){
+	Object elem = Array.get(aobj, i);
+	//String fname = name + "[" + i + "]"; 
+	ObjectNode child = new ObjectNode(elem, clazz, name, i, false);
+	recursiveObjectTree(child);
+	child.setAdministrable(node.isAdministrable());
+	child.setControllable(node.isControllable());
+
+	node.add(child);
+      }
+    }
+  }
+
+
+  class ObjectNodeRenderer implements TreeCellRenderer {
+    private JLabel label;
+
+    public ObjectNodeRenderer() {
+      label = new JLabel();
+      label.setOpaque(true);
+    }
+    
+    public Component getTreeCellRendererComponent(JTree tree,
+						  Object value,
+						  boolean isSelected,
+						  boolean isExpanded,
+						  boolean isLeaf,
+						  int row,
+						  boolean cellHasFocus){
+
+      //label.setFont(tree.getFont());
+      label.setForeground(tree.getForeground());
+      if(isSelected){
+	//label.setBackground(UIManager.getColor("Tree.backgroundSelectionColor"));
+	//label.setForeground(UIManager.getColor("Tree.textSelectionColor"));
+	label.setBackground(MetalLookAndFeel.getPrimaryControl());
+      } else {
+	//label.setBackground(UIManager.getColor("Tree.backgroundNonSelectionColor"));
+	//label.setForeground(UIManager.getColor("Tree.textNonSelectionColor"));
+	label.setBackground(tree.getBackground());
+      }
+
+      ObjectNode node = (ObjectNode) value;
+      label.setText(node.getTitle());
+      label.setIcon(node.getIcon());
+      return label;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/river-container/blob/7ff8b15a/browser/src/main/java/org/apache/river/container/examples/browser/Introspector.java
----------------------------------------------------------------------
diff --git a/browser/src/main/java/org/apache/river/container/examples/browser/Introspector.java b/browser/src/main/java/org/apache/river/container/examples/browser/Introspector.java
new file mode 100644
index 0000000..e7781d5
--- /dev/null
+++ b/browser/src/main/java/org/apache/river/container/examples/browser/Introspector.java
@@ -0,0 +1,106 @@
+/*
+ * 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 org.apache.river.container.examples.browser;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Array;
+import java.lang.reflect.Modifier;
+
+/**
+ * Introspection related methods
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ * @version 0.2 06/04/98
+ *
+ */
+
+class Introspector {
+
+  public static boolean isHidden(Field f){
+    int m = f.getModifiers();
+
+    if(Modifier.isPrivate(m) || Modifier.isStatic(m))
+      return true;
+
+    return false;
+  }
+
+  public static boolean isString(Class clazz){
+    if("java.lang.String".equals(clazz.getName()))
+      return true;
+    return false;
+  }
+
+  public static boolean isWrapper(Class clazz){
+    String name = clazz.getName();
+
+    if("java.lang.Integer".equals(name) ||
+       "java.lang.Boolean".equals(name) ||
+       "java.lang.Byte".equals(name) ||
+       "java.lang.Char".equals(name) ||
+       "java.lang.Double".equals(name) ||
+       "java.lang.Float".equals(name) ||
+       "java.lang.Long".equals(name)){
+      return true;
+    }
+    return false;
+  }
+
+  /** Return the name of an interface or primitive type, handling arrays. */
+  public static String getTypename(Class t, boolean showPackage) {
+    String brackets = "";
+    while(t.isArray()) {
+      brackets += "[]";
+      t = t.getComponentType();
+    }
+
+    if(showPackage)
+      return t.getName() + brackets;
+    else
+      return extractClassName(t.getName()) + brackets;
+  }
+
+  /** Return a string version of modifiers, handling spaces nicely. */
+  public static String getModifierString(int m) {
+    if(m == 0)
+      return "";
+    else
+      return Modifier.toString(m) + " ";
+  }
+
+  /** Print the modifiers, type, and name of a field. */
+  public static String getFieldString(Field f, boolean showModifier, boolean showPackage) {
+    String fstring = "";
+    
+    if(showModifier)
+      fstring += getModifierString(f.getModifiers());
+
+    fstring += getTypename(f.getType(), showPackage);
+    fstring += " ";
+    fstring += f.getName();
+
+    return fstring;
+  }
+
+  public static String extractClassName(String fullName){
+    int index = fullName.lastIndexOf(".");
+    
+    return fullName.substring(index + 1);
+  }
+}


Mime
View raw message