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