From fa6e5bb0c17c4d59d8598979feb1a7701bc32679 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Tue, 12 Dec 2006 23:55:39 +0000
Subject: [PATCH] Publish a separate monitor entry for each connection handler, which includes the protocol, listen address/port, number of established connections, and information about each connection.

---
 opends/resource/schema/02-config.ldif                                                 |   23 +
 opends/src/server/org/opends/server/monitors/BackendMonitor.java                      |   17 +
 opends/src/server/org/opends/server/types/HostPort.java                               |  143 ++++++++
 opends/src/server/org/opends/server/protocols/internal/InternalConnectionHandler.java |   45 ++
 opends/src/server/org/opends/server/api/ConnectionHandler.java                        |   78 ++++
 opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java            |   39 ++
 opends/src/server/org/opends/server/util/ServerConstants.java                         |   53 +++
 opends/src/server/org/opends/server/core/DirectoryServer.java                         |   16 
 opends/src/server/org/opends/server/api/ClientConnection.java                         |   57 +++
 opends/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java            |  247 ++++++++++++++
 opends/src/server/org/opends/server/backends/MonitorBackend.java                      |   24 +
 opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java           |   71 ++++
 opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java         |   70 +++
 opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java  |   22 +
 opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java          |   69 +++
 opends/src/server/org/opends/server/api/MonitorProvider.java                          |   24 +
 16 files changed, 983 insertions(+), 15 deletions(-)

diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index a6be239..cd3a18b 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -1009,6 +1009,18 @@
 attributeTypes: ( 1.3.6.1.4.1.26027.1.1.295 NAME 'ds-backend-writability-mode'
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
   X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.296 NAME
+  'ds-connectionhandler-connection' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.297 NAME
+  'ds-connectionhandler-listener' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.298 NAME
+  'ds-connectionhandler-num-connections' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.299 NAME
+  'ds-connectionhandler-protocol' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
   NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
   MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1067,7 +1079,7 @@
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.13
   NAME 'ds-cfg-connection-handler' SUP top STRUCTURAL
   MUST ( cn $ ds-cfg-connection-handler-class $
-  ds-cfg-connection-handler-enabled ) MAY ( ds-cfg-allowed-client $ 
+  ds-cfg-connection-handler-enabled ) MAY ( ds-cfg-allowed-client $
   ds-cfg-denied-client ) X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.14
   NAME 'ds-cfg-ldap-connection-handler' SUP ds-cfg-connection-handler
@@ -1380,4 +1392,13 @@
   X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.77 NAME 'ds-monitor-entry' SUP top
   STRUCTURAL MUST cn X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.78 NAME 'ds-backend-monitor-entry'
+  SUP ds-monitor-entry STRUCTURAL MAY ( ds-backend-id $ ds-backend-base-dn $
+  ds-backend-entry-count $ ds-backend-writability-mode )
+  X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.79 NAME
+  'ds-connectionhandler-monitor-entry' SUP ds-monitor-entry STRUCTURAL
+  MAY ( ds-connectionhandler-connection $ ds-connectionhandler-listener $
+  ds-connectionhandler-num-connections $ ds-connectionhandler-protocol )
+  X-ORIGIN 'OpenDS Directory Server' )
 
diff --git a/opends/src/server/org/opends/server/api/ClientConnection.java b/opends/src/server/org/opends/server/api/ClientConnection.java
index c813a3e..41fd2ca 100644
--- a/opends/src/server/org/opends/server/api/ClientConnection.java
+++ b/opends/src/server/org/opends/server/api/ClientConnection.java
@@ -46,6 +46,7 @@
 import org.opends.server.types.IntermediateResponse;
 import org.opends.server.types.SearchResultEntry;
 import org.opends.server.types.SearchResultReference;
+import org.opends.server.util.TimeThread;
 
 import static org.opends.server.loggers.Debug.*;
 import static org.opends.server.messages.MessageHandler.*;
@@ -83,10 +84,17 @@
   // The lookthrough limit for use with this client connection.
   private int lookthroughLimit;
 
+  // The time that this client connection was established.
+  private long connectTime;
+
   // The opaque information used for storing intermediate state
   // information needed across multi-stage SASL binds.
   private Object saslAuthState;
 
+  // A string representation of the time that this client connection
+  // was established.
+  private String connectTimeString;
+
   // A set of persistent searches registered for this client.
   private CopyOnWriteArrayList<PersistentSearch> persistentSearches;
 
