1. /*
  2. * @(#)file SnmpTableSupport.java
  3. * @(#)author Sun Microsystems, Inc.
  4. * @(#)version 1.17
  5. * @(#)date 04/09/15
  6. *
  7. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  8. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  9. */
  10. package com.sun.jmx.snmp.agent;
  11. // java imports
  12. //
  13. import java.io.Serializable;
  14. import java.util.Date;
  15. import java.util.Vector;
  16. import java.util.Enumeration;
  17. import java.util.List;
  18. import java.util.ArrayList;
  19. // jmx imports
  20. //
  21. import javax.management.Notification;
  22. import javax.management.ObjectName;
  23. import javax.management.NotificationFilter;
  24. import javax.management.NotificationListener;
  25. import javax.management.NotificationBroadcaster;
  26. import javax.management.MBeanNotificationInfo;
  27. import javax.management.ListenerNotFoundException;
  28. import com.sun.jmx.snmp.SnmpOid;
  29. import com.sun.jmx.snmp.SnmpValue;
  30. import com.sun.jmx.snmp.SnmpVarBind;
  31. import com.sun.jmx.snmp.SnmpStatusException;
  32. /**
  33. * This class is an abstraction for an SNMP table.
  34. * It is the base class for implementing SNMP tables in the
  35. * MBean world.
  36. *
  37. * <p>
  38. * Its responsibility is to synchronize the MBean view of the table
  39. * (Table of entries) with the MIB view (array of OID indexes). Each
  40. * object of this class will be bound to the Metadata object which
  41. * manages the same SNMP Table within the MIB.
  42. * </p>
  43. *
  44. * <p>
  45. * For each table defined in a MIB, mibgen will generate a specific
  46. * class called Table<i>TableName</i> that will subclass this class, and
  47. * a corresponding <i>TableName</i>Meta class extending SnmpMibTable
  48. * and corresponding to the MIB view of the same table.
  49. * </p>
  50. *
  51. * <p>
  52. * Objects of this class are instantiated by MBeans representing
  53. * the SNMP Group to which the table belong.
  54. * </p>
  55. *
  56. * <p><b>This API is a Sun Microsystems internal API and is subject
  57. * to change without notice.</b></p>
  58. * @see com.sun.jmx.snmp.agent.SnmpTableEntryFactory
  59. * @see com.sun.jmx.snmp.agent.SnmpMibTable
  60. *
  61. */
  62. public abstract class SnmpTableSupport implements SnmpTableEntryFactory,
  63. // NPCTE fix for bugId 4499265, esc 0, MR 04 sept 2001
  64. // SnmpTableCallbackHandler {
  65. SnmpTableCallbackHandler, Serializable {
  66. // end of NPCTE fix for bugId 4499265
  67. //-----------------------------------------------------------------
  68. //
  69. // Protected Variables
  70. //
  71. //-----------------------------------------------------------------
  72. /**
  73. * The list of entries
  74. **/
  75. protected List entries;
  76. /**
  77. * The associated metadata object
  78. **/
  79. protected SnmpMibTable meta;
  80. /**
  81. * The MIB to which this table belongs
  82. **/
  83. protected SnmpMib theMib;
  84. //-----------------------------------------------------------------
  85. //
  86. // Private Variables
  87. //
  88. //-----------------------------------------------------------------
  89. /**
  90. * This variable is initialized while binding this object to its
  91. * corresponding meta object.
  92. **/
  93. private boolean registrationRequired = false;
  94. //-----------------------------------------------------------------
  95. //
  96. // Constructor
  97. //
  98. //-----------------------------------------------------------------
  99. /**
  100. * Initializes the table.
  101. * The steps are these:
  102. * <ul><li> allocate an array for storing entry object,</li>
  103. * <li> retrieve the corresponding metadata object
  104. * from the MIB,
  105. * <li> bind this object to the corresponding metadata object
  106. * from the MIB.</li>
  107. * </ul>
  108. *
  109. * @param mib The MIB to which this table belong.
  110. *
  111. **/
  112. protected SnmpTableSupport(SnmpMib mib) {
  113. theMib = mib;
  114. meta = getRegisteredTableMeta(mib);
  115. bindWithTableMeta();
  116. entries = allocateTable();
  117. }
  118. //-----------------------------------------------------------------
  119. //
  120. // Implementation of the SnmpTableEntryFactory interface
  121. //
  122. //-----------------------------------------------------------------
  123. /**
  124. * Creates a new entry in the table.
  125. *
  126. * This factory method is generated by mibgen and used internally.
  127. * It is part of the
  128. * {@link com.sun.jmx.snmp.agent.SnmpTableEntryFactory} interface.
  129. * You may subclass this method to implement any specific behaviour
  130. * your application requires.
  131. *
  132. * @exception SnmpStatusException if the entry cannot be created.
  133. **/
  134. public abstract void createNewEntry(SnmpMibSubRequest request,
  135. SnmpOid rowOid, int depth,
  136. SnmpMibTable meta)
  137. throws SnmpStatusException;
  138. //-----------------------------------------------------------------
  139. //
  140. // Public methods
  141. //
  142. //-----------------------------------------------------------------
  143. /**
  144. * Returns the entry located at the given position in the table.
  145. *
  146. * @return The entry located at the given position, <code>null</code>
  147. * if no entry can be found at this position.
  148. **/
  149. // XXXX xxxx zzz ZZZZ => public? or protected?
  150. public Object getEntry(int pos) {
  151. if (entries == null) return null;
  152. return entries.get(pos);
  153. }
  154. /**
  155. * Returns the number of entries registered in the table.
  156. *
  157. * @return The number of entries registered in the table.
  158. **/
  159. public int getSize() {
  160. return meta.getSize();
  161. }
  162. /**
  163. * This method lets you dynamically switch the creation policy.
  164. *
  165. * <CODE>setCreationEnabled()</CODE> will switch the policy of
  166. * remote entry creation via SET operations, by calling
  167. * <code>setCreationEnabled()</code> on the metadata object
  168. * associated with this table.
  169. * <BR> By default remote entry creation via SET operation is disabled.
  170. *
  171. * @param remoteCreationFlag Tells whether remote entry creation must
  172. * be enabled or disabled.
  173. * <li>
  174. * <CODE>setCreationEnabled(true)</CODE> will enable remote entry
  175. * creation via SET operations.</li>
  176. * <li>
  177. * <CODE>setCreationEnabled(false)</CODE> will disable remote entry
  178. * creation via SET operations.</li>
  179. * <p> By default remote entry creation via SET operation is disabled.
  180. * </p>
  181. *
  182. * @see com.sun.jmx.snmp.agent.SnmpMibTable
  183. *
  184. **/
  185. public void setCreationEnabled(boolean remoteCreationFlag) {
  186. meta.setCreationEnabled(remoteCreationFlag);
  187. }
  188. /**
  189. * Tells whether a new entry should be created when a SET operation
  190. * is received for an entry that does not exist yet.
  191. * This method calls <code>isCreationEnabled()</code> on the metadata
  192. * object associated with this table.
  193. *
  194. * @return true if a new entry must be created, false otherwise.<br>
  195. * [default: returns <CODE>false</CODE>]
  196. *
  197. * @see com.sun.jmx.snmp.agent.SnmpMibTable
  198. **/
  199. public boolean isCreationEnabled() {
  200. return meta.isCreationEnabled();
  201. }
  202. /**
  203. * Tells whether the metadata object to which this table is linked
  204. * requires entries to be registered. In this case passing an
  205. * ObjectName when registering entries will be mandatory.
  206. *
  207. * @return <code>true</code> if the associated metadata requires entries
  208. * to be registered (mibgen generated generic metadata).
  209. **/
  210. public boolean isRegistrationRequired() {
  211. return registrationRequired;
  212. }
  213. /**
  214. * Builds an entry SnmpIndex from its row OID.
  215. *
  216. * This method is generated by mibgen and used internally.
  217. *
  218. * @param rowOid The SnmpOid object identifying a table entry.
  219. *
  220. * @return The SnmpIndex of the entry identified by <code>rowOid</code>.
  221. *
  222. * @exception SnmpStatusException if the index cannot be built from the
  223. * given OID.
  224. **/
  225. public SnmpIndex buildSnmpIndex(SnmpOid rowOid)
  226. throws SnmpStatusException {
  227. return buildSnmpIndex(rowOid.longValue(false), 0);
  228. }
  229. /**
  230. * Builds an SnmpOid from an SnmpIndex object.
  231. *
  232. * This method is generated by mibgen and used internally.
  233. *
  234. * @param index An SnmpIndex object identifying a table entry.
  235. *
  236. * @return The SnmpOid form of the given entry index.
  237. *
  238. * @exception SnmpStatusException if the given index is not valid.
  239. **/
  240. public abstract SnmpOid buildOidFromIndex(SnmpIndex index)
  241. throws SnmpStatusException;
  242. /**
  243. * Builds the default ObjectName of an entry from the SnmpIndex
  244. * identifying this entry. No access is made on the entry itself.
  245. *
  246. * This method is generated by mibgen and used internally.
  247. * You can subclass this method if you want to change the default
  248. * ObjectName policy. This is only meaningfull when entries
  249. * are registered MBeans.
  250. *
  251. * @param index The SnmpIndex identifying the entry from which we
  252. * want to build the default ObjectName.
  253. *
  254. * @return The default ObjectName for the entry identified by
  255. * the given index.
  256. *
  257. * @exception SnmpStatusException if the given index is not valid.
  258. **/
  259. public abstract ObjectName buildNameFromIndex(SnmpIndex index)
  260. throws SnmpStatusException;
  261. //-----------------------------------------------------------------
  262. //
  263. // Implementation of the SnmpTableEntryFactory interface
  264. //
  265. //-----------------------------------------------------------------
  266. /**
  267. * This callback is called by the associated metadata object
  268. * when a new table entry has been registered in the
  269. * table metadata.
  270. *
  271. * This method will update the <code>entries</code> list.
  272. *
  273. * @param pos The position at which the new entry was inserted
  274. * in the table.
  275. * @param row The row OID of the new entry
  276. * @param name The ObjectName of the new entry (as specified by the
  277. * factory)
  278. * @param entry The new entry (as returned by the factory)
  279. * @param meta The table metadata object.
  280. *
  281. **/
  282. public void addEntryCb(int pos, SnmpOid row, ObjectName name,
  283. Object entry, SnmpMibTable meta)
  284. throws SnmpStatusException {
  285. try {
  286. if (entries != null) entries.add(pos,entry);
  287. } catch (Exception e) {
  288. throw new SnmpStatusException(SnmpStatusException.noSuchName);
  289. }
  290. }
  291. /**
  292. * This callback is called by the associated metadata object
  293. * when a new table entry has been removed from the
  294. * table metadata.
  295. *
  296. * This method will update the <code>entries</code> list.
  297. *
  298. * @param pos The position from which the entry was deleted
  299. * @param row The row OID of the deleted entry
  300. * @param name The ObjectName of the deleted entry (may be null if
  301. * ObjectName's were not required)
  302. * @param entry The deleted entry (may be null if only ObjectName's
  303. * were required)
  304. * @param meta The table metadata object.
  305. *
  306. **/
  307. public void removeEntryCb(int pos, SnmpOid row, ObjectName name,
  308. Object entry, SnmpMibTable meta)
  309. throws SnmpStatusException {
  310. try {
  311. if (entries != null) entries.remove(pos);
  312. } catch (Exception e) {
  313. }
  314. }
  315. /**
  316. * Enables to add an SNMP entry listener to this
  317. * <CODE>SnmpMibTable</CODE>.
  318. *
  319. * @param listener The listener object which will handle the
  320. * notifications emitted by the registered MBean.
  321. *
  322. * @param filter The filter object. If filter is null, no filtering
  323. * will be performed before handling notifications.
  324. *
  325. * @param handback The context to be sent to the listener when a
  326. * notification is emitted.
  327. *
  328. * @exception IllegalArgumentException Listener parameter is null.
  329. */
  330. public void
  331. addNotificationListener(NotificationListener listener,
  332. NotificationFilter filter, Object handback) {
  333. meta.addNotificationListener(listener,filter,handback);
  334. }
  335. /**
  336. * Enables to remove an SNMP entry listener from this
  337. * <CODE>SnmpMibTable</CODE>.
  338. *
  339. * @param listener The listener object which will handle the
  340. * notifications emitted by the registered MBean.
  341. * This method will remove all the information related to this
  342. * listener.
  343. *
  344. * @exception ListenerNotFoundException The listener is not registered
  345. * in the MBean.
  346. */
  347. public synchronized void
  348. removeNotificationListener(NotificationListener listener)
  349. throws ListenerNotFoundException {
  350. meta.removeNotificationListener(listener);
  351. }
  352. /**
  353. * Returns a <CODE>NotificationInfo</CODE> object containing the
  354. * notification class and the notification type sent by the
  355. * <CODE>SnmpMibTable</CODE>.
  356. */
  357. public MBeanNotificationInfo[] getNotificationInfo() {
  358. return meta.getNotificationInfo();
  359. }
  360. //-----------------------------------------------------------------
  361. //
  362. // Protected Abstract methods
  363. //
  364. //-----------------------------------------------------------------
  365. /**
  366. * Builds an SnmpIndex object from the index part of an OID.
  367. *
  368. * This method is generated by mibgen and used internally.
  369. *
  370. * @param oid The OID from which to build the index, represented
  371. * as an array of long.
  372. * @param start The position where to start from in the OID array.
  373. *
  374. * @return The SnmpOid form of the given entry index.
  375. *
  376. * @exception SnmpStatusException if the given index is not valid.
  377. **/
  378. protected abstract SnmpIndex buildSnmpIndex(long oid[], int start )
  379. throws SnmpStatusException;
  380. /**
  381. * Returns the metadata object associated with this table.
  382. *
  383. * This method is generated by mibgen and used internally.
  384. *
  385. * @param mib The SnmpMib object holding the Metadata corresponding
  386. * to this table.
  387. *
  388. * @return The metadata object associated with this table.
  389. * Returns <code>null</code> if this implementation of the
  390. * MIB doesn't support this table.
  391. **/
  392. protected abstract SnmpMibTable getRegisteredTableMeta(SnmpMib mib);
  393. //-----------------------------------------------------------------
  394. //
  395. // Protected methods
  396. //
  397. //-----------------------------------------------------------------
  398. /**
  399. * Allocates an ArrayList for storing table entries.
  400. *
  401. * This method is called within the constructor at object creation.
  402. * Any object implementing the {@link java.util.List} interface can
  403. * be used.
  404. *
  405. * @return A new list in which to store entries. If <code>null</code>
  406. * is returned then no entry will be stored in the list
  407. * and getEntry() will always return null.
  408. **/
  409. protected List allocateTable() {
  410. return new ArrayList();
  411. }
  412. /**
  413. * Add an entry in this table.
  414. *
  415. * This method registers an entry in the table and perform
  416. * synchronization with the associated table metadata object.
  417. *
  418. * This method assumes that the given entry will not be registered,
  419. * or will be registered with its default ObjectName built from the
  420. * associated SnmpIndex.
  421. * <p>
  422. * If the entry is going to be registered, then
  423. * {@link com.sun.jmx.snmp.agent.SnmpTableSupport#addEntry(SnmpIndex, ObjectName, Object)} should be prefered.
  424. * <br> This function is mainly provided for backward compatibility.
  425. *
  426. * @param index The SnmpIndex built from the given entry.
  427. * @param entry The entry that should be added in the table.
  428. *
  429. * @exception SnmpStatusException if the entry cannot be registered with
  430. * the given index.
  431. **/
  432. protected void addEntry(SnmpIndex index, Object entry)
  433. throws SnmpStatusException {
  434. SnmpOid oid = buildOidFromIndex(index);
  435. ObjectName name = null;
  436. if (isRegistrationRequired()) {
  437. name = buildNameFromIndex(index);
  438. }
  439. meta.addEntry(oid,name,entry);
  440. }
  441. /**
  442. * Add an entry in this table.
  443. *
  444. * This method registers an entry in the table and performs
  445. * synchronization with the associated table metadata object.
  446. *
  447. * @param index The SnmpIndex built from the given entry.
  448. * @param name The ObjectName with which this entry will be registered.
  449. * @param entry The entry that should be added in the table.
  450. *
  451. * @exception SnmpStatusException if the entry cannot be registered with
  452. * the given index.
  453. **/
  454. protected void addEntry(SnmpIndex index, ObjectName name, Object entry)
  455. throws SnmpStatusException {
  456. SnmpOid oid = buildOidFromIndex(index);
  457. meta.addEntry(oid,name,entry);
  458. }
  459. /**
  460. * Remove an entry from this table.
  461. *
  462. * This method unregisters an entry from the table and performs
  463. * synchronization with the associated table metadata object.
  464. *
  465. * @param index The SnmpIndex identifying the entry.
  466. * @param entry The entry that should be removed in the table. This
  467. * parameter is optional and can be omitted if it doesn't
  468. * need to be passed along to the
  469. * <code>removeEntryCb()</code> callback defined in the
  470. * {@link com.sun.jmx.snmp.agent.SnmpTableCallbackHandler}
  471. * interface.
  472. *
  473. * @exception SnmpStatusException if the entry cannot be unregistered.
  474. **/
  475. protected void removeEntry(SnmpIndex index, Object entry)
  476. throws SnmpStatusException {
  477. SnmpOid oid = buildOidFromIndex(index);
  478. meta.removeEntry(oid,entry);
  479. }
  480. // protected void removeEntry(ObjectName name, Object entry)
  481. // throws SnmpStatusException {
  482. // meta.removeEntry(name,entry);
  483. // }
  484. /**
  485. * Returns the entries in the table.
  486. *
  487. * @return An Object[] array containing the entries registered in the
  488. * table.
  489. **/
  490. protected Object[] getBasicEntries() {
  491. if (entries == null) return null;
  492. Object[] array= new Object[entries.size()];
  493. entries.toArray(array);
  494. return array;
  495. }
  496. /**
  497. * Binds this table with its associated metadata, registering itself
  498. * as an SnmpTableEntryFactory.
  499. **/
  500. protected void bindWithTableMeta() {
  501. if (meta == null) return;
  502. registrationRequired = meta.isRegistrationRequired();
  503. meta.registerEntryFactory(this);
  504. }
  505. }