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
init_class_cache(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
find_class(JNIEnv * env,CC_CLASSMAP_ID id)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
get_methodID(JNIEnv * env,jclass class,CC_METHODMAP_ID id)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 }
266