@@ -100,6 +108,8 @@
   {
     assert debugConstructor(CLASS_NAME);
 
+    connectTime        = TimeThread.getTime();
+    connectTimeString  = TimeThread.getUTCTime();
     authenticationInfo = new AuthenticationInfo();
     saslAuthState      = null;
     bindInProgress     = false;
@@ -112,6 +122,38 @@
 
 
   /**
+   * Retrieves the time that this connection was established, measured
+   * in the number of milliseconds since January 1, 1970 UTC.
+   *
+   * @return  The time that this connection was established, measured
+   *          in the number of milliseconds since January 1, 1970 UTC.
+   */
+  public long getConnectTime()
+  {
+    assert debugEnter(CLASS_NAME, "getConnectTime");
+
+    return connectTime;
+  }
+
+
+
+  /**
+   * Retrieves a string representation of the time that this
+   * connection was established.
+   *
+   * @return  A string representation of the time that this connection
+   *          was established.
+   */
+  public String getConnectTimeString()
+  {
+    assert debugEnter(CLASS_NAME, "getConnectTimeString");
+
+    return connectTimeString;
+  }
+
+
+
+  /**
    * Retrieves the unique identifier that has been assigned to this
    * connection.
    *
@@ -852,6 +894,21 @@
 
 
   /**
+   * Retrieves a one-line summary of this client connection in a form
+   * that is suitable for including in the monitor entry for the
+   * associated connection handler.  It should be in a format that is
+   * both humand readable and machine parseable (e.g., a
+   * space-delimited name-value list, with quotes around the values).
+   *
+   * @return  A one-line summary of this client connection in a form
+   *          that is suitable for including in the monitor entry for
+   *          the associated connection handler.
+   */
+  public abstract String getMonitorSummary();
+
+
+
+  /**
    * Retrieves a string representation of this client connection.
    *
    * @return  A string representation of this client connection.
diff --git a/opends/src/server/org/opends/server/api/ConnectionHandler.java b/opends/src/server/org/opends/server/api/ConnectionHandler.java
index 74a03e3..fde92b8 100644
--- a/opends/src/server/org/opends/server/api/ConnectionHandler.java
+++ b/opends/src/server/org/opends/server/api/ConnectionHandler.java
@@ -31,6 +31,8 @@
 import java.util.Collection;
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
+import org.opends.server.monitors.ConnectionHandlerMonitor;
+import org.opends.server.types.HostPort;
 import org.opends.server.types.InitializationException;
 
 import static org.opends.server.loggers.Debug.*;
@@ -52,6 +54,11 @@
 
 
 
+  // The monitor associated with this connection handler.
+  private ConnectionHandlerMonitor monitor;
+
+
+
   /**
    * Creates a new instance of this connection handler.  This must be
    * called by all connection handlers, and all connection handlers
@@ -65,6 +72,7 @@
     super(threadName);
 
     assert debugConstructor(CLASS_NAME, String.valueOf(threadName));
+    monitor = null;
   }
 
 
@@ -114,6 +122,44 @@
 
 
   /**
+   * Retrieves a name that may be used to refer to this connection
+   * handler.  Every connection handler instance (even handlers of the
+   * same type) must have a unique name.
+   *
+   * @return  A unique name that may be used to refer to this
+   *          connection handler.
+   */
+  public abstract String getConnectionHandlerName();
+
+
+
+  /**
+   * Retrieves the name of the protocol used to communicate with
+   * clients.  It should take into account any special naming that may
+   * be needed to express any security mechanisms or other constraints
+   * in place (e.g., "LDAPS" for LDAP over SSL).
+   *
+   * @return  The name of the protocol used to communicate with
+   *          clients.
+   */
+  public abstract String getProtocol();
+
+
+
+  /**
+   * Retrieves information about the listener(s) that will be used to
+   * accept client connections.
+   *
+   * @return  Information about the listener(s) that will be used to
+   *          accept client connections, or an empty list if this
+   *          connection handler does not accept connections from
+   *          network clients.
+   */
+  public abstract Collection<HostPort> getListeners();
+
+
+
+  /**
    * Retrieves the set of active client connections that have been
    * established through this connection handler.
    *
@@ -133,6 +179,38 @@
 
 
   /**
+   * Retrieves the monitor instance for this connection handler.
+   *
+   * @return  The monitor instance for this connection handler, or
+   *          {@code null} if none has been provided.
+   */
+  public ConnectionHandlerMonitor getConnectionHandlerMonitor()
+  {
+    assert debugEnter(CLASS_NAME, "getConnectionHandlerMonitor");
+
+    return monitor;
+  }
+
+
+
+  /**
+   * Sets the monitor instance for this connection handler.
+   *
+   * @param  monitor  The monitor instance for this connection
+   *                  handler.
+   */
+  public void setConnectionHandlerMonitor(
+                   ConnectionHandlerMonitor monitor)
+  {
+    assert debugEnter(CLASS_NAME, "setConnectionHandlerMonitor",
+                      String.valueOf(monitor));
+
+    this.monitor = monitor;
+  }
+
+
+
+  /**
    * Retrieves a string representation of this connection handler.
    *
    * @return  A string representation of this connection handler.
diff --git a/opends/src/server/org/opends/server/api/MonitorProvider.java b/opends/src/server/org/opends/server/api/MonitorProvider.java
index 9ea1f34..bc8dbe7 100644
--- a/opends/src/server/org/opends/server/api/MonitorProvider.java
+++ b/opends/src/server/org/opends/server/api/MonitorProvider.java
@@ -33,9 +33,12 @@
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.types.Attribute;
+import org.opends.server.types.DirectoryConfig;
 import org.opends.server.types.InitializationException;
+import org.opends.server.types.ObjectClass;
 
 import static org.opends.server.loggers.Debug.*;
+import static org.opends.server.util.ServerConstants.*;
 
 
 
@@ -149,6 +152,27 @@
 
 
   /**
+   * Retrieves the objectclass that should be included in the monitor
+   * entry created from this monitor provider.  This may be overridden
+   * by subclasses that wish to include their own custom objectclass
+   * in the monitor entry (e.g., to make it easier to search for
+   * monitor entries of that type).  The default implementation
+   * returns the "extensibleObject" objectclass.
+   *
+   * @return  The objectclass that should be included in the monitor
+   *          entry created from this monitor provider.
+   */
+  public ObjectClass getMonitorObjectClass()
+  {
+    assert debugEnter(CLASS_NAME, "getMonitorObjectClass");
+
+    return DirectoryConfig.getObjectClass(OC_EXTENSIBLE_OBJECT_LC,
+                                          true);
+  }
+
+
+
+  /**
    * Retrieves the length of time in milliseconds that should elapse
    * between calls to the <CODE>updateMonitorData()</CODE> method.  A
    * negative or zero return value indicates that the
diff --git a/opends/src/server/org/opends/server/backends/MonitorBackend.java b/opends/src/server/org/opends/server/backends/MonitorBackend.java
index 5803d79..f5a821f 100644
--- a/opends/src/server/org/opends/server/backends/MonitorBackend.java
+++ b/opends/src/server/org/opends/server/backends/MonitorBackend.java
@@ -222,7 +222,7 @@
 
 
     // Construct the set of objectclasses to include in the base monitor entry.
-    monitorObjectClasses = new LinkedHashMap<ObjectClass,String>(3);
+    monitorObjectClasses = new LinkedHashMap<ObjectClass,String>(2);
     ObjectClass topOC = DirectoryServer.getObjectClass(OC_TOP, true);
     monitorObjectClasses.put(topOC, OC_TOP);
 
@@ -230,10 +230,6 @@
                                                            true);
     monitorObjectClasses.put(monitorOC, OC_MONITOR_ENTRY);
 
-    ObjectClass extensibleObjectOC =
-         DirectoryServer.getObjectClass(OC_EXTENSIBLE_OBJECT_LC, true);
-    monitorObjectClasses.put(extensibleObjectOC, OC_EXTENSIBLE_OBJECT);
-
 
     // Define an empty sets for the supported controls and features.
     supportedControls = new HashSet<String>(0);
@@ -509,6 +505,13 @@
     assert debugEnter(CLASS_NAME, "getBaseMonitorEntry");
 
 
+    HashMap<ObjectClass,String> monitorClasses =
+         new LinkedHashMap<ObjectClass,String>(3);
+    monitorClasses.putAll(monitorObjectClasses);
+
+    ObjectClass extensibleObjectOC =
+         DirectoryServer.getObjectClass(OC_EXTENSIBLE_OBJECT_LC, true);
+    monitorClasses.put(extensibleObjectOC, OC_EXTENSIBLE_OBJECT);
 
     HashMap<AttributeType,List<Attribute>> monitorUserAttrs =
          new LinkedHashMap<AttributeType,List<Attribute>>();
@@ -655,7 +658,7 @@
 
 
     // Construct and return the entry.
-    return new Entry(baseMonitorDN, monitorObjectClasses, monitorUserAttrs,
+    return new Entry(baseMonitorDN, monitorClasses, monitorUserAttrs,
                      monitorOperationalAttrs);
   }
 
@@ -677,6 +680,13 @@
     assert debugEnter(CLASS_NAME, "getMonitorEntry",
                       String.valueOf(monitorProvider));
 
+    HashMap<ObjectClass,String> monitorClasses =
+         new LinkedHashMap<ObjectClass,String>(3);
+    monitorClasses.putAll(monitorObjectClasses);
+
+    ObjectClass monitorOC = monitorProvider.getMonitorObjectClass();
+    monitorClasses.put(monitorOC, monitorOC.getPrimaryName());
+
     List<Attribute> monitorAttrs = monitorProvider.getMonitorData();
     HashMap<AttributeType,List<Attribute>> attrMap =
          new LinkedHashMap<AttributeType,List<Attribute>>(
@@ -717,7 +727,7 @@
       }
     }
 
-    return new Entry(entryDN, monitorObjectClasses, attrMap,
+    return new Entry(entryDN, monitorClasses, attrMap,
                      new HashMap<AttributeType,List<Attribute>>(0));
   }
 
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index e4f69a6..1d60a8e 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -91,6 +91,7 @@
 import org.opends.server.loggers.StartupDebugLogger;
 import org.opends.server.loggers.StartupErrorLogger;
 import org.opends.server.monitors.BackendMonitor;
+import org.opends.server.monitors.ConnectionHandlerMonitor;
 import org.opends.server.schema.AttributeTypeSyntax;
 import org.opends.server.schema.BinarySyntax;
 import org.opends.server.schema.BooleanEqualityMatchingRule;
@@ -5340,6 +5341,7 @@
         String instanceName = toLowerCase(monitor.getMonitorInstanceName());
         deregisterMonitorProvider(instanceName);
         monitor.finalizeMonitorProvider();
+        backend.setBackendMonitor(null);
       }
     }
   }
@@ -6444,6 +6446,11 @@
     synchronized (directoryServer.connectionHandlers)
     {
       directoryServer.connectionHandlers.add(handler);
+
+      ConnectionHandlerMonitor monitor = new ConnectionHandlerMonitor(handler);
+      monitor.initializeMonitorProvider(null);
+      handler.setConnectionHandlerMonitor(monitor);
+      registerMonitorProvider(monitor);
     }
   }
 
@@ -6463,6 +6470,15 @@
     synchronized (directoryServer.connectionHandlers)
     {
       directoryServer.connectionHandlers.remove(handler);
+
+      ConnectionHandlerMonitor monitor = handler.getConnectionHandlerMonitor();
+      if (monitor != null)
+      {
+        String instanceName = toLowerCase(monitor.getMonitorInstanceName());
+        deregisterMonitorProvider(instanceName);
+        monitor.finalizeMonitorProvider();
+        handler.setConnectionHandlerMonitor(null);
+      }
     }
   }
 
diff --git a/opends/src/server/org/opends/server/monitors/BackendMonitor.java b/opends/src/server/org/opends/server/monitors/BackendMonitor.java
index 42029df..eb910e1 100644
--- a/opends/src/server/org/opends/server/monitors/BackendMonitor.java
+++ b/opends/src/server/org/opends/server/monitors/BackendMonitor.java
@@ -41,6 +41,7 @@
 import org.opends.server.types.ByteStringFactory;
 import org.opends.server.types.DirectoryConfig;
 import org.opends.server.types.DN;
+import org.opends.server.types.ObjectClass;
 
 import static org.opends.server.loggers.Debug.*;
 import static org.opends.server.util.ServerConstants.*;
@@ -141,6 +142,22 @@
 
 
   /**
+   * Retrieves the objectclass that should be included in the monitor entry
+   * created from this monitor provider.
+   *
+   * @return  The objectclass that should be included in the monitor entry
+   *          created from this monitor provider.
+   */
+  public ObjectClass getMonitorObjectClass()
+  {
+    assert debugEnter(CLASS_NAME, "getMonitorObjectClass");
+
+    return DirectoryConfig.getObjectClass(OC_MONITOR_BACKEND, true);
+  }
+
+
+
+  /**
    * {@inheritDoc}
    */
   public long getUpdateInterval()
diff --git a/opends/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java b/opends/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java
new file mode 100644
index 0000000..0e3f70c
--- /dev/null
+++ b/opends/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java
@@ -0,0 +1,247 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.server.monitors;
+
+
+
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.ConnectionHandler;
+import org.opends.server.api.MonitorProvider;
+import org.opends.server.config.ConfigEntry;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.ByteStringFactory;
+import org.opends.server.types.DirectoryConfig;
+import org.opends.server.types.HostPort;
+import org.opends.server.types.ObjectClass;
+
+import static org.opends.server.loggers.Debug.*;
+import static org.opends.server.util.ServerConstants.*;
+
+
+
+/**
+ * This class implements a monitor provider that will report generic information
+ * for an enabled Directory Server connection handler, including its protocol,
+ * listeners, and established connections.
+ */
+public class ConnectionHandlerMonitor
+       extends MonitorProvider
+{
+  /**
+   * The fully-qualified name of this class for debugging purposes.
+   */
+  private static final String CLASS_NAME =
+       "org.opends.server.monitors.ConnectionHandlerMonitor";
+
+
+
+  // The attribute type that will be used to report the established connections.
+  private AttributeType connectionsType;
+
+  // The attribute type that will be used to report the listeners.
+  private AttributeType listenerType;
+
+  // The attribute type that will be used to report the number of established
+  // client connections.
+  private AttributeType numConnectionsType;
+
+  // The attribute type that will be used to report the protocol.
+  private AttributeType protocolType;
+
+  // The connection handler with which this monitor is associated.
+  private ConnectionHandler connectionHandler;
+
+  // The name for this monitor.
+  private String monitorName;
+
+
+
+  /**
+   * Creates a new instance of this connection handler monitor provider that
+   * will work with the provided connection handler.  Most of the initialization
+   * should be handled in the {@code initializeMonitorProvider} method.
+   *
+   * @param  connectionHandler  The connection handler with which this monitor
+   *                            is associated.
+   */
+  public ConnectionHandlerMonitor(ConnectionHandler connectionHandler)
+  {
+    super(connectionHandler.getConnectionHandlerName());
+
+    assert debugConstructor(CLASS_NAME, String.valueOf(connectionHandler));
+
+    this.connectionHandler = connectionHandler;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void initializeMonitorProvider(ConfigEntry configEntry)
+  {
+    assert debugEnter(CLASS_NAME, "initializeMonitorProvider",
+                      String.valueOf(configEntry));
+
+    monitorName = connectionHandler.getConnectionHandlerName();
+
+    connectionsType =
+         DirectoryConfig.getAttributeType(ATTR_MONITOR_CONNHANDLER_CONNECTION,
+                                          true);
+
+    listenerType =
+         DirectoryConfig.getAttributeType(ATTR_MONITOR_CONNHANDLER_LISTENER,
+                                          true);
+
+    numConnectionsType =
+         DirectoryConfig.getAttributeType(
+              ATTR_MONITOR_CONNHANDLER_NUMCONNECTIONS, true);
+
+    protocolType =
+         DirectoryConfig.getAttributeType(ATTR_MONITOR_CONNHANDLER_PROTOCOL,
+                                          true);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getMonitorInstanceName()
+  {
+    assert debugEnter(CLASS_NAME, "getMonitorInstanceName");
+
+    return monitorName;
+  }
+
+
+
+  /**
+   * Retrieves the objectclass that should be included in the monitor entry
+   * created from this monitor provider.
+   *
+   * @return  The objectclass that should be included in the monitor entry
+   *          created from this monitor provider.
+   */
+  public ObjectClass getMonitorObjectClass()
+  {
+    assert debugEnter(CLASS_NAME, "getMonitorObjectClass");
+
+    return DirectoryConfig.getObjectClass(OC_MONITOR_CONNHANDLER, true);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public long getUpdateInterval()
+  {
+    assert debugEnter(CLASS_NAME, "getUpdateInterval");
+
+    // We don't need do anything on a periodic basis.
+    return 0;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void updateMonitorData()
+  {
+    assert debugEnter(CLASS_NAME, "updateMonitorData");
+
+    // No implementaiton is required.
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public List<Attribute> getMonitorData()
+  {
+    assert debugEnter(CLASS_NAME, "getMonitorData");
+
+    LinkedList<Attribute> attrs = new LinkedList<Attribute>();
+
+    int numConnections = 0;
+    LinkedList<ClientConnection> conns =
+         new LinkedList<ClientConnection>(
+                  connectionHandler.getClientConnections());
+    LinkedList<HostPort> listeners =
+         new LinkedList<HostPort>(connectionHandler.getListeners());
+
+    LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>();
+    values.add(new AttributeValue(protocolType,
+         ByteStringFactory.create(connectionHandler.getProtocol())));
+    attrs.add(new Attribute(protocolType, ATTR_MONITOR_CONNHANDLER_PROTOCOL,
+                            values));
+
+
+    if (! listeners.isEmpty())
+    {
+      values = new LinkedHashSet<AttributeValue>();
+      for (HostPort hp : listeners)
+      {
+        values.add(new AttributeValue(listenerType,
+                                      ByteStringFactory.create(hp.toString())));
+      }
+      attrs.add(new Attribute(listenerType, ATTR_MONITOR_CONNHANDLER_LISTENER,
+                              values));
+    }
+
+    if (! conns.isEmpty())
+    {
+      values = new LinkedHashSet<AttributeValue>();
+      for (ClientConnection c : conns)
+      {
+        numConnections++;
+        values.add(new AttributeValue(connectionsType,
+             ByteStringFactory.create(c.getMonitorSummary())));
+      }
+      attrs.add(new Attribute(connectionsType,
+                              ATTR_MONITOR_CONNHANDLER_CONNECTION, values));
+    }
+
+    values = new LinkedHashSet<AttributeValue>();
+    values.add(new AttributeValue(numConnectionsType,
+         ByteStringFactory.create(String.valueOf(numConnections))));
+    attrs.add(new Attribute(numConnectionsType,
+                            ATTR_MONITOR_CONNHANDLER_NUMCONNECTIONS, values));
+
+    return attrs;
+  }
+}
+
diff --git a/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java b/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
index 9d4942e..f4b4389 100644
--- a/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -1701,6 +1701,25 @@
 
 
   /**
+   * {@inheritDoc}
+   */
+  public String getMonitorSummary()
+  {
+    assert debugEnter(CLASS_NAME, "getMonitorSummary");
+
+    StringBuilder buffer = new StringBuilder();
+    buffer.append("connID=\"");
+    buffer.append(connectionID);
+    buffer.append("\" authDN=\"");
+    buffer.append(getAuthenticationInfo().getAuthenticationDN());
+    buffer.append("\"");
+
+    return buffer.toString();
+  }
+
+
+
+  /**
    * Appends a string representation of this client connection to the
    * provided buffer.
    *
@@ -1709,6 +1728,9 @@
    */
   public void toString(StringBuilder buffer)
   {
+    assert debugEnter(CLASS_NAME, "toString",
+                      "java.lang.StringBuilder");
+
     buffer.append("InternalClientConnection(connID=");
     buffer.append(connectionID);
     buffer.append(", authDN=\"");
diff --git a/opends/src/server/org/opends/server/protocols/internal/InternalConnectionHandler.java b/opends/src/server/org/opends/server/protocols/internal/InternalConnectionHandler.java
index 83578ab..6a37060 100644
--- a/opends/src/server/org/opends/server/protocols/internal/InternalConnectionHandler.java
+++ b/opends/src/server/org/opends/server/protocols/internal/InternalConnectionHandler.java
@@ -36,6 +36,7 @@
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.types.InitializationException;
+import org.opends.server.types.HostPort;
 
 import static org.opends.server.loggers.Debug.*;
 
@@ -65,6 +66,12 @@
   // handler.
   private LinkedList<ClientConnection> connectionList;
 
+  // The list of listeners associated with this connection handler.
+  private LinkedList<HostPort> listeners;
+
+  // The name of the protocol for this connection handler.
+  private String protocol;
+
 
 
   /**
@@ -81,7 +88,9 @@
     // Since we can't guarantee that the initializeConnectionHandler
     // method will always be called for this method, we'll do the
     // necessary "initialization" here.
+    protocol       = "internal";
     connectionList = new LinkedList<ClientConnection>();
+    listeners      = new LinkedList<HostPort>();
   }
 
 
@@ -154,6 +163,42 @@
 
 
   /**
+   * {@inheritDoc}
+   */
+  public String getConnectionHandlerName()
+  {
+    assert debugEnter(CLASS_NAME, "getConnectionHandlerName");
+
+    return "Internal Connection Handler";
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getProtocol()
+  {
+    assert debugEnter(CLASS_NAME, "getProtocol");
+
+    return protocol;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Collection<HostPort> getListeners()
+  {
+    assert debugEnter(CLASS_NAME, "getProtocol");
+
+    return listeners;
+  }
+
+
+
+  /**
    * Retrieves the set of active client connections that have been
    * established through this connection handler.
    *
diff --git a/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java b/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
index b0052f1..79678d2 100644
--- a/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -1084,6 +1084,45 @@
 
 
   /**
+   * {@inheritDoc}
+   */
+  public String getMonitorSummary()
+  {
+    assert debugEnter(CLASS_NAME, "getMonitorSummary");
+
+    StringBuilder buffer = new StringBuilder();
+    buffer.append("connID=\"");
+    buffer.append(connectionID);
+    buffer.append("\" connectTime=\"");
+    buffer.append(getConnectTimeString());
+    buffer.append("\" jmxConnID=\"");
+    buffer.append(jmxConnectionID);
+    buffer.append("\" authDN=\"");
+
+    DN authDN = getAuthenticationInfo().getAuthenticationDN();
+    if (authDN != null)
+    {
+      authDN.toString(buffer);
+    }
+
+    buffer.append("\" security=\"");
+    if (securityProvider.isSecure())
+    {
+      buffer.append(securityProvider.getSecurityMechanismName());
+    }
+    else
+    {
+      buffer.append("none");
+    }
+
+    buffer.append("\"");
+
+    return buffer.toString();
+  }
+
+
+
+  /**
    * Appends a string representation of this client connection to the provided
    * buffer.
    *
diff --git a/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java b/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
index bbfe835..672c353 100644
--- a/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
+++ b/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
@@ -61,6 +61,7 @@
 import org.opends.server.types.DN;
 import org.opends.server.types.ErrorLogCategory;
 import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.HostPort;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ResultCode;
 
@@ -170,6 +171,21 @@
     new LinkedList<ConfigAttribute>();
 
   /**
+   * The unique name for this connection handler.
+   */
+  protected String connectionHandlerName;
+
+  /**
+   * The protocol used to communicate with clients.
+   */
+  protected String protocol;
+
+  /**
+   * The set of listeners for this connection handler.
+   */
+  protected LinkedList<HostPort> listeners = new LinkedList<HostPort>();
+
+  /**
    * The list of active client connection.
    */
   protected LinkedList<ClientConnection> connectionList =
@@ -493,6 +509,19 @@
       String message = getMessage(msgID, String.valueOf(configEntryDN), "");
       throw new InitializationException(msgID, message);
     }
+
+    if (useSSL)
+    {
+      protocol = "JMX+SSL";
+    }
+    else
+    {
+      protocol = "JMX";
+    }
+
+    listeners.clear();
+    listeners.add(new HostPort("0.0.0.0", listenPort));
+    connectionHandlerName = "JMX Connection Handler "+ listenPort;
   }
 
   /**
@@ -518,6 +547,36 @@
   }
 
   /**
+   * {@inheritDoc}
+   */
+  public String getConnectionHandlerName()
+  {
+    assert debugEnter(CLASS_NAME, "getConnectionHandlerName");
+
+    return connectionHandlerName;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getProtocol()
+  {
+    assert debugEnter(CLASS_NAME, "getProtocol");
+
+    return protocol;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Collection<HostPort> getListeners()
+  {
+    assert debugEnter(CLASS_NAME, "getListeners");
+
+    return listeners;
+  }
+
+  /**
    * Retrieves the set of active client connections that have been
    * established through this connection handler.
    *
@@ -842,6 +901,18 @@
       }
     }
 
+    if (useSSL)
+    {
+      protocol = "JMX+SSL";
+    }
+    else
+    {
+      protocol = "JMX";
+    }
+
+    listeners.clear();
+    listeners.add(new HostPort(listenPort));
+
     //
     // Start the new RMI Connector
     rmiConnector.initialize();
diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
index 105d52b..c8c22af 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -188,6 +188,10 @@
   // The string representation of the address of the client.
   private String clientAddress;
 
+  // The name of the protocol that the client is using to communicate with the
+  // server.
+  private String protocol;
+
   // The string representation of the address of the server to which the client
   // has connected.
   private String serverAddress;
@@ -237,6 +241,7 @@
     disconnectRequested  = false;
     operationsInProgress = new ConcurrentHashMap<Integer,Operation>();
     keepStats            = connectionHandler.keepStats();
+    protocol             = "LDAP";
 
     clientAddress = clientChannel.socket().getInetAddress().getHostAddress();
     clientPort    = clientChannel.socket().getPort();
@@ -351,9 +356,7 @@
   {
     assert debugEnter(CLASS_NAME, "getProtocol");
 
-    // FIXME -- what if it is a secure connection?  And what if it is secure now
-    // but wasn't when it was established?
-    return "LDAP";
+    return protocol;
   }
 
 
@@ -522,6 +525,15 @@
                       String.valueOf(securityProvider));
 
     this.securityProvider = securityProvider;
+
+    if (securityProvider.isSecure())
+    {
+      protocol = "LDAP+" + securityProvider.getSecurityMechanismName();
+    }
+    else
+    {
+      protocol = "LDAP";
+    }
   }
 
 
@@ -2355,6 +2367,55 @@
 
 
   /**
+   * {@inheritDoc}
+   */
+  public String getMonitorSummary()
+  {
+    assert debugEnter(CLASS_NAME, "getMonitorSummary");
+
+    StringBuilder buffer = new StringBuilder();
+    buffer.append("connID=\"");
+    buffer.append(connectionID);
+    buffer.append("\" connectTime=\"");
+    buffer.append(getConnectTimeString());
+    buffer.append("\" source=\"");
+    buffer.append(clientAddress);
+    buffer.append(":");
+    buffer.append(clientPort);
+    buffer.append("\" destination=\"");
+    buffer.append(serverAddress);
+    buffer.append(":");
+    buffer.append(connectionHandler.getListenPort());
+    buffer.append("\" ldapVersion=\"");
+    buffer.append(ldapVersion);
+    buffer.append("\" authDN=\"");
+
+    DN authDN = getAuthenticationInfo().getAuthenticationDN();
+    if (authDN != null)
+    {
+      authDN.toString(buffer);
+    }
+
+    buffer.append("\" security=\"");
+    if (securityProvider.isSecure())
+    {
+      buffer.append(securityProvider.getSecurityMechanismName());
+    }
+    else
+    {
+      buffer.append("none");
+    }
+
+    buffer.append("\" opsInProgress=\"");
+    buffer.append(operationsInProgress.size());
+    buffer.append("\"");
+
+    return buffer.toString();
+  }
+
+
+
+  /**
    * Appends a string representation of this client connection to the provided
    * buffer.
    *
@@ -2480,7 +2541,7 @@
     }
 
     clearSecurityProvider = securityProvider;
-    securityProvider      = tlsSecurityProvider;
+    setConnectionSecurityProvider(tlsSecurityProvider);
   }
 
 
diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
index e078e82..adb2099 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -69,6 +69,7 @@
 import org.opends.server.types.DN;
 import org.opends.server.types.ErrorLogCategory;
 import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.HostPort;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ResultCode;
 import org.opends.server.types.SSLClientAuthPolicy;
@@ -206,6 +207,9 @@
   // accepted by the server.
   private int requestHandlerIndex;
 
+  // The set of listeners for this connection handler.
+  private LinkedList<HostPort> listeners;
+
   // The set of request handlers that are associated with this connection
   // handler.
   private LDAPRequestHandler[] requestHandlers;
@@ -223,6 +227,9 @@
   // The unique name assigned to this connection handler.
   private String handlerName;
 
+  // The protocol used by this connection handler.
+  private String protocol;
+
   // The security mechanism used for connections accepted by this connection
   // handler.
   private String securityMechanism;
@@ -996,11 +1003,14 @@
     }
 
 
-    // Construct a unique name for this connection handler.
+    // Construct a unique name for this connection handler, and put together the
+    // set of listeners.
+    listeners = new LinkedList<HostPort>();
     StringBuilder nameBuffer = new StringBuilder();
     nameBuffer.append("LDAP Connection Handler");
     for (InetAddress a : listenAddresses)
     {
+      listeners.add(new HostPort(a.getHostAddress(), listenPort));
       nameBuffer.append(" ");
       nameBuffer.append(a.getHostAddress());
     }
@@ -1013,16 +1023,18 @@
     if (useSSL)
     {
       securityMechanism = SECURITY_MECHANISM_SSL;
+      protocol          = "LDAP+SSL";
     }
     else
     {
       securityMechanism = null;
+      protocol          = "LDAP";
     }
 
 
     // Perform any additional initialization that might be required.
     connHandlerThread = null;
-    statTracker = new LDAPStatistics(handlerName);
+    statTracker = new LDAPStatistics(handlerName + " Statistics");
 
 
     // Create and start the request handlers.
@@ -1091,6 +1103,42 @@
 
 
   /**
+   * {@inheritDoc}
+   */
+  public String getConnectionHandlerName()
+  {
+    assert debugEnter(CLASS_NAME, "getConnectionHandlerName");
+
+    return handlerName;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getProtocol()
+  {
+    assert debugEnter(CLASS_NAME, "getProtocol");
+
+    return protocol;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Collection<HostPort> getListeners()
+  {
+    assert debugEnter(CLASS_NAME, "getProtocol");
+
+    return listeners;
+  }
+
+
+
+  /**
    * Retrieves the set of active client connections that have been established
    * through this connection handler.
    *
@@ -1114,6 +1162,22 @@
 
 
   /**
+   * Retrieves the port on which this connection handler is listening
+   * for client connections.
+   *
+   * @return  The port on which this connection handler is listening
+   *          for client connections.
+   */
+  public int getListenPort()
+  {
+    assert debugEnter(CLASS_NAME, "getListenPort");
+
+    return listenPort;
+  }
+
+
+
+  /**
    * Operates in a loop, accepting new connections and ensuring that requests on
    * those connections are handled properly.
    */
@@ -3013,7 +3077,7 @@
         {
           if (statTracker == null)
           {
-            statTracker = new LDAPStatistics(handlerName);
+            statTracker = new LDAPStatistics(handlerName + " Statistics");
           }
           else
           {
diff --git a/opends/src/server/org/opends/server/types/HostPort.java b/opends/src/server/org/opends/server/types/HostPort.java
new file mode 100644
index 0000000..6f1e68d
--- /dev/null
+++ b/opends/src/server/org/opends/server/types/HostPort.java
@@ -0,0 +1,143 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.server.types;
+
+
+
+import static org.opends.server.loggers.Debug.*;
+
+
+
+/**
+ * This class defines a data structure that combines an address and
+ * port number, as may be used to accept a connection from or initiate
+ * a connection to a remote system.
+ */
+public final class HostPort
+{
+  /**
+   * The fully-qualified name of this class for debugging purposes.
+   */
+  private static final String CLASS_NAME =
+       "org.opends.server.types.HostPort";
+
+
+
+  // The host for this object.
+  private String host;
+
+  // The port for this object;
+  private int port;
+
+
+
+  /**
+   * Creates a new {@code HostPort} object with the specified port
+   * number but no host.
+   *
+   * @param  port  The port number for this {@code HostPort} object.
+   */
+  public HostPort(int port)
+  {
+    assert debugConstructor(CLASS_NAME, String.valueOf(port));
+
+    this.host = null;
+    this.port = port;
+  }
+
+
+
+  /**
+   * Creates a new {@code HostPort} object with the specified port
+   * number but no explicit host.
+   *
+   * @param  host  The host address or name for this {@code HostPort}
+   *               object, or {@code null} if there is none.
+   * @param  port  The port number for this {@code HostPort} object.
+   */
+  public HostPort(String host, int port)
+  {
+    assert debugConstructor(CLASS_NAME, String.valueOf(host),
+                            String.valueOf(port));
+
+    this.host = host;
+    this.port = port;
+  }
+
+
+
+  /**
+   * Retrieves the host for this {@code HostPort} object.
+   *
+   * @return  The host for this {@code HostPort} object, or
+   *          {@code null} if none was provided.
+   */
+  public String getHost()
+  {
+    assert debugEnter(CLASS_NAME, "getHost");
+
+    return host;
+  }
+
+
+
+  /**
+   * Retrieves the port number for this {@code HostPort} object.
+   *
+   * @return  The port number for this {@code HostPort} object.
+   */
+  public int getPort()
+  {
+    assert debugEnter(CLASS_NAME, "getPort");
+
+    return port;
+  }
+
+
+
+  /**
+   * Retrieves a string representation of this {@code HostPort}
+   * object.  It will be the host element (or nothing if no host was
+   * given) followed by a colon and the port number.
+   *
+   * @return  A string representation of this {@code HostPort} object.
+   */
+  public String toString()
+  {
+    assert debugEnter(CLASS_NAME, "toString");
+
+    if (host ==  null)
+    {
+      return ":" + port;
+    }
+    else
+    {
+      return host + ":" + port;
+    }
+  }
+}
+
diff --git a/opends/src/server/org/opends/server/util/ServerConstants.java b/opends/src/server/org/opends/server/util/ServerConstants.java
index c103f85..bc74ccc 100644
--- a/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -218,6 +218,42 @@
 
 
   /**
+   * The name of the monitor attribute that is used to hold the connection
+   * handler connections.
+   */
+  public static final String ATTR_MONITOR_CONNHANDLER_CONNECTION =
+       "ds-connectionhandler-connection";
+
+
+
+  /**
+   * The name of the monitor attribute that is used to hold the connection
+   * handler listeners.
+   */
+  public static final String ATTR_MONITOR_CONNHANDLER_LISTENER =
+       "ds-connectionhandler-listener";
+
+
+
+  /**
+   * The name of the monitor attribute that is used to hold the connection
+   * handler number of established connections.
+   */
+  public static final String ATTR_MONITOR_CONNHANDLER_NUMCONNECTIONS =
+       "ds-connectionhandler-num-connections";
+
+
+
+  /**
+   * The name of the monitor attribute that is used to hold the connection
+   * handler protocol.
+   */
+  public static final String ATTR_MONITOR_CONNHANDLER_PROTOCOL =
+       "ds-connectionhandler-protocol";
+
+
+
+  /**
    * The name of the standard attribute that is used to specify the set of
    * public naming contexts (suffixes) for the Directory Server, formatted in
    * camel case.
@@ -569,6 +605,23 @@
 
 
   /**
+   * The name of the custom objectclass that will be included in backend monitor
+   * entries.
+   */
+  public static final String OC_MONITOR_BACKEND = "ds-backend-monitor-entry";
+
+
+
+  /**
+   * The name of the custom objectclass that will be included in connection
+   * handler monitor entries.
+   */
+  public static final String OC_MONITOR_CONNHANDLER =
+       "ds-connectionhandler-monitor-entry";
+
+
+
+  /**
    * The name of the objectclass that will be used as the structural class for
    * monitor entries.
    */

--
Gitblit v1.10.0