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.JvmRTLibraryPathTableMeta;
  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 "JvmRTLibraryPathTable".
  70   */
  71 public class JvmRTLibraryPathTableMetaImpl extends JvmRTLibraryPathTableMeta {
  72 
  73     static final long serialVersionUID = 6713252710712502068L;
  74     private SnmpTableCache cache;
  75 
  76      /**
  77      * A concrete implementation of {@link SnmpTableCache}, for the
  78      * JvmRTLibraryPathTable.
  79      **/
  80     private static class JvmRTLibraryPathTableCache extends SnmpTableCache {
  81         static final long serialVersionUID = 2035304445719393195L;
  82         private JvmRTLibraryPathTableMetaImpl meta;
  83 
  84         JvmRTLibraryPathTableCache(JvmRTLibraryPathTableMetaImpl meta,
  85                                  long validity) {
  86             this.meta = meta;
  87             this.validity = validity;
  88         }
  89 
  90         /**
  91          * Call <code>getTableDatas(JvmContextFactory.getUserData())</code>.
  92          **/
  93         public SnmpTableHandler getTableHandler() {
  94             final Map<Object,Object> userData = JvmContextFactory.getUserData();
  95             return getTableDatas(userData);
  96         }
  97 
  98 
  99         /**
 100          * Return a table handler containing the Thread indexes.
 101          * Indexes are computed from the ThreadId.
 102          **/
 103         protected SnmpCachedData updateCachedDatas(Object userData) {
 104 
 105 
 106             // We are getting all the input args
 107             final String[] path =
 108                 JvmRuntimeImpl.getLibraryPath(userData);
 109 
 110             // Time stamp for the cache
 111             final long time = System.currentTimeMillis();
 112             final int len = path.length;
 113 
 114             SnmpOid indexes[] = new SnmpOid[len];
 115 
 116             for(int i = 0; i < len; i++) {
 117                 indexes[i] = new SnmpOid(i + 1);
 118             }
 119 
 120             return new SnmpCachedData(time, indexes, path);
 121         }
 122     }
 123 
 124     /**
 125      * Constructor for the table. Initialize metadata for
 126      * "JvmRTLibraryPathTableMeta".
 127      * The reference on the MBean server is updated so the entries
 128      * created through an SNMP SET will be AUTOMATICALLY REGISTERED
 129      * in Java DMK.
 130      */
 131     public JvmRTLibraryPathTableMetaImpl(SnmpMib myMib,
 132                                        SnmpStandardObjectServer objserv) {
 133         super(myMib, objserv);
 134         cache = new JvmRTLibraryPathTableCache(this, -1);
 135     }
 136 
 137     // See com.sun.jmx.snmp.agent.SnmpMibTable
 138     protected SnmpOid getNextOid(Object userData)
 139         throws SnmpStatusException {
 140         // null means get the first OID.
 141         return getNextOid(null,userData);
 142     }
 143 
 144     // See com.sun.jmx.snmp.agent.SnmpMibTable
 145     protected SnmpOid getNextOid(SnmpOid oid, Object userData)
 146         throws SnmpStatusException {
 147         final boolean dbg = log.isDebugOn();
 148         if (dbg) log.debug("getNextOid", "previous=" + oid);
 149 
 150 
 151         // Get the data handler.
 152         //
 153         SnmpTableHandler handler = getHandler(userData);
 154         if (handler == null) {
 155             // This should never happen.
 156             // If we get here it's a bug.
 157             //
 158             if (dbg) log.debug("getNextOid", "handler is null!");
 159             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 160         }
 161 
 162         // Get the next oid
 163         //
 164         final SnmpOid next = handler.getNext(oid);
 165         if (dbg) log.debug("*** **** **** **** getNextOid", "next=" + next);
 166 
 167         // if next is null: we reached the end of the table.
 168         //
 169         if (next == null)
 170             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 171 
 172         return next;
 173     }
 174 
 175 
 176     // See com.sun.jmx.snmp.agent.SnmpMibTable
 177     protected boolean contains(SnmpOid oid, Object userData) {
 178 
 179         // Get the handler.
 180         //
 181         SnmpTableHandler handler = getHandler(userData);
 182 
 183         // handler should never be null.
 184         //
 185         if (handler == null)
 186             return false;
 187 
 188         return handler.contains(oid);
 189     }
 190 
 191     // See com.sun.jmx.snmp.agent.SnmpMibTable
 192     public Object getEntry(SnmpOid oid)
 193         throws SnmpStatusException {
 194         final boolean dbg = log.isDebugOn();
 195         if (dbg) log.debug("getEntry", "oid [" + oid + "]");
 196         if (oid == null || oid.getLength() != 1) {
 197             if (dbg) log.debug("getEntry", "Invalid oid [" + oid + "]");
 198             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 199         }
 200 
 201         // Get the request contextual cache (userData).
 202         //
 203         final Map<Object, Object> m = JvmContextFactory.getUserData();
 204 
 205         // We're going to use this name to store/retrieve the entry in
 206         // the request contextual cache.
 207         //
 208         // Revisit: Probably better programming to put all these strings
 209         //          in some interface.
 210         //
 211         final String entryTag = ((m==null)?null:
 212                                  ("JvmRTLibraryPathTable.entry." +
 213                                   oid.toString()));
 214 
 215         // If the entry is in the cache, simply return it.
 216         //
 217         if (m != null) {
 218             final Object entry = m.get(entryTag);
 219             if (entry != null) {
 220                 if (dbg)
 221                     log.debug("getEntry", "Entry is already in the cache");
 222                 return entry;
 223             } else if (dbg) log.debug("getEntry", "Entry is not in the cache");
 224 
 225         }
 226 
 227         // The entry was not in the cache, make a new one.
 228         //
 229         // Get the data hanler.
 230         //
 231         SnmpTableHandler handler = getHandler(m);
 232 
 233         // handler should never be null.
 234         //
 235         if (handler == null)
 236             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 237 
 238         // Get the data associated with our entry.
 239         //
 240         final Object data = handler.getData(oid);
 241 
 242         // data may be null if the OID we were given is not valid.
 243         //
 244         if (data == null)
 245             throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
 246 
 247         // make the new entry (transient object that will be kept only
 248         // for the duration of the request.
 249         //
 250         if (dbg) log.debug("getEntry","data is a: "+
 251                            data.getClass().getName());
 252         final Object entry =
 253             new JvmRTLibraryPathEntryImpl((String) data,(int)oid.getOidArc(0));
 254 
 255         // Put the entry in the cache in case we need it later while processing
 256         // the request.
 257         //
 258         if (m != null && entry != null) {
 259             m.put(entryTag,entry);
 260         }
 261 
 262         return entry;
 263     }
 264 
 265     /**
 266      * Get the SnmpTableHandler that holds the jvmThreadInstanceTable data.
 267      * First look it up in the request contextual cache, and if it is
 268      * not found, obtain it from the weak cache.
 269      * <br>The request contextual cache will be released at the end of the
 270      * current requests, and is used only to process this request.
 271      * <br>The weak cache is shared by all requests, and is only
 272      * recomputed when it is found to be obsolete.
 273      * <br>Note that the data put in the request contextual cache is
 274      *     never considered to be obsolete, in order to preserve data
 275      *     coherency.
 276      **/
 277     protected SnmpTableHandler getHandler(Object userData) {
 278         final Map<Object, Object> m;
 279         if (userData instanceof Map) m=Util.cast(userData);
 280         else m=null;
 281 
 282         // Look in the contextual cache.
 283         if (m != null) {
 284             final SnmpTableHandler handler =
 285                 (SnmpTableHandler)m.get("JvmRTLibraryPathTable.handler");
 286             if (handler != null) return handler;
 287         }
 288 
 289         // No handler in contextual cache, make a new one.
 290         final SnmpTableHandler handler = cache.getTableHandler();
 291 
 292         if (m != null && handler != null )
 293             m.put("JvmRTLibraryPathTable.handler",handler);
 294 
 295         return handler;
 296     }
 297 
 298     static final MibLogger log =
 299         new MibLogger(JvmRTLibraryPathTableMetaImpl.class);
 300 }