1 /*
   2  * Copyright (c) 2015, 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_reflect_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.reflect.Module and VM will do deeper validation.
  38  */
  39 static char*
  40 GetInternalPackageName(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 
  70 JNIEXPORT void JNICALL
  71 Java_java_lang_reflect_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 idx;
  77     jsize num_packages = (*env)->GetArrayLength(env, packages);
  78 
  79     if (num_packages != 0 && (pkgs = calloc(num_packages, sizeof(char*))) == NULL) {
  80         JNU_ThrowOutOfMemoryError(env, NULL);
  81         return;
  82     } else {
  83         int valid = 1;
  84         for (idx = 0; idx < num_packages; idx++) {
  85             jstring pkg = (*env)->GetObjectArrayElement(env, packages, idx);
  86             pkgs[idx] = GetInternalPackageName(env, pkg, NULL, 0);
  87             if (pkgs[idx] == NULL) {
  88                 valid = 0;
  89                 break;
  90             }
  91         }
  92 
  93         if (valid != 0) {
  94             JVM_DefineModule(env, module, is_open, version, location,
  95                     (const char* const*)pkgs, num_packages);
  96         }
  97     }
  98 
  99     if (num_packages > 0) {
 100         for (idx = 0; idx < num_packages; idx++) {
 101             if (pkgs[idx] != NULL) {
 102                 free(pkgs[idx]);
 103             }
 104         }
 105         free(pkgs);
 106     }
 107 }
 108 
 109 JNIEXPORT void JNICALL
 110 Java_java_lang_reflect_Module_addReads0(JNIEnv *env, jclass cls, jobject from, jobject to)
 111 {
 112     JVM_AddReadsModule(env, from, to);
 113 }
 114 
 115 JNIEXPORT void JNICALL
 116 Java_java_lang_reflect_Module_addExports0(JNIEnv *env, jclass cls, jobject from,
 117                                           jstring pkg, jobject to)
 118 {
 119     char buf[128];
 120     char* pkg_name;
 121 
 122     if (pkg == NULL) {
 123         JNU_ThrowNullPointerException(env, "package is null");
 124         return;
 125     }
 126 
 127     pkg_name = GetInternalPackageName(env, pkg, buf, (jsize)sizeof(buf));
 128     if (pkg_name != NULL) {
 129         JVM_AddModuleExports(env, from, pkg_name, to);
 130         if (pkg_name != buf) {
 131             free(pkg_name);
 132         }
 133     }
 134 }
 135 
 136 JNIEXPORT void JNICALL
 137 Java_java_lang_reflect_Module_addExportsToAll0(JNIEnv *env, jclass cls, jobject from,
 138                                                jstring pkg)
 139 {
 140     char buf[128];
 141     char* pkg_name;
 142 
 143     if (pkg == NULL) {
 144         JNU_ThrowNullPointerException(env, "package is null");
 145         return;
 146     }
 147 
 148     pkg_name = GetInternalPackageName(env, pkg, buf, (jsize)sizeof(buf));
 149     if (pkg_name != NULL) {
 150         JVM_AddModuleExportsToAll(env, from, pkg_name);
 151         if (pkg_name != buf) {
 152             free(pkg_name);
 153         }
 154     }
 155 }
 156 
 157 JNIEXPORT void JNICALL
 158 Java_java_lang_reflect_Module_addExportsToAllUnnamed0(JNIEnv *env, jclass cls,
 159                                                       jobject from, jstring pkg)
 160 {
 161     char buf[128];
 162     char* pkg_name;
 163 
 164     if (pkg == NULL) {
 165         JNU_ThrowNullPointerException(env, "package is null");
 166         return;
 167     }
 168 
 169     pkg_name = GetInternalPackageName(env, pkg, buf, (jsize)sizeof(buf));
 170     if (pkg_name != NULL) {
 171         JVM_AddModuleExportsToAllUnnamed(env, from, pkg_name);
 172         if (pkg_name != buf) {
 173             free(pkg_name);
 174         }
 175     }
 176 }
 177 
 178 JNIEXPORT void JNICALL
 179 Java_java_lang_reflect_Module_addPackage0(JNIEnv *env, jclass cls, jobject m, jstring pkg)
 180 {
 181     char buf[128];
 182     char* pkg_name;
 183 
 184     if (pkg == NULL) {
 185         JNU_ThrowNullPointerException(env, "package is null");
 186         return;
 187     }
 188 
 189     pkg_name = GetInternalPackageName(env, pkg, buf, (jsize)sizeof(buf));
 190     if (pkg_name != NULL) {
 191         JVM_AddModulePackage(env, m, pkg_name);
 192         if (pkg_name != buf) {
 193             free(pkg_name);
 194         }
 195     }
 196 }