2570 lines · 97.3 KB · Java
RawDownload
/* * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.jmx.snmp.agent; import java.io.Serializable;import java.util.Date;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;import java.util.logging.Level; import javax.management.ListenerNotFoundException;import javax.management.MBeanNotificationInfo;import javax.management.Notification;import javax.management.NotificationBroadcaster;import javax.management.NotificationFilter;import javax.management.NotificationListener;import javax.management.ObjectName; import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;import com.sun.jmx.snmp.EnumRowStatus;import com.sun.jmx.snmp.SnmpInt;import com.sun.jmx.snmp.SnmpOid;import com.sun.jmx.snmp.SnmpStatusException;import com.sun.jmx.snmp.SnmpValue;import com.sun.jmx.snmp.SnmpVarBind; /** * This class is the base class for SNMP table metadata. * <p> * Its responsibility is to manage a sorted array of OID indexes * according to the SNMP indexing scheme over the "real" table. * Each object of this class can be bound to an * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} to which it will * forward remote entry creation requests, and invoke callbacks * when an entry has been successfully added to / removed from * the OID index array. * </p> * * <p> * For each table defined in the MIB, mibgen will generate a specific * class called Table<i>TableName</i> that will implement the * SnmpTableEntryFactory interface, and a corresponding * <i>TableName</i>Meta class that will extend this class. <br> * The Table<i>TableName</i> class corresponds to the MBean view of the * table while the <i>TableName</i>Meta class corresponds to the * MIB metadata view of the same table. * </p> * * <p> * Objects of this class are instantiated by the generated * whole MIB class extending {@link com.sun.jmx.snmp.agent.SnmpMib} * You should never need to instantiate this class directly. * </p> * * <p><b>This API is a Sun Microsystems internal API  and is subject * to change without notice.</b></p> * @see com.sun.jmx.snmp.agent.SnmpMib * @see com.sun.jmx.snmp.agent.SnmpMibEntry * @see com.sun.jmx.snmp.agent.SnmpTableEntryFactory * @see com.sun.jmx.snmp.agent.SnmpTableSupport * */ public abstract class SnmpMibTable extends SnmpMibNode    implements NotificationBroadcaster, Serializable {     /**     * Create a new <CODE>SnmpMibTable</CODE> metadata node.     *     * <p>     * @param mib The SNMP MIB to which the metadata will be linked.     */    public SnmpMibTable(SnmpMib mib) {        this.theMib= mib;        setCreationEnabled(false);    }     // -------------------------------------------------------------------    // PUBLIC METHODS    // -------------------------------------------------------------------     /**     * This method is invoked when the creation of a new entry is requested     * by a remote SNMP manager.     * <br>By default, remote entry creation is disabled - and this method     * will not be called. You can dynamically switch the entry creation     * policy by calling <code>setCreationEnabled(true)</code> and <code>     * setCreationEnabled(false)</code> on this object.     * <p><b><i>     * This method is called internally by the SNMP runtime and you     * should never need to call it directly. </b></i>However you might want     * to extend it in order to implement your own specific application     * behaviour, should the default behaviour not be at your convenience.     * </p>     * <p>     * @param req   The SNMP  subrequest requesting this creation     * @param rowOid  The OID indexing the conceptual row (entry) for which     *                the creation was requested.     * @param depth The position of the columnar object arc in the OIDs     *              from the varbind list.     *     * @exception SnmpStatusException if the entry cannot be created.     */    public abstract void createNewEntry(SnmpMibSubRequest req, SnmpOid rowOid,                                        int depth)        throws SnmpStatusException;     /**     * Tell whether the specific version of this metadata generated     * by <code>mibgen</code> requires entries to be registered with     * the MBeanServer. In this case an ObjectName will have to be     * passed to addEntry() in order for the table to behave correctly     * (case of the generic metadata).     * <p>     * If that version of the metadata does not require entry to be     * registered, then passing an ObjectName becomes optional (null     * can be passed instead).     *     * @return <code>true</code> if registration is required by this     *         version of the metadata.     */    public abstract boolean isRegistrationRequired();     /**     * Tell whether a new entry should be created when a SET operation     * is received for an entry that does not exist yet.     *     * @return true if a new entry must be created, false otherwise.<br>     *         [default: returns <CODE>false</CODE>]     **/    public boolean isCreationEnabled() {        return creationEnabled;    }     /**     * This method lets you dynamically switch the creation policy.     *     * <p>     * @param remoteCreationFlag Tells whether remote entry creation must     *        be enabled or disabled.     * <ul><li>     * <CODE>setCreationEnabled(true)</CODE> will enable remote entry     *      creation via SET operations.</li>     * <li>     * <CODE>setCreationEnabled(false)</CODE> will disable remote entry     *      creation via SET operations.</li>     * <p> By default remote entry creation via SET operation is disabled.     * </p>     * </ul>     **/    public void setCreationEnabled(boolean remoteCreationFlag) {        creationEnabled = remoteCreationFlag;    }     /**     * Return <code>true</code> if the conceptual row contains a columnar     * object used to control creation/deletion of rows in this table.     * <p>     * This  columnar object can be either a variable with RowStatus     * syntax as defined by RFC 2579, or a plain variable whose     * semantics is table specific.     * <p>     * By default, this function returns <code>false</code>, and it is     * assumed that the table has no such control variable.<br>     * When <code>mibgen</code> is used over SMIv2 MIBs, it will generate     * an <code>hasRowStatus()</code> method returning <code>true</code>     * for each table containing an object with RowStatus syntax.     * <p>     * When this method returns <code>false</code> the default mechanism     * for remote entry creation is used.     * Otherwise, creation/deletion is performed as specified     * by the control variable (see getRowAction() for more details).     * <p>     * This method is called internally when a SET request involving     * this table is processed.     * <p>     * If you need to implement a control variable which do not use     * the RowStatus convention as defined by RFC 2579, you should     * subclass the generated table metadata class in order to redefine     * this method and make it returns <code>true</code>.<br>     * You will then have to redefine the isRowStatus(), mapRowStatus(),     * isRowReady(), and setRowStatus() methods to suit your specific     * implementation.     * <p>     * @return <li><code>true</code> if this table contains a control     *         variable (eg: a variable with RFC 2579 RowStatus syntax),     *         </li>     *         <li><code>false</code> if this table does not contain     *         any control variable.</li>     *     **/    public boolean hasRowStatus() {        return false;    }     // ---------------------------------------------------------------------    //    // Implements the method defined in SnmpMibNode.    //    // ---------------------------------------------------------------------    /**     * Generic handling of the <CODE>get</CODE> operation.     * <p> The default implementation of this method is to     * <ul>     * <li> check whether the entry exists, and if not register an     *      exception for each varbind in the list.     * <li> call the generated     *      <CODE>get(req,oid,depth+1)</CODE> method. </li>     * </ul>     * <p>     * <pre>     * public void get(SnmpMibSubRequest req, int depth)     *    throws SnmpStatusException {     *    boolean         isnew  = req.isNewEntry();     *     *    // if the entry does not exists, then registers an error for     *    // each varbind involved (nb: this should not happen, since     *    // the error should already have been detected earlier)     *    //     *    if (isnew) {     *        SnmpVarBind     var = null;     *        for (Enumeration e= req.getElements(); e.hasMoreElements();) {     *            var = (SnmpVarBind) e.nextElement();     *            req.registerGetException(var,noSuchNameException);     *        }     *    }     *     *    final SnmpOid oid = req.getEntryOid();     *    get(req,oid,depth+1);     * }     * </pre>     * <p> You should not need to override this method in any cases, because     * it will eventually call     * <CODE>get(SnmpMibSubRequest req, int depth)</CODE> on the generated     * derivative of <CODE>SnmpMibEntry</CODE>. If you need to implement     * specific policies for minimizing the accesses made to some remote     * underlying resources, or if you need to implement some consistency     * checks between the different values provided in the varbind list,     * you should then rather override     * <CODE>get(SnmpMibSubRequest req, int depth)</CODE> on the generated     * derivative of <CODE>SnmpMibEntry</CODE>.     * <p>     *     */    public void get(SnmpMibSubRequest req, int depth)        throws SnmpStatusException {         final boolean         isnew  = req.isNewEntry();        final SnmpMibSubRequest  r      = req;         // if the entry does not exists, then registers an error for        // each varbind involved (nb: should not happen, the error        // should have been registered earlier)        if (isnew) {            SnmpVarBind     var = null;            for (Enumeration e= r.getElements(); e.hasMoreElements();) {                var      = (SnmpVarBind) e.nextElement();                r.registerGetException(var,noSuchInstanceException);            }        }         final SnmpOid     oid    = r.getEntryOid();         // SnmpIndex   index  = buildSnmpIndex(oid.longValue(false), 0);        // get(req,index,depth+1);        //        get(req,oid,depth+1);    }     // ---------------------------------------------------------------------    //    // Implements the method defined in SnmpMibNode.    //    // ---------------------------------------------------------------------    /**     * Generic handling of the <CODE>check</CODE> operation.     * <p> The default implementation of this method is to     * <ul>     * <li> check whether a new entry must be created, and if remote     *      creation of entries is enabled, create it. </li>     * <li> call the generated     *      <CODE>check(req,oid,depth+1)</CODE> method. </li>     * </ul>     * <p>     * <pre>     * public void check(SnmpMibSubRequest req, int depth)     *    throws SnmpStatusException {     *    final SnmpOid     oid    = req.getEntryOid();     *    final int         action = getRowAction(req,oid,depth+1);     *     *    beginRowAction(req,oid,depth+1,action);     *    check(req,oid,depth+1);     * }     * </pre>     * <p> You should not need to override this method in any cases, because     * it will eventually call     * <CODE>check(SnmpMibSubRequest req, int depth)</CODE> on the generated     * derivative of <CODE>SnmpMibEntry</CODE>. If you need to implement     * specific policies for minimizing the accesses made to some remote     * underlying resources, or if you need to implement some consistency     * checks between the different values provided in the varbind list,     * you should then rather override     * <CODE>check(SnmpMibSubRequest req, int depth)</CODE> on the generated     * derivative of <CODE>SnmpMibEntry</CODE>.     * <p>     *     */    public void check(SnmpMibSubRequest req, int depth)        throws SnmpStatusException {        final SnmpOid     oid    = req.getEntryOid();        final int         action = getRowAction(req,oid,depth+1);         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),                    "check", "Calling beginRowAction");        }         beginRowAction(req,oid,depth+1,action);         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),                    "check",                    "Calling check for " + req.getSize() + " varbinds");        }         check(req,oid,depth+1);         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),                    "check", "check finished");        }    }     // ---------------------------------------------------------------------    //    // Implements the method defined in SnmpMibNode.    //    // ---------------------------------------------------------------------    /**     * Generic handling of the <CODE>set</CODE> operation.     * <p> The default implementation of this method is to     * call the generated     * <CODE>set(req,oid,depth+1)</CODE> method.     * <p>     * <pre>     * public void set(SnmpMibSubRequest req, int depth)     *    throws SnmpStatusException {     *    final SnmpOid oid = req.getEntryOid();     *    final int  action = getRowAction(req,oid,depth+1);     *     *    set(req,oid,depth+1);     *    endRowAction(req,oid,depth+1,action);     * }     * </pre>     * <p> You should not need to override this method in any cases, because     * it will eventually call     * <CODE>set(SnmpMibSubRequest req, int depth)</CODE> on the generated     * derivative of <CODE>SnmpMibEntry</CODE>. If you need to implement     * specific policies for minimizing the accesses made to some remote     * underlying resources, or if you need to implement some consistency     * checks between the different values provided in the varbind list,     * you should then rather override     * <CODE>set(SnmpMibSubRequest req, int depth)</CODE> on the generated     * derivative of <CODE>SnmpMibEntry</CODE>.     * <p>     *     */    public void set(SnmpMibSubRequest req, int depth)        throws SnmpStatusException {          if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),                    "set", "Entering set");        }         final SnmpOid     oid    = req.getEntryOid();        final int         action = getRowAction(req,oid,depth+1);         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),                    "set", "Calling set for " + req.getSize() + " varbinds");        }         set(req,oid,depth+1);         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),                    "set", "Calling endRowAction");        }         endRowAction(req,oid,depth+1,action);         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMibTable.class.getName(),                    "set", "RowAction finished");        }     }     /**     * Add a new entry in this <CODE>SnmpMibTable</CODE>.     * Also triggers the addEntryCB() callback of the     * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface     * if this node is bound to a factory.     *     * This method assumes that the given entry will not be registered.     * If the entry is going to be registered, or if ObjectName's are     * required, then     * {@link com.sun.jmx.snmp.agent.SnmpMibTable#addEntry(SnmpOid,     * ObjectName, Object)} should be prefered.     * <br> This function is mainly provided for backward compatibility.     *     * <p>     * @param rowOid The <CODE>SnmpOid</CODE> identifying the table     *               row to be added.     * @param entry The entry to add.     *     * @exception SnmpStatusException The entry couldn't be added     *            at the position identified by the given     *            <code>rowOid</code>, or this version of the metadata     *            requires ObjectName's.     */     // public void addEntry(SnmpIndex index, Object entry)     public void addEntry(SnmpOid rowOid, Object entry)        throws SnmpStatusException {          addEntry(rowOid, null, entry);    }     /**     * Add a new entry in this <CODE>SnmpMibTable</CODE>.     * Also triggers the addEntryCB() callback of the     * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface     * if this node is bound to a factory.     *     * <p>     * @param oid    The <CODE>SnmpOid</CODE> identifying the table     *               row to be added.     *     * @param name  The ObjectName with which this entry is registered.     *              This parameter can be omitted if isRegistrationRequired()     *              return false.     *     * @param entry The entry to add.     *     * @exception SnmpStatusException The entry couldn't be added     *            at the position identified by the given     *            <code>rowOid</code>, or if this version of the metadata     *            requires ObjectName's, and the given name is null.     */    // protected synchronized void addEntry(SnmpIndex index, ObjectName name,    //                                      Object entry)    public synchronized void addEntry(SnmpOid oid, ObjectName name,                                      Object entry)        throws SnmpStatusException {         if (isRegistrationRequired() == true && name == null)            throw new SnmpStatusException(SnmpStatusException.badValue);         if (size == 0) {            //            indexes.addElement(index);            // XX oids.addElement(oid);            insertOid(0,oid);            if (entries != null)                entries.addElement(entry);            if (entrynames != null)                entrynames.addElement(name);            size++;             // triggers callbacks on the entry factory            //            if (factory != null) {                try {                    factory.addEntryCb(0,oid,name,entry,this);                } catch (SnmpStatusException x) {

Lines 1–500 of 2570.