1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright (c) 2001 by Sun Microsystems, Inc.
  24  * All rights reserved.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <assert.h>
  30 #include <synch.h>
  31 #include <jni.h>
  32 
  33 #include "class_cache.h"
  34 
  35 /*
  36  * Only certain classes are deemed worthy of caching. These be them.
  37  */
  38 #define DCR_NAME                "com/sun/dhcpmgr/data/DhcpClientRecord"
  39 #define DTR_NAME                "com/sun/dhcpmgr/data/DhcptabRecord"
  40 #define NET_NAME                "com/sun/dhcpmgr/data/Network"
  41 #define MAC_NAME                "com/sun/dhcpmgr/data/Macro"
  42 #define OPT_NAME                "com/sun/dhcpmgr/data/Option"
  43 #define DS_NAME                 "com/sun/dhcpmgr/data/DhcpDatastore"
  44 #define CFG_NAME                "com/sun/dhcpmgr/data/DhcpdOptions"
  45 #define RES_NAME                "com/sun/dhcpmgr/data/DhcpResource"
  46 #define IP_NAME                 "com/sun/dhcpmgr/data/IPAddress"
  47 #define IPIF_NAME               "com/sun/dhcpmgr/data/IPInterface"
  48 
  49 /*
  50  * As with classes, only certain methods are cached.
  51  */
  52 #define DCR_CONS_NAME           "<init>"
  53 #define DCR_GETCID_NAME         "getClientId"
  54 #define DCR_GETFLAG_NAME        "getFlagString"
  55 #define DCR_GETCIP_NAME         "getClientIPAddress"
  56 #define DCR_GETSIP_NAME         "getServerIPAddress"
  57 #define DCR_GETEXP_NAME         "getExpirationTime"
  58 #define DCR_GETSIG_NAME         "getSignature"
  59 #define DCR_GETMAC_NAME         "getMacro"
  60 #define DCR_GETCMT_NAME         "getComment"
  61 #define DTR_GETKEY_NAME         "getKey"
  62 #define DTR_GETFLAG_NAME        "getFlag"
  63 #define DTR_GETSIG_NAME         "getSignature"
  64 #define DTR_GETVAL_NAME         "getValue"
  65 #define NET_CONS_NAME           "<init>"
  66 #define MAC_CONS_NAME           "<init>"
  67 #define OPT_CONS_NAME           "<init>"
  68 #define DS_CONS_NAME            "<init>"
  69 #define DS_GETRSRC_NAME         "getResource"
  70 #define DS_GETLOC_NAME          "getLocation"
  71 #define DS_GETRSRCCFG_NAME      "getConfig"
  72 #define DS_GETVER_NAME          "getVersion"
  73 #define CFG_CONS_NAME           "<init>"
  74 #define CFG_SET_NAME            "set"
  75 #define CFG_GETALL_NAME         "getAll"
  76 #define RES_GETKEY_NAME         "getKey"
  77 #define RES_GETVAL_NAME         "getValue"
  78 #define RES_ISCOM_NAME          "isComment"
  79 #define IP_CONS_NAME            "<init>"
  80 #define IPIF_CONS_NAME          "<init>"
  81 
  82 /*
  83  * Signatures for the methods can be found below.
  84  */
  85 #define DCR_CONS_SIG            "(Ljava/lang/String;Ljava/lang/String;"\
  86                                 "Ljava/lang/String;Ljava/lang/String;"\
  87                                 "Ljava/lang/String;Ljava/lang/String;"\
  88                                 "Ljava/lang/String;Ljava/lang/String;)V"
  89 
  90 #define DCR_GETCID_SIG          "()Ljava/lang/String;"
  91 #define DCR_GETFLAG_SIG         "()Ljava/lang/String;"
  92 #define DCR_GETCIP_SIG          "()Ljava/lang/String;"
  93 #define DCR_GETSIP_SIG          "()Ljava/lang/String;"
  94 #define DCR_GETEXP_SIG          "()Ljava/lang/String;"
  95 #define DCR_GETSIG_SIG          "()Ljava/lang/String;"
  96 #define DCR_GETMAC_SIG          "()Ljava/lang/String;"
  97 #define DCR_GETCMT_SIG          "()Ljava/lang/String;"
  98 #define DTR_GETKEY_SIG          "()Ljava/lang/String;"
  99 #define DTR_GETFLAG_SIG         "()Ljava/lang/String;"
 100 #define DTR_GETSIG_SIG          "()Ljava/lang/String;"
 101 #define DTR_GETVAL_SIG          "()Ljava/lang/String;"
 102 #define NET_CONS_SIG            "(Ljava/lang/String;I)V"
 103 #define MAC_CONS_SIG            "(Ljava/lang/String;Ljava/lang/String;"\
 104                                 "Ljava/lang/String;)V"
 105 #define OPT_CONS_SIG            "(Ljava/lang/String;B[Ljava/lang/String;"\
 106                                 "SBIILjava/lang/String;Z)V"
 107 #define DS_CONS_SIG             "(Ljava/lang/String;IZ)V"
 108 #define DS_GETRSRC_SIG          "()Ljava/lang/String;"
 109 #define DS_GETLOC_SIG           "()Ljava/lang/String;"
 110 #define DS_GETRSRCCFG_SIG       "()Ljava/lang/String;"
 111 #define DS_GETVER_SIG           "()I"
 112 #define CFG_CONS_SIG            "()V"
 113 #define CFG_SET_SIG             "(Ljava/lang/String;Ljava/lang/String;Z)V"
 114 #define CFG_GETALL_SIG          "()[Ljava/lang/Object;"
 115 #define RES_GETKEY_SIG          "()Ljava/lang/String;"
 116 #define RES_GETVAL_SIG          "()Ljava/lang/String;"
 117 #define RES_ISCOM_SIG           "()Z"
 118 #define IP_CONS_SIG             "(Ljava/lang/String;)V"
 119 #define IPIF_CONS_SIG           "(Ljava/lang/String;Ljava/lang/String;"\
 120                                 "Ljava/lang/String;)V"
 121 /*
 122  * Class map.
 123  */
 124 typedef struct {
 125         jclass          cl_class;
 126         char            *cl_name;
 127 } cl_map_t;
 128 
 129 /*
 130  * Note that the order of the entries in this table must match
 131  * exactly with the CC_CLASSMAP_ID enumeration in class_cache.h.
 132  */
 133 static cl_map_t classMap[] = {
 134         { NULL, DCR_NAME },     /* DCR_CLASS */
 135         { NULL, DTR_NAME },     /* DTR_CLASS */
 136         { NULL, NET_NAME },     /* NET_CLASS */
 137         { NULL, MAC_NAME },     /* MAC_CLASS */
 138         { NULL, OPT_NAME },     /* OPT_CLASS */
 139         { NULL, DS_NAME },      /* DS_CLASS */
 140         { NULL, CFG_NAME },     /* CFG_CLASS */
 141         { NULL, RES_NAME },     /* RES_CLASS */
 142         { NULL, IP_NAME },      /* IP_CLASS */
 143         { NULL, IPIF_NAME }     /* IPIF_CLASS */
 144 };
 145 
 146 /*
 147  * Method ID map.
 148  */
 149 typedef struct {
 150         jmethodID       mi_methodID;
 151         char            *mi_name;
 152         char            *mi_signature;
 153 } mi_map_t;
 154 
 155 /*
 156  * Note that the order of the entries in this table must match
 157  * exactly with the CC_METHODMAP_ID enumeration in class_cache.h.
 158  */
 159 static mi_map_t methodIDMap[] = {
 160         { NULL, DCR_CONS_NAME, DCR_CONS_SIG },          /* DCR_CONS */
 161         { NULL, DCR_GETCID_NAME, DCR_GETCID_SIG },      /* DCR_GETCID */
 162         { NULL, DCR_GETFLAG_NAME, DCR_GETFLAG_SIG },    /* DCR_GETFLAG */
 163         { NULL, DCR_GETCIP_NAME, DCR_GETCIP_SIG },      /* DCR_GETCIP */
 164         { NULL, DCR_GETSIP_NAME, DCR_GETSIP_SIG },      /* DCR_GETSIP */
 165         { NULL, DCR_GETEXP_NAME, DCR_GETEXP_SIG },      /* DCR_GETEXP */
 166         { NULL, DCR_GETSIG_NAME, DCR_GETSIG_SIG },      /* DCR_GETSIG */
 167         { NULL, DCR_GETMAC_NAME, DCR_GETMAC_SIG },      /* DCR_GETMAC */
 168         { NULL, DCR_GETCMT_NAME, DCR_GETCMT_SIG },      /* DCR_GETCMT */
 169         { NULL, DTR_GETKEY_NAME, DTR_GETKEY_SIG },      /* DTR_GETKEY */
 170         { NULL, DTR_GETFLAG_NAME, DTR_GETFLAG_SIG },    /* DTR_GETFLAG */
 171         { NULL, DTR_GETSIG_NAME, DTR_GETSIG_SIG },      /* DTR_GETSIG */
 172         { NULL, DTR_GETVAL_NAME, DTR_GETVAL_SIG },      /* DTR_GETVAL */
 173         { NULL, NET_CONS_NAME, NET_CONS_SIG },          /* NET_CONS */
 174         { NULL, MAC_CONS_NAME, MAC_CONS_SIG },          /* MAC_CONS */
 175         { NULL, OPT_CONS_NAME, OPT_CONS_SIG },          /* OPT_CONS */
 176         { NULL, DS_CONS_NAME, DS_CONS_SIG },            /* DS_CONS */
 177         { NULL, DS_GETRSRC_NAME, DS_GETRSRC_SIG },      /* DS_GETRSRC */
 178         { NULL, DS_GETLOC_NAME, DS_GETLOC_SIG },        /* DS_GETLOC */
 179         { NULL, DS_GETRSRCCFG_NAME, DS_GETRSRCCFG_SIG }, /* DS_GETRSRCCFG */
 180         { NULL, DS_GETVER_NAME, DS_GETVER_SIG },        /* DS_GETVER */
 181         { NULL, CFG_CONS_NAME, CFG_CONS_SIG },          /* CFG_CONS */
 182         { NULL, CFG_SET_NAME, CFG_SET_SIG },            /* CFG_SET */
 183         { NULL, CFG_GETALL_NAME, CFG_GETALL_SIG },      /* CFG_GETALL */
 184         { NULL, RES_GETKEY_NAME, RES_GETKEY_SIG },      /* RES_GETKEY */
 185         { NULL, RES_GETVAL_NAME, RES_GETVAL_SIG },      /* RES_GETVAL */
 186         { NULL, RES_ISCOM_NAME, RES_ISCOM_SIG },        /* RES_ISCOM */
 187         { NULL, IP_CONS_NAME, IP_CONS_SIG },            /* IP_CONS */
 188         { NULL, IPIF_CONS_NAME, IPIF_CONS_SIG }         /* IPIF_CONS */
 189 };
 190 
 191 /*
 192  * The locks to protect the class and method maps.
 193  */
 194 static mutex_t cmap_lock;
 195 static mutex_t mmap_lock;
 196 
 197 void
 198 init_class_cache(void) {
 199         (void) mutex_init(&cmap_lock, USYNC_THREAD, NULL);
 200         (void) mutex_init(&mmap_lock, USYNC_THREAD, NULL);
 201 }
 202 
 203 /*
 204  * Get a dhcpmgr class from the cache.
 205  */
 206 jclass
 207 find_class(JNIEnv *env, CC_CLASSMAP_ID id) {
 208 
 209         jclass *class;
 210 
 211         assert(id >= 0 && id <= CC_CLASSMAP_NUM);
 212 
 213         /*
 214          * If the class has not been cached yet, go find it and cache it.
 215          */
 216         class = &classMap[id].cl_class;
 217         if (*class == NULL) {
 218                 /*
 219                  * Check again with the lock held this time.
 220                  */
 221                 (void) mutex_lock(&cmap_lock);
 222                 if (*class == NULL) {
 223                         char *name = classMap[id].cl_name;
 224                         jclass local = (*env)->FindClass(env, name);
 225                         if (local != NULL) {
 226                                 *class = (*env)->NewGlobalRef(env, local);
 227                                 (*env)->DeleteLocalRef(env, local);
 228                         }
 229                 }
 230                 (void) mutex_unlock(&cmap_lock);
 231         }
 232 
 233         return (*class);
 234 }
 235 
 236 /*
 237  * Get a dhcpmgr class methodid from the cache.
 238  */
 239 jmethodID
 240 get_methodID(JNIEnv *env, jclass class, CC_METHODMAP_ID id) {
 241 
 242         jmethodID *methodID;
 243 
 244         assert(id >= 0 && id <= CC_METHODMAP_NUM);
 245 
 246         /*
 247          * If the methodID has not been cached, go find it and cache it.
 248          */
 249         methodID = &methodIDMap[id].mi_methodID;
 250         if (*methodID == NULL) {
 251                 /*
 252                  * Check again with the lock held this time.
 253                  */
 254                 (void) mutex_lock(&mmap_lock);
 255                 if (*methodID == NULL) {
 256                         char *name = methodIDMap[id].mi_name;
 257                         char *signature = methodIDMap[id].mi_signature;
 258                         *methodID = (*env)->GetMethodID(env, class, name,
 259                             signature);
 260                 }
 261                 (void) mutex_unlock(&mmap_lock);
 262         }
 263 
 264         return (*methodID);
 265 }