1 /*
   2  * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package sun.management.snmp.jvminstr;
  26 
  27 // java imports
  28 //
  29 import com.sun.jmx.mbeanserver.Util;
  30 import java.util.List;
  31 import java.util.Map;
  32 
  33 // jmx imports
  34 //
  35 import javax.management.MBeanServer;
  36 import javax.management.ObjectName;
  37 import com.sun.jmx.snmp.SnmpCounter;
  38 import com.sun.jmx.snmp.SnmpCounter64;
  39 import com.sun.jmx.snmp.SnmpGauge;
  40 import com.sun.jmx.snmp.SnmpInt;
  41 import com.sun.jmx.snmp.SnmpUnsignedInt;
  42 import com.sun.jmx.snmp.SnmpIpAddress;
  43 import com.sun.jmx.snmp.SnmpTimeticks;
  44 import com.sun.jmx.snmp.SnmpOpaque;
  45 import com.sun.jmx.snmp.SnmpString;
  46 import com.sun.jmx.snmp.SnmpStringFixed;
  47 import com.sun.jmx.snmp.SnmpOid;
  48 import com.sun.jmx.snmp.SnmpNull;
  49 import com.sun.jmx.snmp.SnmpValue;
  50 import com.sun.jmx.snmp.SnmpVarBind;
  51 import com.sun.jmx.snmp.SnmpStatusException;
  52 
  53 // jdmk imports
  54 //
  55 import com.sun.jmx.snmp.agent.SnmpIndex;
  56 import com.sun.jmx.snmp.agent.SnmpMib;
  57 import com.sun.jmx.snmp.agent.SnmpMibTable;
  58 import com.sun.jmx.snmp.agent.SnmpMibSubRequest;
  59 import com.sun.jmx.snmp.agent.SnmpStandardObjectServer;
  60 
  61 import sun.management.snmp.jvmmib.JvmRTClassPathTableMeta;
  62 import sun.management.snmp.util.SnmpCachedData;
  63 import sun.management.snmp.util.SnmpTableCache;
  64 import sun.management.snmp.util.SnmpTableHandler;
  65 import sun.management.snmp.util.MibLogger;
  66 import sun.management.snmp.util.JvmContextFactory;
  67 
  68 /**
  69  * The class is used for implementing the "JvmRTClassPathTable".
  70   */
  71 public class JvmRTClassPathTableMetaImpl extends JvmRTClassPathTableMeta {
  72 
  73     static final long serialVersionUID = -6914494148818455166L;
  74 
  75     private SnmpTableCache cache;
  76 
  77      /**
  78      * A concrete implementation of {@link SnmpTableCache}, for the
  79      * JvmRTClassPathTable.
  80      **/
  81     private static class JvmRTClassPathTableCache extends SnmpTableCache {
  82         static final long serialVersionUID = 3805032372592117315L;
  83         private JvmRTClassPathTableMetaImpl meta;
  84 
  85         JvmRTClassPathTableCache(JvmRTClassPathTableMetaImpl meta,
  86                                  long validity) {
  87             this.meta = meta;
  88             this.validity = validity;
  89         }
  90 
  91         /**
  92          * Call <code>getTableDatas(JvmContextFactory.getUserData())</code>.
  93          **/
  94         public SnmpTableHandler getTableHandler() {
  95             final Map<Object, Object> userData = JvmContextFactory.getUserData();
  96             return getTableDatas(userData);
  97         }
  98 
  99 
 100         /**
 101          * Return a table handler containing the Thread indexes.
 102          * Indexes are computed from the ThreadId.
 103          **/
 104         protected SnmpCachedData updateCachedDatas(Object userData) {
 105 
 106 
 107             // We are getting all the input args
 108             final String[] path =
 109                 JvmRuntimeImpl.getClassPath(userData);
 110 
 111             // Time stamp for the cache
 112             final long time = System.currentTimeMillis();
 113             final int len = path.length;
 114 
 115             SnmpOid indexes[] = new SnmpOid[len];
 116 
 117             for(int i = 0; i < len; i++) {
 118                 indexes[i] = new SnmpOid(i + 1);
 119             }
 120 
 121             return new SnmpCachedData(time, indexes, path);
 122         }
 123     }
 124 
 125     /**
 126      * Constructor for the table. Initialize metadata for
 127      * "JvmRTClassPathTableMeta".
 128      * The reference on the MBean server is updated so the entries
 129      * created through an SNMP SET will be AUTOMATICALLY REGISTERED
 130      * in Java DMK.
 131      */
 132     public JvmRTClassPathTableMetaImpl(SnmpMib myMib,
 133                                        SnmpStandardObjectServer objserv) {
 134         super(myMib, objserv);
 135         cache = new JvmRTClassPathTableCache(this, -1);
 136     }
 137 
 138     // See com.sun.jmx.snmp.agent.SnmpMibTable
 139     protected SnmpOid getNextOid(Object userData)
 140         throws SnmpStatusException {
 141         // null means get the first OID.
 142         return getNextOid(null,userData);
 143     }
 144 
 145     // See com.sun.jmx.snmp.agent.SnmpMibTable
 146     protected SnmpOid getNextOid(SnmpOid oid, Object userData)
 147         throws SnmpStatusException {
 148         final boolean dbg = log.isDebugOn();
 149         if (dbg) log.debug("getNextOid", "previous=" + oid);
 150 
 151 
 152         // Get the data handler.
 153         //
 154         SnmpTableHandler handler = getHandler(userData);
 155         if (handler == null) {
 156             // This should never happen.
 157             // If we get here it's a bug.
 158             //
 159             if (dbg) log.debug("getNextOid", "handler is null!");
 160             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 161         }
 162 
 163         // Get the next oid
 164         //
 165         final SnmpOid next = handler.getNext(oid);
 166         if (dbg) log.debug("*** **** **** **** getNextOid", "next=" + next);
 167 
 168         // if next is null: we reached the end of the table.
 169         //
 170         if (next == null)
 171             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 172 
 173         return next;
 174     }
 175 
 176 
 177     // See com.sun.jmx.snmp.agent.SnmpMibTable
 178     protected boolean contains(SnmpOid oid, Object userData) {
 179 
 180         // Get the handler.
 181         //
 182         SnmpTableHandler handler = getHandler(userData);
 183 
 184         // handler should never be null.
 185         //
 186         if (handler == null)
 187             return false;
 188 
 189         return handler.contains(oid);
 190     }
 191 
 192     // See com.sun.jmx.snmp.agent.SnmpMibTable
 193     public Object getEntry(SnmpOid oid)
 194         throws SnmpStatusException {
 195         final boolean dbg = log.isDebugOn();
 196         if (dbg) log.debug("getEntry", "oid [" + oid + "]");
 197         if (oid == null || oid.getLength() != 1) {
 198             if (dbg) log.debug("getEntry", "Invalid oid [" + oid + "]");
 199             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 200         }
 201 
 202         // Get the request contextual cache (userData).
 203         //
 204         final Map<Object, Object> m = JvmContextFactory.getUserData();
 205 
 206         // We're going to use this name to store/retrieve the entry in
 207         // the request contextual cache.
 208         //
 209         // Revisit: Probably better programming to put all these strings
 210         //          in some interface.
 211         //
 212         final String entryTag = ((m==null)?null:
 213                                  ("JvmRTClassPathTable.entry." +
 214                                   oid.toString()));
 215 
 216         // If the entry is in the cache, simply return it.
 217         //
 218         if (m != null) {
 219             final Object entry = m.get(entryTag);
 220             if (entry != null) {
 221                 if (dbg)
 222                     log.debug("getEntry", "Entry is already in the cache");
 223                 return entry;
 224             } else
 225                 if (dbg) log.debug("getEntry", "Entry is not in the cache");
 226         }
 227 
 228         // The entry was not in the cache, make a new one.
 229         //
 230         // Get the data hanler.
 231         //
 232         SnmpTableHandler handler = getHandler(m);
 233 
 234         // handler should never be null.
 235         //
 236         if (handler == null)
 237             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 238 
 239         // Get the data associated with our entry.
 240         //
 241         final Object data = handler.getData(oid);
 242 
 243         // data may be null if the OID we were given is not valid.
 244         //
 245         if (data == null)
 246             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 247 
 248         // make the new entry (transient object that will be kept only
 249         // for the duration of the request.
 250         //
 251         if (dbg)
 252             log.debug("getEntry","data is a: " + data.getClass().getName());
 253         final Object entry =
 254             new JvmRTClassPathEntryImpl((String) data, (int) oid.getOidArc(0));
 255 
 256         // Put the entry in the cache in case we need it later while processing
 257         // the request.
 258         //
 259         if (m != null && entry != null) {
 260             m.put(entryTag,entry);
 261         }
 262 
 263         return entry;
 264     }
 265 
 266     /**
 267      * Get the SnmpTableHandler that holds the jvmThreadInstanceTable data.
 268      * First look it up in the request contextual cache, and if it is
 269      * not found, obtain it from the weak cache.
 270      * <br>The request contextual cache will be released at the end of the
 271      * current requests, and is used only to process this request.
 272      * <br>The weak cache is shared by all requests, and is only
 273      * recomputed when it is found to be obsolete.
 274      * <br>Note that the data put in the request contextual cache is
 275      *     never considered to be obsolete, in order to preserve data
 276      *     coherency.
 277      **/
 278     protected SnmpTableHandler getHandler(Object userData) {
 279         final Map<Object, Object> m;
 280         if (userData instanceof Map) m=Util.cast(userData);
 281         else m=null;
 282 
 283         // Look in the contextual cache.
 284         if (m != null) {
 285             final SnmpTableHandler handler =
 286                 (SnmpTableHandler)m.get("JvmRTClassPathTable.handler");
 287             if (handler != null) return handler;
 288         }
 289 
 290         // No handler in contextual cache, make a new one.
 291         final SnmpTableHandler handler = cache.getTableHandler();
 292 
 293         if (m != null && handler != null )
 294             m.put("JvmRTClassPathTable.handler",handler);
 295 
 296         return handler;
 297     }
 298 
 299     static final MibLogger log =
 300         new MibLogger(JvmRTClassPathTableMetaImpl.class);
 301 }