1/*
2 * Copyright (c) 2013, 2016, 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
26#include <stdlib.h>
27#include <jni.h>
28#include "management_ext.h"
29#include "com_sun_management_internal_DiagnosticCommandImpl.h"
30
31JNIEXPORT void JNICALL Java_com_sun_management_internal_DiagnosticCommandImpl_setNotificationEnabled
32(JNIEnv *env, jobject dummy, jboolean enabled) {
33 if (jmm_version <= JMM_VERSION_1_2_2) {
34 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
35 "JMX interface to diagnostic framework notifications is not supported by this VM");
36 return;
37 }
38 jmm_interface->SetDiagnosticFrameworkNotificationEnabled(env, enabled);
39}
40
41JNIEXPORT jobjectArray JNICALL
42Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommands
43 (JNIEnv *env, jobject dummy)
44{
45 return jmm_interface->GetDiagnosticCommands(env);
46}
47
48#define EXCEPTION_CHECK_AND_FREE(x) do { \
49 if ((*env)->ExceptionCheck(env)) { \
50 free(x); \
51 return NULL; \
52 } \
53 } while(0)
54
55jobject getDiagnosticCommandArgumentInfoArray(JNIEnv *env, jstring command,
56 int num_arg) {
57 int i;
58 jobject obj;
59 jobjectArray result;
60 dcmdArgInfo* dcmd_arg_info_array;
61 jclass dcmdArgInfoCls;
62 jclass arraysCls;
63 jmethodID mid;
64 jobject resultList;
65
66 dcmd_arg_info_array = (dcmdArgInfo*) malloc(num_arg * sizeof(dcmdArgInfo));
67 /* According to ISO C it is perfectly legal for malloc to return zero if called with a zero argument */
68 if (dcmd_arg_info_array == NULL && num_arg != 0) {
69 JNU_ThrowOutOfMemoryError(env, 0);
70 return NULL;
71 }
72 jmm_interface->GetDiagnosticCommandArgumentsInfo(env, command,
73 dcmd_arg_info_array);
74 dcmdArgInfoCls = (*env)->FindClass(env,
75 "com/sun/management/internal/DiagnosticCommandArgumentInfo");
76 if ((*env)->ExceptionCheck(env)) {
77 free(dcmd_arg_info_array);
78 return NULL;
79 }
80
81 result = (*env)->NewObjectArray(env, num_arg, dcmdArgInfoCls, NULL);
82 if (result == NULL) {
83 free(dcmd_arg_info_array);
84 return NULL;
85 }
86 for (i=0; i<num_arg; i++) {
87 jstring jname, jdesc,jtype,jdefStr;
88
89 jname = (*env)->NewStringUTF(env,dcmd_arg_info_array[i].name);
90 EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
91
92 jdesc = (*env)->NewStringUTF(env,dcmd_arg_info_array[i].description);
93 EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
94
95 jtype = (*env)->NewStringUTF(env,dcmd_arg_info_array[i].type);
96 EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
97
98 jdefStr = (*env)->NewStringUTF(env, dcmd_arg_info_array[i].default_string);
99 EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
100 obj = JNU_NewObjectByName(env,
101 "com/sun/management/internal/DiagnosticCommandArgumentInfo",
102 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZI)V",
103 jname, jdesc, jtype,
104 dcmd_arg_info_array[i].default_string == NULL ? NULL: jdefStr,
105 dcmd_arg_info_array[i].mandatory,
106 dcmd_arg_info_array[i].option,
107 dcmd_arg_info_array[i].multiple,
108 dcmd_arg_info_array[i].position);
109 if (obj == NULL) {
110 free(dcmd_arg_info_array);
111 return NULL;
112 }
113 (*env)->SetObjectArrayElement(env, result, i, obj);
114 EXCEPTION_CHECK_AND_FREE(dcmd_arg_info_array);
115 }
116 free(dcmd_arg_info_array);
117 arraysCls = (*env)->FindClass(env, "java/util/Arrays");
118 if ((*env)->ExceptionCheck(env)) {
119 return NULL;
120 }
121 mid = (*env)->GetStaticMethodID(env, arraysCls,
122 "asList", "([Ljava/lang/Object;)Ljava/util/List;");
123 resultList = (*env)->CallStaticObjectMethod(env, arraysCls, mid, result);
124 if ((*env)->ExceptionCheck(env)) {
125 // Make sure we return NULL in case of OOM inside Java
126 return NULL;
127 }
128 return resultList;
129}
130
131/* Throws IllegalArgumentException if at least one of the diagnostic command
132 * passed in argument is not supported by the JVM
133 */
134JNIEXPORT jobjectArray JNICALL
135Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommandInfo
136(JNIEnv *env, jobject dummy, jobjectArray commands)
137{
138 int i;
139 jclass dcmdInfoCls;
140 jobject result;
141 jobjectArray args;
142 jobject obj;
143 jmmOptionalSupport mos;
144 jint ret = jmm_interface->GetOptionalSupport(env, &mos);
145 jsize num_commands;
146 dcmdInfo* dcmd_info_array;
147 jstring jname, jdesc, jimpact;
148
149 if (commands == NULL) {
150 JNU_ThrowNullPointerException(env, "Invalid String Array");
151 return NULL;
152 }
153 num_commands = (*env)->GetArrayLength(env, commands);
154 dcmdInfoCls = (*env)->FindClass(env,
155 "com/sun/management/internal/DiagnosticCommandInfo");
156 if ((*env)->ExceptionCheck(env)) {
157 return NULL;
158 }
159
160 result = (*env)->NewObjectArray(env, num_commands, dcmdInfoCls, NULL);
161 if (result == NULL) {
162 return NULL;
163 }
164 if (num_commands == 0) {
165 /* Handle the 'zero commands' case specially to avoid calling 'malloc()' */
166 /* with a zero argument because that may legally return a NULL pointer. */
167 return result;
168 }
169 dcmd_info_array = (dcmdInfo*) malloc(num_commands * sizeof(dcmdInfo));
170 if (dcmd_info_array == NULL) {
171 JNU_ThrowOutOfMemoryError(env, NULL);
172 return NULL;
173 }
174 jmm_interface->GetDiagnosticCommandInfo(env, commands, dcmd_info_array);
175 for (i=0; i<num_commands; i++) {
176 args = getDiagnosticCommandArgumentInfoArray(env,
177 (*env)->GetObjectArrayElement(env,commands,i),
178 dcmd_info_array[i].num_arguments);
179 if (args == NULL) {
180 free(dcmd_info_array);
181 return NULL;
182 }
183
184 jname = (*env)->NewStringUTF(env,dcmd_info_array[i].name);
185 EXCEPTION_CHECK_AND_FREE(dcmd_info_array);
186
187 jdesc = (*env)->NewStringUTF(env,dcmd_info_array[i].description);
188 EXCEPTION_CHECK_AND_FREE(dcmd_info_array);
189
190 jimpact = (*env)->NewStringUTF(env,dcmd_info_array[i].impact);
191 EXCEPTION_CHECK_AND_FREE(dcmd_info_array);
192
193 obj = JNU_NewObjectByName(env,
194 "com/sun/management/internal/DiagnosticCommandInfo",
195 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/util/List;)V",
196 jname, jdesc, jimpact,
197 dcmd_info_array[i].permission_class==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_class),
198 dcmd_info_array[i].permission_name==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_name),
199 dcmd_info_array[i].permission_action==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_action),
200 dcmd_info_array[i].enabled,
201 args);
202 if (obj == NULL) {
203 free(dcmd_info_array);
204 return NULL;
205 }
206
207 (*env)->SetObjectArrayElement(env, result, i, obj);
208 EXCEPTION_CHECK_AND_FREE(dcmd_info_array);
209 }
210 free(dcmd_info_array);
211 return result;
212}
213
214/* Throws IllegalArgumentException if the diagnostic command
215 * passed in argument is not supported by the JVM
216 */
217JNIEXPORT jstring JNICALL
218Java_com_sun_management_internal_DiagnosticCommandImpl_executeDiagnosticCommand
219(JNIEnv *env, jobject dummy, jstring command) {
220 return jmm_interface->ExecuteDiagnosticCommand(env, command);
221}
222