/* * 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 * * * Copyright 2008-2009 Sun Microsystems, Inc. * Portions Copyright 2012 ForgeRock Inc. */ package org.opends.server.snmp; import javax.management.MBeanServer; import com.sun.management.snmp.agent.SnmpMib; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Set; import javax.management.MBeanServerNotification; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.ObjectName; import org.opends.server.loggers.debug.DebugLogger; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.types.DebugLogLevel; /** * The class represents the "DsMIB" group implementation. * The group is defined with the following oid: 1.3.6.1.2.1.66. */ public class DsMIBImpl extends DsMIB implements NotificationListener { /** * The serial version identifier required to satisfy the compiler because * this class implements the <CODE>java.io.Serializable</CODE> interface. * This value was generated using the <CODE>serialver</CODE> command-line * utility included with the Java SDK. */ private static final long serialVersionUID = 6787374593664749374L; /** * The debug log tracer for this class. */ private static final DebugTracer TRACER = DebugLogger.getTracer(); /** * Directory Server MIB access. */ private SnmpMib mib; /** * Register or not the SNMP MBean. */ private boolean registeredSnmpMBean = false; /** * List of DsTableEntries. * SNMP dsTable contains the list of Directory Servers */ private Hashtable<ObjectName, DsEntry> dsTableEntries = new Hashtable<ObjectName, DsEntry>(); /** * List of DsApplIfOpsTableEntries. * SNMP dsAppIfOpsTable provides summary statistics on the accesses * operations and errors for each application protocol interface * of a Directory Server */ private Hashtable<ObjectName, DsEntry> dsApplIfOpsTableEntries = new Hashtable<ObjectName, DsEntry>(); /** * List of DsIntTableEntries. * SNMP dsIntTable provides some useful information on the * interactions of the monitored DS with peer DS */ private Hashtable<ObjectName, DsEntry> dsIntTableEntries = new Hashtable<ObjectName, DsEntry>(); /** * Directory Server MBeanServer. */ private MBeanServer server; /** * cn=monitor Mapping Class SNMP->MBean. */ private SNMPMonitor monitor; /** * Start Table indexes. */ private int applIndex = 1; private int applIfOpsIndex = 1; private int intIndex = 1; /** * Constructor for the "DsMIB" group. * If the group contains a table, the entries created through an SNMP SET * will not be registered in Java DMK. * @param myMib snmp mib * @param server where the MBeans are registered * @param registered if the MBeans should be registered in server */ public DsMIBImpl(SnmpMib myMib, MBeanServer server, boolean registered) { super(myMib); this.mib = myMib; this.server = server; this.monitor = SNMPMonitor.getMonitor(server); this.registeredSnmpMBean = registered; this.dsTableEntries.clear(); this.dsApplIfOpsTableEntries.clear(); this.dsIntTableEntries.clear(); // Initialize the MIB initDsTables(); if (DebugLogger.debugEnabled()) { TRACER.debugVerbose("DsMIB Group Created"); } } /** * Returns the Set of ObjectName of all the created entries in all the Table. * @return The Set of ObjectName */ @SuppressWarnings("unchecked") public Set<ObjectName> getEntriesObjectNames() { Set<ObjectName> results = new HashSet<ObjectName>(); results.addAll(this.dsTableEntries.keySet()); results.addAll(this.dsApplIfOpsTableEntries.keySet()); results.addAll(this.dsIntTableEntries.keySet()); return results; } /** * Returns the list of Created Entries. * @return Set of created entries */ @SuppressWarnings("unchecked") public Set<ObjectName> getEntries() { Set results = new HashSet(); results.addAll(this.dsTableEntries.values()); results.addAll(this.dsApplIfOpsTableEntries.values()); results.addAll(this.dsIntTableEntries.values()); return results; } /** * handleNotification callback called when an MBeansServer Notification is * received. * @param notification received * @param handback The handback */ public void handleNotification(Notification notification, Object handback) { if (notification instanceof MBeanServerNotification) { MBeanServerNotification notif = (MBeanServerNotification) notification; // Process the ConnectionHandler Registration if (notif.getType().equals( MBeanServerNotification.REGISTRATION_NOTIFICATION)) { ObjectName name = notif.getMBeanName(); if ((name.getKeyProperty("Rdn1").equals("cn-monitor")) && (isAConnectionHandler(name))) { addRowInDsApplIfOpsTable(name); } } // Process the ConnectionHandler unregistration else if (notif.getType().equals( MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) { ObjectName name = notif.getMBeanName(); if ((name.getKeyProperty("Rdn1").equals("cn-monitor")) && (isAConnectionHandler(name))) { removeRowInDsApplIfOpsTable(name); } } } } /** * initDsTables in the dsMib Group. */ private void initDsTables() { // Initialize the DSTable with one Entry : Current Directory Server initializeDsTable(); // Initialize the DsApplIfOpsTable with one entry per Connection Handler. initializeDsApplIfOpsTable(); // Register as listener of the MBeanServer Notification to process // new Connection Handler MBeans try { ObjectName name = new ObjectName( "JMImplementation:type=MBeanServerDelegate"); this.server.addNotificationListener(name, this, null, null); } catch (Exception ex) { if (DebugLogger.debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ex); } } } /** * initializeDsTable with the current Directory server instance. * Only one entry is created in this table **/ private void initializeDsTable() { // Add the Current Directory Server Instance in the DsTable addRowInDsTable(); } /** * initializeDsApplIfOpsTable with the already registered Connection * Handlers. **/ private void initializeDsApplIfOpsTable() { // Get the list of ConnectionHandlers MBeans Set connectionHandlers = this.monitor.getConnectionHandlers(); for (Iterator iter=connectionHandlers.iterator();iter.hasNext();) { ObjectName name = (ObjectName)iter.next(); // Add the ConnectionHandler in the DsApplIfOpsTable addRowInDsApplIfOpsTable(name); } } /** * addRowInDsTable. * @return true if the entry has been added else false */ private boolean addRowInDsTable() { try { // Create the entry DsTableEntryImpl entry = new DsTableEntryImpl( this.mib, this.server, this.applIndex); // if the entry already exists nothing to do if ((this.dsTableEntries.containsKey(entry.getObjectName())) || (entry == null)) { return true; } // Add the entry in the table this.DsTable.addEntry(entry, entry.getObjectName()); this.dsTableEntries.put(entry.getObjectName(), (DsEntry)entry); if (this.registeredSnmpMBean) { // Register the SNMP OID MBean this.server.registerMBean(entry, entry.getObjectName()); } } catch (Exception ex) { if (DebugLogger.debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ex); } return false; } return true; } /** * addRowInDsIntTable Not Supported. * @return false (Not Supported for this current delivery) */ private boolean addRowInDsIntTable() { return false; } /** * addRowInDsApplIfOpsTable. * @param connectionHandlerName to add * @return true if the entry has been added else false */ private boolean addRowInDsApplIfOpsTable(ObjectName connectionHandlerName) { try { // Created the entry DsApplIfOpsEntryImpl entry = new DsApplIfOpsEntryImpl( this.mib, this.server, connectionHandlerName, this.applIndex, this.applIfOpsIndex); // If the entry already exists then nothing to do if ((this.dsApplIfOpsTableEntries.containsKey(entry.getObjectName())) || (entry == null)) { return true; } // Add the entry in the Table this.DsApplIfOpsTable.addEntry(entry); this.dsApplIfOpsTableEntries.put(entry.getObjectName(), entry); this.applIfOpsIndex++; if (this.registeredSnmpMBean) { // Register the SNMP OID MBean in the MBeanServer this.server.registerMBean(entry, entry.getObjectName()); } } catch (Exception ex) { if (DebugLogger.debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ex); } return false; } return true; } /** * removeRowInDsApplIfOpsTable. * @param connectionHandlerName * @return true if the entry has been removed else false */ private boolean removeRowInDsApplIfOpsTable(ObjectName connectionHandlerName){ try { // Check if the entry is known if (!this.dsApplIfOpsTableEntries.containsKey(connectionHandlerName)) { return false; } DsApplIfOpsEntryImpl entry = (DsApplIfOpsEntryImpl) this.dsApplIfOpsTableEntries.get(connectionHandlerName); this.DsApplIfOpsTable.removeEntry((DsApplIfOpsEntryMBean) entry); this.dsApplIfOpsTableEntries.remove(connectionHandlerName); this.server.unregisterMBean(entry.getObjectName()); return true; } catch (Exception ex) { return false; } } /** * isAConnectionHandler allows to check if the Mbean is a Connection Handler. * @param name of the MBean * @return true if the MBean is a Connection Handler else false */ private boolean isAConnectionHandler(ObjectName name) { // First level String Rdn2 = name.getKeyProperty("Rdn2"); // Second level String Rdn3 = name.getKeyProperty("Rdn3"); if ((Rdn3==null) || (Rdn3.length()==0)) { if ((Rdn2.contains("Connection_Handler")) && (!(Rdn2.endsWith("_Statistics")))) { return true; } } return false; } }