1/*
2 * Copyright (c) 2015, 2017, 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#include <stdlib.h>
26#include <string.h>
27
28#include "jni.h"
29#include "jni_util.h"
30#include "jvm.h"
31
32#include "java_lang_Module.h"
33
34/*
35 * Gets the UTF-8 chars for the string and translates '.' to '/'. Does no
36 * further validation, assumption being that both calling code in
37 * java.lang.Module and VM will do deeper validation.
38 */
39static char*
40GetInternalPackageName(JNIEnv *env, jstring pkg, char* buf, jsize buf_size)
41{
42 jsize len;
43 jsize unicode_len;
44 char* p;
45 char* utf_str;
46
47 len = (*env)->GetStringUTFLength(env, pkg);
48 unicode_len = (*env)->GetStringLength(env, pkg);
49 if (len >= buf_size) {
50 utf_str = malloc(len + 1);
51 if (utf_str == NULL) {
52 JNU_ThrowOutOfMemoryError(env, NULL);
53 return NULL;
54 }
55 } else {
56 utf_str = buf;
57 }
58 (*env)->GetStringUTFRegion(env, pkg, 0, unicode_len, utf_str);
59
60 p = utf_str;
61 while (*p != '\0') {
62 if (*p == '.') {
63 *p = '/';
64 }
65 p++;
66 }
67 return utf_str;
68}
69
70JNIEXPORT void JNICALL
71Java_java_lang_Module_defineModule0(JNIEnv *env, jclass cls, jobject module,
72 jboolean is_open, jstring version,
73 jstring location, jobjectArray packages)
74{
75 char** pkgs = NULL;
76 jsize num_packages = (*env)->GetArrayLength(env, packages);
77
78 if (num_packages != 0 && (pkgs = calloc(num_packages, sizeof(char*))) == NULL) {
79 JNU_ThrowOutOfMemoryError(env, NULL);
80 return;
81 } else if ((*env)->EnsureLocalCapacity(env, (jint)num_packages) == 0) {
82 jboolean failed = JNI_FALSE;
83 int idx;
84 for (idx = 0; idx < num_packages; idx++) {
85 jstring pkg = (*env)->GetObjectArrayElement(env, packages, idx);
86 char* name = GetInternalPackageName(env, pkg, NULL, 0);
87 if (name != NULL) {
88 pkgs[idx] = name;
89 } else {
90 failed = JNI_TRUE;
91 break;
92 }
93 }
94 if (!failed) {
95 JVM_DefineModule(env, module, is_open, version, location,
96 (const char* const*)pkgs, num_packages);
97 }
98 }
99
100 if (num_packages > 0) {
101 int idx;
102 for (idx = 0; idx < num_packages; idx++) {
103 if (pkgs[idx] != NULL) {
104 free(pkgs[idx]);
105 }
106 }
107 free(pkgs);
108 }
109}
110
111JNIEXPORT void JNICALL
112Java_java_lang_Module_addReads0(JNIEnv *env, jclass cls, jobject from, jobject to)
113{
114 JVM_AddReadsModule(env, from, to);
115}
116
117JNIEXPORT void JNICALL
118Java_java_lang_Module_addExports0(JNIEnv *env, jclass cls, jobject from,
119 jstring pkg, jobject to)
120{
121 char buf[128];
122 char* pkg_name;
123
124 if (pkg == NULL) {
125 JNU_ThrowNullPointerException(env, "package is null");
126 return;
127 }
128
129 pkg_name = GetInternalPackageName(env, pkg, buf, (jsize)sizeof(buf));
130 if (pkg_name != NULL) {
131 JVM_AddModuleExports(env, from, pkg_name, to);
132 if (pkg_name != buf) {
133 free(pkg_name);
134 }
135 }
136}
137
138JNIEXPORT void JNICALL
139Java_java_lang_Module_addExportsToAll0(JNIEnv *env, jclass cls, jobject from,
140 jstring pkg)
141{
142 char buf[128];
143 char* pkg_name;
144
145 if (pkg == NULL) {
146 JNU_ThrowNullPointerException(env, "package is null");
147 return;
148 }
149
150 pkg_name = GetInternalPackageName(env, pkg, buf, (jsize)sizeof(buf));
151 if (pkg_name != NULL) {
152 JVM_AddModuleExportsToAll(env, from, pkg_name);
153 if (pkg_name != buf) {
154 free(pkg_name);
155 }
156 }
157}
158
159JNIEXPORT void JNICALL
160Java_java_lang_Module_addExportsToAllUnnamed0(JNIEnv *env, jclass cls,
161 jobject from, jstring pkg)
162{
163 char buf[128];
164 char* pkg_name;
165
166 if (pkg == NULL) {
167 JNU_ThrowNullPointerException(env, "package is null");
168 return;
169 }
170
171 pkg_name = GetInternalPackageName(env, pkg, buf, (jsize)sizeof(buf));
172 if (pkg_name != NULL) {
173 JVM_AddModuleExportsToAllUnnamed(env, from, pkg_name);
174 if (pkg_name != buf) {
175 free(pkg_name);
176 }
177 }
178}
179