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