1 /*
   2  * Copyright (c) 1994, 2018, 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 <string.h>
  27 
  28 #include "jni.h"
  29 #include "jni_util.h"
  30 #include "jvm.h"
  31 #include "java_props.h"
  32 
  33 #include "java_lang_System.h"
  34 #include "jdk_internal_util_SystemProps_Raw.h"
  35 
  36 #define OBJ "Ljava/lang/Object;"
  37 
  38 /* Only register the performance-critical methods */
  39 static JNINativeMethod methods[] = {
  40     {"currentTimeMillis", "()J",              (void *)&JVM_CurrentTimeMillis},
  41     {"nanoTime",          "()J",              (void *)&JVM_NanoTime},
  42     {"arraycopy",     "(" OBJ "I" OBJ "II)V", (void *)&JVM_ArrayCopy},
  43 };
  44 
  45 #undef OBJ
  46 
  47 JNIEXPORT void JNICALL
  48 Java_java_lang_System_registerNatives(JNIEnv *env, jclass cls)
  49 {
  50     (*env)->RegisterNatives(env, cls,
  51                             methods, sizeof(methods)/sizeof(methods[0]));
  52 }
  53 
  54 JNIEXPORT jint JNICALL
  55 Java_java_lang_System_identityHashCode(JNIEnv *env, jobject this, jobject x)
  56 {
  57     return JVM_IHashCode(env, x);
  58 }
  59 
  60 /* VENDOR, VENDOR_URL, VENDOR_URL_BUG are set in VersionProps.java.template. */
  61 
  62 /*
  63  * Store the UTF-8 string encoding of the value in the array
  64  * at the index if the value is non-null.  Store nothing if the value is null.
  65  * On any error, return from Java_jdk_internal_util_SystemProps_00024Raw_platformProperties.
  66  */
  67 #define PUTPROP(array, prop_index, val)                    \
  68     if (val != NULL) {                                     \
  69         jstring jval = (*env)->NewStringUTF(env, val);     \
  70         if (jval == NULL)                                  \
  71             return NULL;                                   \
  72         (*env)->SetObjectArrayElement(env, array, jdk_internal_util_SystemProps_Raw_##prop_index, jval); \
  73         if ((*env)->ExceptionOccurred(env))                \
  74             return NULL;                                   \
  75         (*env)->DeleteLocalRef(env, jval);                 \
  76     }
  77 
  78 /*
  79  * Store the Platform string encoding of the value in the array
  80  * at the index if the value is non-null.  Store nothing if the value is null.
  81  * On any error, return from Java_jdk_internal_util_SystemProps_00024Raw_platformProperties.
  82  */
  83 #define PUTPROP_PlatformString(array, prop_index, val)     \
  84     if (val != NULL) {                                     \
  85         jstring jval = GetStringPlatform(env, val);        \
  86         if (jval == NULL)                                  \
  87             return NULL;                                   \
  88         (*env)->SetObjectArrayElement(env, array, jdk_internal_util_SystemProps_Raw_##prop_index, jval); \
  89         if ((*env)->ExceptionOccurred(env))                \
  90             return NULL;                                   \
  91         (*env)->DeleteLocalRef(env, jval);                 \
  92     }
  93 
  94 /*
  95  * Gather the system properties and return as a String[].
  96  * The first FIXED_LENGTH entries are the platform defined property values, no names.
  97  * The remaining array indices are alternating key/value pairs
  98  * supplied by the VM including those defined on the command line
  99  * using -Dkey=value that may override the platform defined value.
 100  * The caller is responsible for replacing platform provided values as needed.
 101  *
 102  * Class:     jdk_internal_util_SystemProps_Raw
 103  * Method:    platformProperties
 104  * Signature: ()[Ljava/lang/String;
 105  */
 106 JNIEXPORT jobjectArray JNICALL
 107 Java_jdk_internal_util_SystemProps_00024Raw_platformProperties(JNIEnv *env, jclass cla)
 108 {
 109     java_props_t *sprops;
 110     jobject propArray = NULL;
 111     jclass classString;
 112     int nstrings = jdk_internal_util_SystemProps_Raw_FIXED_LENGTH;
 113 
 114     // Get the platform specific values
 115     sprops = GetJavaProperties(env);
 116     CHECK_NULL_RETURN(sprops, NULL);
 117 
 118     /*
 119      * !!! DO NOT call PUTPROP_PlatformString (NewStringPlatform) before this line !!!
 120      */
 121     InitializeEncoding(env, sprops->sun_jnu_encoding);
 122 
 123     // Ensure capacity for the array and for a string for each fixed length element
 124     if ((*env)->EnsureLocalCapacity(env, nstrings + 2) < 0) {
 125         return NULL;
 126     }
 127 
 128     // Allocate an array of String for all the well known props
 129     classString = JNU_ClassString(env);
 130     CHECK_NULL_RETURN(classString, NULL);
 131 
 132     propArray = (*env)->NewObjectArray(env, nstrings, classString, NULL);
 133     CHECK_NULL_RETURN(propArray, NULL);
 134 
 135     /* os properties */
 136     PUTPROP(propArray, _os_name_NDX, sprops->os_name);
 137     PUTPROP(propArray, _os_version_NDX, sprops->os_version);
 138     PUTPROP(propArray, _os_arch_NDX, sprops->os_arch);
 139 
 140 #ifdef JDK_ARCH_ABI_PROP_NAME
 141     PUTPROP(propArray, _sun_arch_abi_NDX, sprops->sun_arch_abi);
 142 #endif
 143 
 144     /* file system properties */
 145     PUTPROP(propArray, _file_separator_NDX, sprops->file_separator);
 146     PUTPROP(propArray, _path_separator_NDX, sprops->path_separator);
 147     PUTPROP(propArray, _line_separator_NDX, sprops->line_separator);
 148 
 149     PUTPROP(propArray, _file_encoding_NDX, sprops->encoding);
 150     PUTPROP(propArray, _sun_jnu_encoding_NDX, sprops->sun_jnu_encoding);
 151 
 152     /*
 153      * file encoding for stdout and stderr
 154      */
 155     PUTPROP(propArray, _sun_stdout_encoding_NDX, sprops->sun_stdout_encoding);
 156     PUTPROP(propArray, _sun_stderr_encoding_NDX, sprops->sun_stderr_encoding);
 157 
 158     /* unicode_encoding specifies the default endianness */
 159     PUTPROP(propArray, _sun_io_unicode_encoding_NDX, sprops->unicode_encoding);
 160     PUTPROP(propArray, _sun_cpu_endian_NDX, sprops->cpu_endian);
 161     PUTPROP(propArray, _sun_cpu_isalist_NDX, sprops->cpu_isalist);
 162 
 163 #ifdef MACOSX
 164     PUTPROP(propArray, _java_awt_headless_NDX, sprops->awt_headless);
 165 
 166     /* Proxy setting properties */
 167     if (sprops->httpProxyEnabled) {
 168         PUTPROP(propArray, _http_proxyHost_NDX, sprops->httpHost);
 169         PUTPROP(propArray, _http_proxyPort_NDX, sprops->httpPort);
 170     }
 171 
 172     if (sprops->httpsProxyEnabled) {
 173         PUTPROP(propArray, _https_proxyHost_NDX, sprops->httpsHost);
 174         PUTPROP(propArray, _https_proxyPort_NDX, sprops->httpsPort);
 175     }
 176 
 177     if (sprops->ftpProxyEnabled) {
 178         PUTPROP(propArray, _ftp_proxyHost_NDX, sprops->ftpHost);
 179         PUTPROP(propArray, _ftp_proxyPort_NDX, sprops->ftpPort);
 180     }
 181 
 182     if (sprops->socksProxyEnabled) {
 183         PUTPROP(propArray, _socksProxyHost_NDX, sprops->socksHost);
 184         PUTPROP(propArray, _socksProxyPort_NDX, sprops->socksPort);
 185     }
 186 
 187     // Mac OS X only has a single proxy exception list which applies
 188     // to all protocols
 189     if (sprops->exceptionList) {
 190         PUTPROP(propArray, _http_nonProxyHosts_NDX, sprops->exceptionList);
 191         PUTPROP(propArray, _ftp_nonProxyHosts_NDX, sprops->exceptionList);
 192         PUTPROP(propArray, _socksNonProxyHosts_NDX, sprops->exceptionList);
 193     }
 194 #endif
 195 
 196     /* data model */
 197     if (sizeof(sprops) == 4) {
 198         sprops->data_model = "32";
 199     } else if (sizeof(sprops) == 8) {
 200         sprops->data_model = "64";
 201     } else {
 202         sprops->data_model = "unknown";
 203     }
 204     PUTPROP(propArray, _sun_arch_data_model_NDX, sprops->data_model);
 205 
 206     /* patch level */
 207     PUTPROP(propArray, _sun_os_patch_level_NDX, sprops->patch_level);
 208 
 209     PUTPROP(propArray, _awt_toolkit_NDX, sprops->awt_toolkit);
 210 
 211     /* Java2D properties */
 212     /* Note: java.awt.graphicsenv is an implementation private property which
 213      * just happens to have a java.* name because it is referenced in
 214      * a java.awt class. It is the mechanism by which the implementation
 215      * finds the appropriate class in the JRE for the platform.
 216      * It is explicitly not designed to be overridden by clients as
 217      * a way of replacing the implementation class, and in any case
 218      * the mechanism by which the class is loaded is constrained to only
 219      * find and load classes that are part of the JRE.
 220      * This property may be removed if that mechanism is redesigned
 221      */
 222     PUTPROP(propArray, _java_awt_graphicsenv_NDX, sprops->graphics_env);
 223 
 224     /*
 225      * The sun.desktop property is currently only set for Gnome and Windows desktops.
 226      */
 227     PUTPROP(propArray, _sun_desktop_NDX, sprops->desktop);
 228 
 229     PUTPROP_PlatformString(propArray, _java_io_tmpdir_NDX, sprops->tmp_dir);
 230 
 231     PUTPROP_PlatformString(propArray, _user_name_NDX, sprops->user_name);
 232     PUTPROP_PlatformString(propArray, _user_home_NDX, sprops->user_home);
 233     PUTPROP_PlatformString(propArray, _user_dir_NDX, sprops->user_dir);
 234 
 235    /*
 236     * Set i18n related property fields from platform.
 237     */
 238    PUTPROP(propArray, _display_language_NDX, sprops->display_language);
 239    PUTPROP(propArray, _display_script_NDX, sprops->display_script);
 240    PUTPROP(propArray, _display_country_NDX, sprops->display_country);
 241    PUTPROP(propArray, _display_variant_NDX, sprops->display_variant);
 242 
 243    PUTPROP(propArray, _format_language_NDX, sprops->format_language);
 244    PUTPROP(propArray, _format_script_NDX, sprops->format_script);
 245    PUTPROP(propArray, _format_country_NDX, sprops->format_country);
 246    PUTPROP(propArray, _format_variant_NDX, sprops->format_variant);
 247 
 248    return propArray;
 249 }
 250 
 251 /*
 252  * Gather the VM and command line properties and return as a String[].
 253  * The array indices are alternating key/value pairs
 254  * supplied by the VM including those defined on the command line
 255  * using -Dkey=value that may override the platform defined value.
 256  *
 257  * Note: The platform encoding must have been set.
 258  *
 259  * Class:     jdk_internal_util_SystemProps_Raw
 260  * Method:    vmProperties
 261  * Signature: ()[Ljava/lang/String;
 262  */
 263 JNIEXPORT jobjectArray JNICALL
 264 Java_jdk_internal_util_SystemProps_00024Raw_vmProperties(JNIEnv *env, jclass cla)
 265 {
 266     jobjectArray cmdProps = JVM_GetProperties(env);
 267     return cmdProps;
 268 }
 269 
 270 /*
 271  * The following three functions implement setter methods for
 272  * java.lang.System.{in, out, err}. They are natively implemented
 273  * because they violate the semantics of the language (i.e. set final
 274  * variable).
 275  */
 276 JNIEXPORT void JNICALL
 277 Java_java_lang_System_setIn0(JNIEnv *env, jclass cla, jobject stream)
 278 {
 279     jfieldID fid =
 280         (*env)->GetStaticFieldID(env,cla,"in","Ljava/io/InputStream;");
 281     if (fid == 0)
 282         return;
 283     (*env)->SetStaticObjectField(env,cla,fid,stream);
 284 }
 285 
 286 JNIEXPORT void JNICALL
 287 Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream)
 288 {
 289     jfieldID fid =
 290         (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");
 291     if (fid == 0)
 292         return;
 293     (*env)->SetStaticObjectField(env,cla,fid,stream);
 294 }
 295 
 296 JNIEXPORT void JNICALL
 297 Java_java_lang_System_setErr0(JNIEnv *env, jclass cla, jobject stream)
 298 {
 299     jfieldID fid =
 300         (*env)->GetStaticFieldID(env,cla,"err","Ljava/io/PrintStream;");
 301     if (fid == 0)
 302         return;
 303     (*env)->SetStaticObjectField(env,cla,fid,stream);
 304 }
 305 
 306 static void cpchars(jchar *dst, char *src, int n)
 307 {
 308     int i;
 309     for (i = 0; i < n; i++) {
 310         dst[i] = src[i];
 311     }
 312 }
 313 
 314 JNIEXPORT jstring JNICALL
 315 Java_java_lang_System_mapLibraryName(JNIEnv *env, jclass ign, jstring libname)
 316 {
 317     int len;
 318     int prefix_len = (int) strlen(JNI_LIB_PREFIX);
 319     int suffix_len = (int) strlen(JNI_LIB_SUFFIX);
 320 
 321     jchar chars[256];
 322     if (libname == NULL) {
 323         JNU_ThrowNullPointerException(env, 0);
 324         return NULL;
 325     }
 326     len = (*env)->GetStringLength(env, libname);
 327     if (len > 240) {
 328         JNU_ThrowIllegalArgumentException(env, "name too long");
 329         return NULL;
 330     }
 331     cpchars(chars, JNI_LIB_PREFIX, prefix_len);
 332     (*env)->GetStringRegion(env, libname, 0, len, chars + prefix_len);
 333     len += prefix_len;
 334     cpchars(chars + len, JNI_LIB_SUFFIX, suffix_len);
 335     len += suffix_len;
 336 
 337     return (*env)->NewString(env, chars, len);
 338 }