Remove cpp code and test-app
This commit is contained in:
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Curses functions
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <curses.h>
|
||||
#include <term.h>
|
||||
|
||||
#define NORMAL_TEXT 0
|
||||
#define BRIGHT_TEXT 1
|
||||
#define FOREGROUND_COLOR 2
|
||||
#define CURSOR_UP 3
|
||||
#define CURSOR_DOWN 4
|
||||
#define CURSOR_LEFT 5
|
||||
#define CURSOR_RIGHT 6
|
||||
#define CURSOR_START_LINE 7
|
||||
#define CLEAR_END_OF_LINE 8
|
||||
|
||||
#ifdef SOLARIS
|
||||
#define TERMINAL_CHAR_TYPE char
|
||||
#else
|
||||
#define TERMINAL_CHAR_TYPE int
|
||||
#endif
|
||||
|
||||
int current_terminal = -1;
|
||||
const char* terminal_capabilities[9];
|
||||
|
||||
int write_to_terminal(TERMINAL_CHAR_TYPE ch) {
|
||||
write(current_terminal, &ch, 1);
|
||||
return ch;
|
||||
}
|
||||
|
||||
const char* getcap(const char* capability) {
|
||||
return tgetstr((char*)capability, NULL);
|
||||
}
|
||||
|
||||
void write_capability(JNIEnv *env, const char* capability, jobject result) {
|
||||
if (capability == NULL) {
|
||||
mark_failed_with_message(env, "unknown terminal capability", result);
|
||||
return;
|
||||
}
|
||||
if (tputs((char*)capability, 1, write_to_terminal) == ERR) {
|
||||
mark_failed_with_message(env, "could not write to terminal", result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void write_param_capability(JNIEnv *env, const char* capability, int count, jobject result) {
|
||||
if (capability == NULL) {
|
||||
mark_failed_with_message(env, "unknown terminal capability", result);
|
||||
return;
|
||||
}
|
||||
|
||||
capability = tparm((char*)capability, count, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
if (capability == NULL) {
|
||||
mark_failed_with_message(env, "could not format terminal capability string", result);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tputs((char*)capability, 1, write_to_terminal) == ERR) {
|
||||
mark_failed_with_message(env, "could not write to terminal", result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_getVersion(JNIEnv *env, jclass target) {
|
||||
return NATIVE_VERSION;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_initTerminal(JNIEnv *env, jclass target, jint output, jobject capabilities, jobject result) {
|
||||
if (!isatty(output+1)) {
|
||||
mark_failed_with_message(env, "not a terminal", result);
|
||||
return;
|
||||
}
|
||||
if (current_terminal < 0) {
|
||||
char* termType = getenv("TERM");
|
||||
if (termType == NULL) {
|
||||
mark_failed_with_message(env, "$TERM not set", result);
|
||||
return;
|
||||
}
|
||||
int retval = tgetent(NULL, termType);
|
||||
if (retval != 1) {
|
||||
mark_failed_with_message(env, "could not get termcap entry", result);
|
||||
return;
|
||||
}
|
||||
|
||||
jclass destClass = env->GetObjectClass(capabilities);
|
||||
jfieldID field = env->GetFieldID(destClass, "terminalName", "Ljava/lang/String;");
|
||||
jstring jtermType = char_to_java(env, termType, result);
|
||||
env->SetObjectField(capabilities, field, jtermType);
|
||||
|
||||
// Text attributes
|
||||
terminal_capabilities[NORMAL_TEXT] = getcap("me");
|
||||
terminal_capabilities[BRIGHT_TEXT] = getcap("md");
|
||||
field = env->GetFieldID(destClass, "textAttributes", "Z");
|
||||
env->SetBooleanField(capabilities, field, terminal_capabilities[NORMAL_TEXT] != NULL && terminal_capabilities[BRIGHT_TEXT] != NULL);
|
||||
|
||||
// Colors
|
||||
terminal_capabilities[FOREGROUND_COLOR] = getcap("AF");
|
||||
field = env->GetFieldID(destClass, "colors", "Z");
|
||||
env->SetBooleanField(capabilities, field, terminal_capabilities[FOREGROUND_COLOR] != NULL);
|
||||
|
||||
// Cursor motion
|
||||
terminal_capabilities[CURSOR_UP] = getcap("up");
|
||||
terminal_capabilities[CURSOR_DOWN] = getcap("do");
|
||||
terminal_capabilities[CURSOR_LEFT] = getcap("le");
|
||||
terminal_capabilities[CURSOR_RIGHT] = getcap("nd");
|
||||
terminal_capabilities[CURSOR_START_LINE] = getcap("cr");
|
||||
terminal_capabilities[CLEAR_END_OF_LINE] = getcap("ce");
|
||||
field = env->GetFieldID(destClass, "cursorMotion", "Z");
|
||||
env->SetBooleanField(capabilities, field, terminal_capabilities[CURSOR_UP] != NULL
|
||||
&& terminal_capabilities[CURSOR_DOWN] != NULL
|
||||
&& terminal_capabilities[CURSOR_RIGHT] != NULL
|
||||
&& terminal_capabilities[CURSOR_LEFT] != NULL
|
||||
&& terminal_capabilities[CURSOR_START_LINE] != NULL
|
||||
&& terminal_capabilities[CLEAR_END_OF_LINE] != NULL);
|
||||
}
|
||||
current_terminal = output + 1;
|
||||
if (terminal_capabilities[NORMAL_TEXT] != NULL) {
|
||||
write_capability(env, terminal_capabilities[NORMAL_TEXT], result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_bold(JNIEnv *env, jclass target, jobject result) {
|
||||
write_capability(env, terminal_capabilities[BRIGHT_TEXT], result);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_reset(JNIEnv *env, jclass target, jobject result) {
|
||||
if (terminal_capabilities[NORMAL_TEXT] != NULL) {
|
||||
write_capability(env, terminal_capabilities[NORMAL_TEXT], result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_foreground(JNIEnv *env, jclass target, jint color, jobject result) {
|
||||
write_param_capability(env, terminal_capabilities[FOREGROUND_COLOR], color, result);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_up(JNIEnv *env, jclass target, jint count, jobject result) {
|
||||
for (jint i = 0; i < count; i++) {
|
||||
write_capability(env, terminal_capabilities[CURSOR_UP], result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_down(JNIEnv *env, jclass target, jint count, jobject result) {
|
||||
for (jint i = 0; i < count; i++) {
|
||||
write_capability(env, terminal_capabilities[CURSOR_DOWN], result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_left(JNIEnv *env, jclass target, jint count, jobject result) {
|
||||
for (jint i = 0; i < count; i++) {
|
||||
write_capability(env, terminal_capabilities[CURSOR_LEFT], result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_right(JNIEnv *env, jclass target, jint count, jobject result) {
|
||||
for (jint i = 0; i < count; i++) {
|
||||
write_capability(env, terminal_capabilities[CURSOR_RIGHT], result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_startLine(JNIEnv *env, jclass target, jobject result) {
|
||||
write_capability(env, terminal_capabilities[CURSOR_START_LINE], result);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_clearToEndOfLine(JNIEnv *env, jclass target, jobject result) {
|
||||
write_capability(env, terminal_capabilities[CLEAR_END_OF_LINE], result);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FreeBSD (including OS X) specific functions.
|
||||
*/
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/attr.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct vol_caps_buf {
|
||||
u_int32_t size;
|
||||
vol_capabilities_attr_t caps;
|
||||
} vol_caps_buf_t;
|
||||
|
||||
/*
|
||||
* File system functions
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) {
|
||||
int fs_count = getfsstat(NULL, 0, MNT_NOWAIT);
|
||||
if (fs_count < 0) {
|
||||
mark_failed_with_errno(env, "could not stat file systems", result);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t len = fs_count * sizeof(struct statfs);
|
||||
struct statfs* buf = (struct statfs*)malloc(len);
|
||||
if (getfsstat(buf, len, MNT_NOWAIT) < 0 ) {
|
||||
mark_failed_with_errno(env, "could not stat file systems", result);
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
jclass info_class = env->GetObjectClass(info);
|
||||
jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ)V");
|
||||
|
||||
for (int i = 0; i < fs_count; i++) {
|
||||
struct attrlist alist;
|
||||
memset(&alist, 0, sizeof(alist));
|
||||
alist.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
alist.volattr = ATTR_VOL_CAPABILITIES | ATTR_VOL_INFO;
|
||||
vol_caps_buf_t buffer;
|
||||
|
||||
// getattrlist requires the path to the actual mount point.
|
||||
int err = getattrlist(buf[i].f_mntonname, &alist, &buffer, sizeof(buffer), 0);
|
||||
if (err != 0) {
|
||||
mark_failed_with_errno(env, "could not determine file system attributes", result);
|
||||
break;
|
||||
}
|
||||
|
||||
jboolean caseSensitive = JNI_TRUE;
|
||||
jboolean casePreserving = JNI_TRUE;
|
||||
if (alist.volattr & ATTR_VOL_CAPABILITIES) {
|
||||
if ((buffer.caps.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE)) {
|
||||
caseSensitive = (buffer.caps.capabilities[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE) != 0;
|
||||
}
|
||||
if ((buffer.caps.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_PRESERVING)) {
|
||||
casePreserving = (buffer.caps.capabilities[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_PRESERVING) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
jstring mount_point = char_to_java(env, buf[i].f_mntonname, result);
|
||||
jstring file_system_type = char_to_java(env, buf[i].f_fstypename, result);
|
||||
jstring device_name = char_to_java(env, buf[i].f_mntfromname, result);
|
||||
jboolean remote = (buf[i].f_flags & MNT_LOCAL) == 0;
|
||||
env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, remote, caseSensitive, casePreserving);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Linux specific functions.
|
||||
*/
|
||||
#ifdef __linux__
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <stdio.h>
|
||||
#include <mntent.h>
|
||||
|
||||
/*
|
||||
* File system functions
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) {
|
||||
FILE *fp = setmntent(MOUNTED, "r");
|
||||
if (fp == NULL) {
|
||||
mark_failed_with_errno(env, "could not open mount file", result);
|
||||
return;
|
||||
}
|
||||
char buf[1024];
|
||||
struct mntent mount_info;
|
||||
|
||||
jclass info_class = env->GetObjectClass(info);
|
||||
jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ)V");
|
||||
|
||||
while (getmntent_r(fp, &mount_info, buf, sizeof(buf)) != NULL) {
|
||||
jstring mount_point = char_to_java(env, mount_info.mnt_dir, result);
|
||||
jstring file_system_type = char_to_java(env, mount_info.mnt_type, result);
|
||||
jstring device_name = char_to_java(env, mount_info.mnt_fsname, result);
|
||||
env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, JNI_FALSE, JNI_TRUE, JNI_TRUE);
|
||||
}
|
||||
|
||||
endmntent(fp);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* POSIX platform functions.
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) {
|
||||
jclass infoClass = env->GetObjectClass(info);
|
||||
|
||||
struct utsname machine_info;
|
||||
if (uname(&machine_info) != 0) {
|
||||
mark_failed_with_errno(env, "could not query machine details", result);
|
||||
return;
|
||||
}
|
||||
|
||||
jfieldID osNameField = env->GetFieldID(infoClass, "osName", "Ljava/lang/String;");
|
||||
env->SetObjectField(info, osNameField, char_to_java(env, machine_info.sysname, result));
|
||||
jfieldID osVersionField = env->GetFieldID(infoClass, "osVersion", "Ljava/lang/String;");
|
||||
env->SetObjectField(info, osVersionField, char_to_java(env, machine_info.release, result));
|
||||
jfieldID machineArchitectureField = env->GetFieldID(infoClass, "machineArchitecture", "Ljava/lang/String;");
|
||||
env->SetObjectField(info, machineArchitectureField, char_to_java(env, machine_info.machine, result));
|
||||
}
|
||||
|
||||
/*
|
||||
* File functions
|
||||
*/
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_chmod(JNIEnv *env, jclass target, jstring path, jint mode, jobject result) {
|
||||
char* pathStr = java_to_char(env, path, result);
|
||||
if (pathStr == NULL) {
|
||||
return;
|
||||
}
|
||||
int retval = chmod(pathStr, mode);
|
||||
free(pathStr);
|
||||
if (retval != 0) {
|
||||
mark_failed_with_errno(env, "could not chmod file", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *env, jclass target, jstring path, jobject dest, jobject result) {
|
||||
struct stat fileInfo;
|
||||
char* pathStr = java_to_char(env, path, result);
|
||||
if (pathStr == NULL) {
|
||||
return;
|
||||
}
|
||||
int retval = lstat(pathStr, &fileInfo);
|
||||
free(pathStr);
|
||||
if (retval != 0 && errno != ENOENT) {
|
||||
mark_failed_with_errno(env, "could not stat file", result);
|
||||
return;
|
||||
}
|
||||
|
||||
jclass destClass = env->GetObjectClass(dest);
|
||||
jfieldID modeField = env->GetFieldID(destClass, "mode", "I");
|
||||
jfieldID typeField = env->GetFieldID(destClass, "type", "I");
|
||||
|
||||
if (retval != 0) {
|
||||
env->SetIntField(dest, typeField, 4);
|
||||
} else {
|
||||
env->SetIntField(dest, modeField, 0777 & fileInfo.st_mode);
|
||||
int type;
|
||||
switch (fileInfo.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
type = 0;
|
||||
break;
|
||||
case S_IFDIR:
|
||||
type = 1;
|
||||
break;
|
||||
case S_IFLNK:
|
||||
type = 2;
|
||||
break;
|
||||
default:
|
||||
type= 3;
|
||||
}
|
||||
env->SetIntField(dest, typeField, type);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_symlink(JNIEnv *env, jclass target, jstring path, jstring contents, jobject result) {
|
||||
char* pathStr = java_to_char(env, path, result);
|
||||
if (pathStr == NULL) {
|
||||
return;
|
||||
}
|
||||
char* contentStr = java_to_char(env, contents, result);
|
||||
if (contentStr == NULL) {
|
||||
free(pathStr);
|
||||
return;
|
||||
}
|
||||
int retval = symlink(contentStr, pathStr);
|
||||
free(contentStr);
|
||||
free(pathStr);
|
||||
if (retval != 0) {
|
||||
mark_failed_with_errno(env, "could not symlink", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_readlink(JNIEnv *env, jclass target, jstring path, jobject result) {
|
||||
struct stat link_info;
|
||||
char* pathStr = java_to_char(env, path, result);
|
||||
if (pathStr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
int retval = lstat(pathStr, &link_info);
|
||||
if (retval != 0) {
|
||||
free(pathStr);
|
||||
mark_failed_with_errno(env, "could not lstat file", result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* contents = (char*)malloc(link_info.st_size + 1);
|
||||
if (contents == NULL) {
|
||||
free(pathStr);
|
||||
mark_failed_with_message(env, "could not create array", result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval = readlink(pathStr, contents, link_info.st_size);
|
||||
free(pathStr);
|
||||
if (retval < 0) {
|
||||
free(contents);
|
||||
mark_failed_with_errno(env, "could not readlink", result);
|
||||
return NULL;
|
||||
}
|
||||
contents[link_info.st_size] = 0;
|
||||
jstring contents_str = char_to_java(env, contents, result);
|
||||
free(contents);
|
||||
return contents_str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process functions
|
||||
*/
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
|
||||
return getpid();
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getWorkingDirectory(JNIEnv *env, jclass target, jobject result) {
|
||||
char* path = getcwd(NULL, 0);
|
||||
if (path == NULL) {
|
||||
mark_failed_with_errno(env, "could not getcwd()", result);
|
||||
return NULL;
|
||||
}
|
||||
jstring dir = char_to_java(env, path, result);
|
||||
free(path);
|
||||
return dir;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setWorkingDirectory(JNIEnv *env, jclass target, jstring dir, jobject result) {
|
||||
char* path = java_to_char(env, dir, result);
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
if (chdir(path) != 0) {
|
||||
mark_failed_with_errno(env, "could not setcwd()", result);
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jobject result) {
|
||||
char* varStr = java_to_char(env, var, result);
|
||||
char* valueStr = getenv(varStr);
|
||||
free(varStr);
|
||||
if (valueStr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return char_to_java(env, valueStr, result);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jstring value, jobject result) {
|
||||
char* varStr = java_to_char(env, var, result);
|
||||
if (value == NULL) {
|
||||
if (setenv(varStr, "", 1) != 0) {
|
||||
mark_failed_with_errno(env, "could not putenv()", result);
|
||||
}
|
||||
} else {
|
||||
char* valueStr = java_to_char(env, value, result);
|
||||
if (setenv(varStr, valueStr, 1) != 0) {
|
||||
mark_failed_with_errno(env, "could not putenv()", result);
|
||||
}
|
||||
free(valueStr);
|
||||
}
|
||||
free(varStr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminal functions
|
||||
*/
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixTerminalFunctions_isatty(JNIEnv *env, jclass target, jint output) {
|
||||
struct stat fileInfo;
|
||||
int result;
|
||||
switch (output) {
|
||||
case 0:
|
||||
case 1:
|
||||
return isatty(output+1) ? JNI_TRUE : JNI_FALSE;
|
||||
default:
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixTerminalFunctions_getTerminalSize(JNIEnv *env, jclass target, jint output, jobject dimension, jobject result) {
|
||||
struct winsize screen_size;
|
||||
int retval = ioctl(output+1, TIOCGWINSZ, &screen_size);
|
||||
if (retval != 0) {
|
||||
mark_failed_with_errno(env, "could not fetch terminal size", result);
|
||||
return;
|
||||
}
|
||||
jclass dimensionClass = env->GetObjectClass(dimension);
|
||||
jfieldID widthField = env->GetFieldID(dimensionClass, "cols", "I");
|
||||
env->SetIntField(dimension, widthField, screen_size.ws_col);
|
||||
jfieldID heightField = env->GetFieldID(dimensionClass, "rows", "I");
|
||||
env->SetIntField(dimension, heightField, screen_size.ws_row);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,614 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <windows.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <wchar.h>
|
||||
|
||||
/*
|
||||
* Marks the given result as failed, using the current value of GetLastError()
|
||||
*/
|
||||
void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) {
|
||||
mark_failed_with_code(env, message, GetLastError(), NULL, result);
|
||||
}
|
||||
|
||||
jstring wchar_to_java(JNIEnv* env, const wchar_t* chars, size_t len, jobject result) {
|
||||
if (sizeof(wchar_t) != 2) {
|
||||
mark_failed_with_message(env, "unexpected size of wchar_t", result);
|
||||
return NULL;
|
||||
}
|
||||
return env->NewString((jchar*)chars, len);
|
||||
}
|
||||
|
||||
wchar_t* java_to_wchar(JNIEnv *env, jstring string, jobject result) {
|
||||
jsize len = env->GetStringLength(string);
|
||||
wchar_t* str = (wchar_t*)malloc(sizeof(wchar_t) * (len+1));
|
||||
env->GetStringRegion(string, 0, len, (jchar*)str);
|
||||
str[len] = L'\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) {
|
||||
jclass infoClass = env->GetObjectClass(info);
|
||||
|
||||
OSVERSIONINFOEX versionInfo;
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
if (GetVersionEx((OSVERSIONINFO*)&versionInfo) == 0) {
|
||||
mark_failed_with_errno(env, "could not get version info", result);
|
||||
return;
|
||||
}
|
||||
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetNativeSystemInfo(&systemInfo);
|
||||
jstring arch = NULL;
|
||||
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
|
||||
arch = env->NewStringUTF("amd64");
|
||||
} else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
|
||||
arch = env->NewStringUTF("x86");
|
||||
} else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
|
||||
arch = env->NewStringUTF("ia64");
|
||||
} else {
|
||||
arch = env->NewStringUTF("unknown");
|
||||
}
|
||||
|
||||
jmethodID method = env->GetMethodID(infoClass, "windows", "(IIIZLjava/lang/String;)V");
|
||||
env->CallVoidMethod(info, method, versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
|
||||
versionInfo.dwBuildNumber, versionInfo.wProductType == VER_NT_WORKSTATION,
|
||||
arch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process functions
|
||||
*/
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
|
||||
return GetCurrentProcessId();
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getWorkingDirectory(JNIEnv *env, jclass target, jobject result) {
|
||||
DWORD size = GetCurrentDirectoryW(0, NULL);
|
||||
if (size == 0) {
|
||||
mark_failed_with_errno(env, "could not determine length of working directory path", result);
|
||||
return NULL;
|
||||
}
|
||||
size = size+1; // Needs to include null character
|
||||
wchar_t* path = (wchar_t*)malloc(sizeof(wchar_t) * size);
|
||||
DWORD copied = GetCurrentDirectoryW(size, path);
|
||||
if (copied == 0) {
|
||||
free(path);
|
||||
mark_failed_with_errno(env, "could get working directory path", result);
|
||||
return NULL;
|
||||
}
|
||||
jstring dirName = wchar_to_java(env, path, copied, result);
|
||||
free(path);
|
||||
return dirName;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setWorkingDirectory(JNIEnv *env, jclass target, jstring dir, jobject result) {
|
||||
wchar_t* dirPath = java_to_wchar(env, dir, result);
|
||||
if (dirPath == NULL) {
|
||||
return;
|
||||
}
|
||||
BOOL ok = SetCurrentDirectoryW(dirPath);
|
||||
free(dirPath);
|
||||
if (!ok) {
|
||||
mark_failed_with_errno(env, "could not set current directory", result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jobject result) {
|
||||
wchar_t* varStr = java_to_wchar(env, var, result);
|
||||
DWORD len = GetEnvironmentVariableW(varStr, NULL, 0);
|
||||
if (len == 0) {
|
||||
if (GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
|
||||
mark_failed_with_errno(env, "could not determine length of environment variable", result);
|
||||
}
|
||||
free(varStr);
|
||||
return NULL;
|
||||
}
|
||||
wchar_t* valueStr = (wchar_t*)malloc(sizeof(wchar_t) * len);
|
||||
DWORD copied = GetEnvironmentVariableW(varStr, valueStr, len);
|
||||
if (copied == 0) {
|
||||
if (len > 1) {
|
||||
// If the value is empty, then copied will be 0
|
||||
mark_failed_with_errno(env, "could not get environment variable", result);
|
||||
}
|
||||
free(varStr);
|
||||
free(valueStr);
|
||||
return NULL;
|
||||
}
|
||||
free(varStr);
|
||||
jstring value = wchar_to_java(env, valueStr, copied, result);
|
||||
free(valueStr);
|
||||
return value;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setEnvironmentVariable(JNIEnv *env, jclass target, jstring var, jstring value, jobject result) {
|
||||
wchar_t* varStr = java_to_wchar(env, var, result);
|
||||
wchar_t* valueStr = value == NULL ? NULL : java_to_wchar(env, value, result);
|
||||
BOOL ok = SetEnvironmentVariableW(varStr, valueStr);
|
||||
free(varStr);
|
||||
if (valueStr != NULL) {
|
||||
free(valueStr);
|
||||
}
|
||||
if (!ok && GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
|
||||
mark_failed_with_errno(env, "could not set environment var", result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* File system functions
|
||||
*/
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) {
|
||||
jclass info_class = env->GetObjectClass(info);
|
||||
jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ)V");
|
||||
|
||||
DWORD required = GetLogicalDriveStringsW(0, NULL);
|
||||
if (required == 0) {
|
||||
mark_failed_with_errno(env, "could not determine logical drive buffer size", result);
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t* buffer = (wchar_t*)malloc(sizeof(wchar_t) * (required + 1));
|
||||
wchar_t* deviceName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH + 1));
|
||||
wchar_t* fileSystemName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH + 1));
|
||||
|
||||
if (GetLogicalDriveStringsW(required, buffer) == 0) {
|
||||
mark_failed_with_errno(env, "could not determine logical drives", result);
|
||||
} else {
|
||||
wchar_t* cur = buffer;
|
||||
for (;cur[0] != L'\0'; cur += wcslen(cur) + 1) {
|
||||
DWORD type = GetDriveTypeW(cur);
|
||||
jboolean remote = type == DRIVE_REMOTE;
|
||||
|
||||
// chop off trailing '\'
|
||||
size_t len = wcslen(cur);
|
||||
cur[len-1] = L'\0';
|
||||
|
||||
// create device name \\.\C:
|
||||
wchar_t devPath[7];
|
||||
swprintf(devPath, 7, L"\\\\.\\%s", cur);
|
||||
|
||||
if (QueryDosDeviceW(cur, deviceName, MAX_PATH+1) == 0) {
|
||||
mark_failed_with_errno(env, "could not map device for logical drive", result);
|
||||
break;
|
||||
}
|
||||
cur[len-1] = L'\\';
|
||||
|
||||
DWORD available = 1;
|
||||
if (!remote) {
|
||||
HANDLE hDevice = CreateFileW(devPath, // like "\\.\E:"
|
||||
FILE_READ_ATTRIBUTES, // read access to the attributes
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // share mode
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hDevice != INVALID_HANDLE_VALUE) {
|
||||
DWORD cbBytesReturned;
|
||||
DWORD bSuccess = DeviceIoControl (hDevice, // device to be queried
|
||||
IOCTL_STORAGE_CHECK_VERIFY2,
|
||||
NULL, 0, // no input buffer
|
||||
NULL, 0, // no output buffer
|
||||
&cbBytesReturned, // # bytes returned
|
||||
(LPOVERLAPPED) NULL); // synchronous I/O
|
||||
if (!bSuccess) {
|
||||
available = 0;
|
||||
}
|
||||
CloseHandle(hDevice);
|
||||
}
|
||||
}
|
||||
|
||||
jboolean casePreserving = JNI_TRUE;
|
||||
if (available) {
|
||||
DWORD flags;
|
||||
if (GetVolumeInformationW(cur, NULL, 0, NULL, NULL, &flags, fileSystemName, MAX_PATH+1) == 0) {
|
||||
mark_failed_with_errno(env, "could not get volume information", result);
|
||||
break;
|
||||
}
|
||||
casePreserving = (flags & FILE_CASE_PRESERVED_NAMES) != 0;
|
||||
} else {
|
||||
if (type == DRIVE_CDROM) {
|
||||
swprintf(fileSystemName, MAX_PATH+1, L"cdrom");
|
||||
} else {
|
||||
swprintf(fileSystemName, MAX_PATH+1, L"unknown");
|
||||
}
|
||||
}
|
||||
|
||||
env->CallVoidMethod(info, method,
|
||||
wchar_to_java(env, cur, wcslen(cur), result),
|
||||
wchar_to_java(env, fileSystemName, wcslen(fileSystemName), result),
|
||||
wchar_to_java(env, deviceName, wcslen(deviceName), result),
|
||||
remote, JNI_FALSE, casePreserving);
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
free(deviceName);
|
||||
free(fileSystemName);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Console functions
|
||||
*/
|
||||
|
||||
HANDLE getHandle(JNIEnv *env, int output, jobject result) {
|
||||
HANDLE handle = output == 0 ? GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
mark_failed_with_errno(env, "could not get console handle", result);
|
||||
return NULL;
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_isConsole(JNIEnv *env, jclass target, jint output, jobject result) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||
HANDLE handle = getHandle(env, output, result);
|
||||
if (handle == NULL) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
|
||||
if (GetLastError() == ERROR_INVALID_HANDLE) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_getConsoleSize(JNIEnv *env, jclass target, jint output, jobject dimension, jobject result) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||
HANDLE handle = getHandle(env, output, result);
|
||||
if (handle == NULL) {
|
||||
mark_failed_with_message(env, "not a console", result);
|
||||
return;
|
||||
}
|
||||
if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
|
||||
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||
return;
|
||||
}
|
||||
|
||||
jclass dimensionClass = env->GetObjectClass(dimension);
|
||||
jfieldID widthField = env->GetFieldID(dimensionClass, "cols", "I");
|
||||
env->SetIntField(dimension, widthField, console_info.srWindow.Right - console_info.srWindow.Left + 1);
|
||||
jfieldID heightField = env->GetFieldID(dimensionClass, "rows", "I");
|
||||
env->SetIntField(dimension, heightField, console_info.srWindow.Bottom - console_info.srWindow.Top + 1);
|
||||
}
|
||||
|
||||
HANDLE current_console = NULL;
|
||||
WORD original_attributes = 0;
|
||||
WORD current_attributes = 0;
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_initConsole(JNIEnv *env, jclass target, jint output, jobject result) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||
HANDLE handle = getHandle(env, output, result);
|
||||
if (handle == NULL) {
|
||||
mark_failed_with_message(env, "not a terminal", result);
|
||||
return;
|
||||
}
|
||||
if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
|
||||
if (GetLastError() == ERROR_INVALID_HANDLE) {
|
||||
mark_failed_with_message(env, "not a console", result);
|
||||
} else {
|
||||
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
current_console = handle;
|
||||
original_attributes = console_info.wAttributes;
|
||||
current_attributes = original_attributes;
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_normal(env, target, result);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_bold(JNIEnv *env, jclass target, jobject result) {
|
||||
current_attributes |= FOREGROUND_INTENSITY;
|
||||
if (!SetConsoleTextAttribute(current_console, current_attributes)) {
|
||||
mark_failed_with_errno(env, "could not set text attributes", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_normal(JNIEnv *env, jclass target, jobject result) {
|
||||
current_attributes &= ~FOREGROUND_INTENSITY;
|
||||
if (!SetConsoleTextAttribute(current_console, current_attributes)) {
|
||||
mark_failed_with_errno(env, "could not set text attributes", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_reset(JNIEnv *env, jclass target, jobject result) {
|
||||
current_attributes = original_attributes;
|
||||
if (!SetConsoleTextAttribute(current_console, current_attributes)) {
|
||||
mark_failed_with_errno(env, "could not set text attributes", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_foreground(JNIEnv *env, jclass target, jint color, jobject result) {
|
||||
current_attributes &= ~ (FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN);
|
||||
switch (color) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
current_attributes |= FOREGROUND_RED;
|
||||
break;
|
||||
case 2:
|
||||
current_attributes |= FOREGROUND_GREEN;
|
||||
break;
|
||||
case 3:
|
||||
current_attributes |= FOREGROUND_RED|FOREGROUND_GREEN;
|
||||
break;
|
||||
case 4:
|
||||
current_attributes |= FOREGROUND_BLUE;
|
||||
break;
|
||||
case 5:
|
||||
current_attributes |= FOREGROUND_RED|FOREGROUND_BLUE;
|
||||
break;
|
||||
case 6:
|
||||
current_attributes |= FOREGROUND_GREEN|FOREGROUND_BLUE;
|
||||
break;
|
||||
default:
|
||||
current_attributes |= FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!SetConsoleTextAttribute(current_console, current_attributes)) {
|
||||
mark_failed_with_errno(env, "could not set text attributes", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_left(JNIEnv *env, jclass target, jint count, jobject result) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||
if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
|
||||
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||
return;
|
||||
}
|
||||
console_info.dwCursorPosition.X -= count;
|
||||
if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
|
||||
mark_failed_with_errno(env, "could not set cursor position", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_right(JNIEnv *env, jclass target, jint count, jobject result) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||
if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
|
||||
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||
return;
|
||||
}
|
||||
console_info.dwCursorPosition.X += count;
|
||||
if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
|
||||
mark_failed_with_errno(env, "could not set cursor position", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_up(JNIEnv *env, jclass target, jint count, jobject result) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||
if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
|
||||
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||
return;
|
||||
}
|
||||
console_info.dwCursorPosition.Y -= count;
|
||||
if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
|
||||
mark_failed_with_errno(env, "could not set cursor position", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_down(JNIEnv *env, jclass target, jint count, jobject result) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||
if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
|
||||
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||
return;
|
||||
}
|
||||
console_info.dwCursorPosition.Y += count;
|
||||
if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
|
||||
mark_failed_with_errno(env, "could not set cursor position", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_startLine(JNIEnv *env, jclass target, jobject result) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||
if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
|
||||
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||
return;
|
||||
}
|
||||
console_info.dwCursorPosition.X = 0;
|
||||
if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
|
||||
mark_failed_with_errno(env, "could not set cursor position", result);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_clearToEndOfLine(JNIEnv *env, jclass target, jobject result) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||
if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
|
||||
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||
return;
|
||||
}
|
||||
DWORD count;
|
||||
if (!FillConsoleOutputCharacterW(current_console, L' ', console_info.dwSize.X - console_info.dwCursorPosition.X, console_info.dwCursorPosition, &count)) {
|
||||
mark_failed_with_errno(env, "could not clear console", result);
|
||||
}
|
||||
}
|
||||
|
||||
void uninheritStream(JNIEnv *env, DWORD stdInputHandle, jobject result) {
|
||||
HANDLE streamHandle = GetStdHandle(stdInputHandle);
|
||||
if (streamHandle == NULL) {
|
||||
// We're not attached to a stdio (eg Desktop application). Ignore.
|
||||
return;
|
||||
}
|
||||
if (streamHandle == INVALID_HANDLE_VALUE) {
|
||||
mark_failed_with_errno(env, "could not get std handle", result);
|
||||
return;
|
||||
}
|
||||
boolean ok = SetHandleInformation(streamHandle, HANDLE_FLAG_INHERIT, 0);
|
||||
if (!ok) {
|
||||
if (GetLastError() != ERROR_INVALID_PARAMETER && GetLastError() != ERROR_INVALID_HANDLE) {
|
||||
mark_failed_with_errno(env, "could not change std handle", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsHandleFunctions_markStandardHandlesUninheritable(JNIEnv *env, jclass target, jobject result) {
|
||||
uninheritStream(env, STD_INPUT_HANDLE, result);
|
||||
uninheritStream(env, STD_OUTPUT_HANDLE, result);
|
||||
uninheritStream(env, STD_ERROR_HANDLE, result);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsHandleFunctions_restoreStandardHandles(JNIEnv *env, jclass target, jobject result) {
|
||||
}
|
||||
|
||||
HKEY get_key_from_ordinal(jint keyNum) {
|
||||
return keyNum == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsRegistryFunctions_getStringValue(JNIEnv *env, jclass target, jint keyNum, jstring subkey, jstring valueName, jobject result) {
|
||||
HKEY key = get_key_from_ordinal(keyNum);
|
||||
wchar_t* subkeyStr = java_to_wchar(env, subkey, result);
|
||||
wchar_t* valueNameStr = java_to_wchar(env, valueName, result);
|
||||
DWORD size = 0;
|
||||
|
||||
LONG retval = SHRegGetValueW(key, subkeyStr, valueNameStr, SRRF_RT_REG_SZ, NULL, NULL, &size);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
free(subkeyStr);
|
||||
free(valueNameStr);
|
||||
if (retval != ERROR_FILE_NOT_FOUND) {
|
||||
mark_failed_with_code(env, "could not determine size of registry value", retval, NULL, result);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t* value = (wchar_t*)malloc(sizeof(wchar_t) * (size+1));
|
||||
retval = SHRegGetValueW(key, subkeyStr, valueNameStr, SRRF_RT_REG_SZ, NULL, value, &size);
|
||||
free(subkeyStr);
|
||||
free(valueNameStr);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
free(value);
|
||||
mark_failed_with_code(env, "could not get registry value", retval, NULL, result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jstring jvalue = wchar_to_java(env, value, wcslen(value), result);
|
||||
free(value);
|
||||
|
||||
return jvalue;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsRegistryFunctions_getSubkeys(JNIEnv *env, jclass target, jint keyNum, jstring subkey, jobject subkeys, jobject result) {
|
||||
wchar_t* subkeyStr = java_to_wchar(env, subkey, result);
|
||||
jclass subkeys_class = env->GetObjectClass(subkeys);
|
||||
jmethodID method = env->GetMethodID(subkeys_class, "add", "(Ljava/lang/Object;)Z");
|
||||
|
||||
HKEY key;
|
||||
LONG retval = RegOpenKeyExW(get_key_from_ordinal(keyNum), subkeyStr, 0, KEY_READ, &key);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
free(subkeyStr);
|
||||
if (retval != ERROR_FILE_NOT_FOUND) {
|
||||
mark_failed_with_code(env, "could open registry key", retval, NULL, result);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD subkeyCount;
|
||||
DWORD maxSubkeyLen;
|
||||
retval = RegQueryInfoKeyW(key, NULL, NULL, NULL, &subkeyCount, &maxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
mark_failed_with_code(env, "could query registry key", retval, NULL, result);
|
||||
} else {
|
||||
wchar_t* keyNameStr = (wchar_t*)malloc(sizeof(wchar_t) * (maxSubkeyLen+1));
|
||||
for (int i = 0; i < subkeyCount; i++) {
|
||||
DWORD keyNameLen = maxSubkeyLen + 1;
|
||||
retval = RegEnumKeyExW(key, i, keyNameStr, &keyNameLen, NULL, NULL, NULL, NULL);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
mark_failed_with_code(env, "could enumerate registry subkey", retval, NULL, result);
|
||||
break;
|
||||
}
|
||||
env->CallVoidMethod(subkeys, method, wchar_to_java(env, keyNameStr, wcslen(keyNameStr), result));
|
||||
}
|
||||
free(keyNameStr);
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
free(subkeyStr);
|
||||
return true;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsRegistryFunctions_getValueNames(JNIEnv *env, jclass target, jint keyNum, jstring subkey, jobject names, jobject result) {
|
||||
wchar_t* subkeyStr = java_to_wchar(env, subkey, result);
|
||||
jclass names_class = env->GetObjectClass(names);
|
||||
jmethodID method = env->GetMethodID(names_class, "add", "(Ljava/lang/Object;)Z");
|
||||
|
||||
HKEY key;
|
||||
LONG retval = RegOpenKeyExW(get_key_from_ordinal(keyNum), subkeyStr, 0, KEY_READ, &key);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
free(subkeyStr);
|
||||
if (retval != ERROR_FILE_NOT_FOUND) {
|
||||
mark_failed_with_code(env, "could open registry key", retval, NULL, result);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD valueCount;
|
||||
DWORD maxValueNameLen;
|
||||
retval = RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL, &valueCount, &maxValueNameLen, NULL, NULL, NULL);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
mark_failed_with_code(env, "could query registry key", retval, NULL, result);
|
||||
} else {
|
||||
wchar_t* valueNameStr = (wchar_t*)malloc(sizeof(wchar_t) * (maxValueNameLen+1));
|
||||
for (int i = 0; i < valueCount; i++) {
|
||||
DWORD valueNameLen = maxValueNameLen + 1;
|
||||
retval = RegEnumValueW(key, i, valueNameStr, &valueNameLen, NULL, NULL, NULL, NULL);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
mark_failed_with_code(env, "could enumerate registry value name", retval, NULL, result);
|
||||
break;
|
||||
}
|
||||
env->CallVoidMethod(names, method, wchar_to_java(env, valueNameStr, wcslen(valueNameStr), result));
|
||||
}
|
||||
free(valueNameStr);
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
free(subkeyStr);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic cross-platform functions.
|
||||
*/
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
|
||||
void mark_failed_with_message(JNIEnv *env, const char* message, jobject result) {
|
||||
mark_failed_with_code(env, message, 0, NULL, result);
|
||||
}
|
||||
|
||||
void mark_failed_with_code(JNIEnv *env, const char* message, int error_code, const char* error_code_message, jobject result) {
|
||||
jclass destClass = env->GetObjectClass(result);
|
||||
jmethodID method = env->GetMethodID(destClass, "failed", "(Ljava/lang/String;ILjava/lang/String;)V");
|
||||
jstring message_str = env->NewStringUTF(message);
|
||||
jstring error_code_str = error_code_message == NULL ? NULL : env->NewStringUTF(error_code_message);
|
||||
env->CallVoidMethod(result, method, message_str, error_code, error_code_str);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getVersion(JNIEnv *env, jclass target) {
|
||||
return NATIVE_VERSION;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* POSIX platform functions.
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <errno.h>
|
||||
|
||||
void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) {
|
||||
const char * errno_message = NULL;
|
||||
switch(errno) {
|
||||
case ENOENT:
|
||||
errno_message = "ENOENT";
|
||||
break;
|
||||
}
|
||||
|
||||
mark_failed_with_code(env, message, errno, errno_message, result);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* POSIX platform functions.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
char* java_to_char(JNIEnv *env, jstring string, jobject result) {
|
||||
size_t len = env->GetStringLength(string);
|
||||
size_t bytes = env->GetStringUTFLength(string);
|
||||
char* chars = (char*)malloc(bytes + 1);
|
||||
env->GetStringUTFRegion(string, 0, len, chars);
|
||||
chars[bytes] = 0;
|
||||
return chars;
|
||||
}
|
||||
|
||||
jstring char_to_java(JNIEnv* env, const char* chars, jobject result) {
|
||||
return env->NewStringUTF(chars);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* UNIX string conversion functions.
|
||||
*/
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
char* java_to_char(JNIEnv *env, jstring string, jobject result) {
|
||||
size_t stringLen = env->GetStringLength(string);
|
||||
wchar_t* wideString = (wchar_t*)malloc(sizeof(wchar_t) * (stringLen+1));
|
||||
const jchar* javaString = env->GetStringChars(string, NULL);
|
||||
for (size_t i = 0; i < stringLen; i++) {
|
||||
wideString[i] = javaString[i];
|
||||
}
|
||||
wideString[stringLen] = L'\0';
|
||||
env->ReleaseStringChars(string, javaString);
|
||||
|
||||
size_t bytes = wcstombs(NULL, wideString, 0);
|
||||
if (bytes == (size_t)-1) {
|
||||
mark_failed_with_message(env, "could not convert string to current locale", result);
|
||||
free(wideString);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* chars = (char*)malloc(bytes + 1);
|
||||
wcstombs(chars, wideString, bytes+1);
|
||||
free(wideString);
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
jstring char_to_java(JNIEnv* env, const char* chars, jobject result) {
|
||||
size_t bytes = strlen(chars);
|
||||
wchar_t* wideString = (wchar_t*)malloc(sizeof(wchar_t) * (bytes+1));
|
||||
if (mbstowcs(wideString, chars, bytes+1) == (size_t)-1) {
|
||||
mark_failed_with_message(env, "could not convert string from current locale", result);
|
||||
free(wideString);
|
||||
return NULL;
|
||||
}
|
||||
size_t stringLen = wcslen(wideString);
|
||||
jchar* javaString = (jchar*)malloc(sizeof(jchar) * stringLen);
|
||||
for (int i =0; i < stringLen; i++) {
|
||||
javaString[i] = (jchar)wideString[i];
|
||||
}
|
||||
jstring string = env->NewString(javaString, stringLen);
|
||||
free(wideString);
|
||||
free(javaString);
|
||||
return string;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDE_GENERIC_H__
|
||||
#define __INCLUDE_GENERIC_H__
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NATIVE_VERSION 20
|
||||
|
||||
/*
|
||||
* Marks the given result as failed, using the given error message
|
||||
*/
|
||||
extern void mark_failed_with_message(JNIEnv *env, const char* message, jobject result);
|
||||
|
||||
/*
|
||||
* Marks the given result as failed, using the given error message and the current value of errno/GetLastError()
|
||||
*/
|
||||
extern void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result);
|
||||
|
||||
/*
|
||||
* Marks the given result as failed, using the given error message and error code
|
||||
*/
|
||||
extern void mark_failed_with_code(JNIEnv *env, const char* message, int error_code, const char* error_code_message, jobject result);
|
||||
|
||||
/*
|
||||
* Converts the given Java string to a NULL terminated wchar_str. Should call free() when finished.
|
||||
*
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
extern wchar_t*
|
||||
java_to_wchar(JNIEnv *env, jstring string, jobject result);
|
||||
|
||||
/*
|
||||
* Converts the given wchar_t string to a Java string.
|
||||
*
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
extern jstring wchar_to_java(JNIEnv* env, const wchar_t* chars, size_t len, jobject result);
|
||||
|
||||
/*
|
||||
* Converts the given Java string to a NULL terminated char string. Should call free() when finished.
|
||||
*
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
extern char* java_to_char(JNIEnv *env, jstring string, jobject result);
|
||||
|
||||
/*
|
||||
* Converts the given NULL terminated char string to a Java string.
|
||||
*
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
extern jstring char_to_java(JNIEnv* env, const char* chars, jobject result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.rubygrapefruit.platform
|
||||
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import spock.lang.Specification
|
||||
|
||||
class FileSystemsTest extends Specification {
|
||||
@Rule TemporaryFolder tmpDir
|
||||
final FileSystems fileSystems = Native.get(FileSystems.class)
|
||||
|
||||
def "caches file systems instance"() {
|
||||
expect:
|
||||
Native.get(FileSystems.class) == fileSystems
|
||||
}
|
||||
|
||||
def "can query filesystem details"() {
|
||||
expect:
|
||||
fileSystems.fileSystems.collect() { it.mountPoint }.containsAll(File.listRoots())
|
||||
}
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.rubygrapefruit.platform
|
||||
|
||||
import spock.lang.Specification
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import spock.lang.IgnoreIf
|
||||
import net.rubygrapefruit.platform.internal.Platform
|
||||
|
||||
@IgnoreIf({Platform.current().windows})
|
||||
class PosixFilesTest extends Specification {
|
||||
@Rule TemporaryFolder tmpDir
|
||||
final PosixFiles file = Native.get(PosixFiles.class)
|
||||
|
||||
def "caches file instance"() {
|
||||
expect:
|
||||
Native.get(PosixFiles.class) == file
|
||||
}
|
||||
|
||||
def "can get details of a file"() {
|
||||
def testFile = tmpDir.newFile(fileName)
|
||||
|
||||
when:
|
||||
def stat = file.stat(testFile)
|
||||
|
||||
then:
|
||||
stat.type == PosixFile.Type.File
|
||||
stat.mode != 0
|
||||
|
||||
where:
|
||||
fileName << ["test.txt", "test\u03b1\u2295.txt"]
|
||||
}
|
||||
|
||||
def "can get details of a directory"() {
|
||||
def testFile = tmpDir.newFolder(fileName)
|
||||
|
||||
when:
|
||||
def stat = file.stat(testFile)
|
||||
|
||||
then:
|
||||
stat.type == PosixFile.Type.Directory
|
||||
stat.mode != 0
|
||||
|
||||
where:
|
||||
fileName << ["test-dir", "test\u03b1\u2295-dir"]
|
||||
}
|
||||
|
||||
def "can get details of a missing file"() {
|
||||
def testFile = new File(tmpDir.root, fileName)
|
||||
|
||||
when:
|
||||
def stat = file.stat(testFile)
|
||||
|
||||
then:
|
||||
stat.type == PosixFile.Type.Missing
|
||||
stat.mode == 0
|
||||
|
||||
where:
|
||||
fileName << ["test-dir", "test\u03b1\u2295-dir"]
|
||||
}
|
||||
|
||||
def "can set mode on a file"() {
|
||||
def testFile = tmpDir.newFile(fileName)
|
||||
|
||||
when:
|
||||
file.setMode(testFile, 0740)
|
||||
|
||||
then:
|
||||
file.getMode(testFile) == 0740
|
||||
file.stat(testFile).mode == 0740
|
||||
|
||||
where:
|
||||
fileName << ["test.txt", "test\u03b1\u2295.txt"]
|
||||
}
|
||||
|
||||
def "can set mode on a directory"() {
|
||||
def testFile = tmpDir.newFolder(fileName)
|
||||
|
||||
when:
|
||||
file.setMode(testFile, 0740)
|
||||
|
||||
then:
|
||||
file.getMode(testFile) == 0740
|
||||
file.stat(testFile).mode == 0740
|
||||
|
||||
where:
|
||||
fileName << ["test-dir", "test\u03b1\u2295-dir"]
|
||||
}
|
||||
|
||||
def "cannot set mode on file that does not exist"() {
|
||||
def testFile = new File(tmpDir.root, "unknown")
|
||||
|
||||
when:
|
||||
file.setMode(testFile, 0660)
|
||||
|
||||
then:
|
||||
NativeException e = thrown()
|
||||
e.message == "Could not set UNIX mode on $testFile: could not chmod file (ENOENT errno 2)"
|
||||
}
|
||||
|
||||
def "cannot get mode on file that does not exist"() {
|
||||
def testFile = new File(tmpDir.root, "unknown")
|
||||
|
||||
when:
|
||||
file.getMode(testFile)
|
||||
|
||||
then:
|
||||
NativeException e = thrown()
|
||||
e.message == "Could not get UNIX mode on $testFile: file does not exist."
|
||||
}
|
||||
|
||||
def "can create symbolic link"() {
|
||||
def testFile = new File(tmpDir.root, "test.txt")
|
||||
testFile.text = "hi"
|
||||
def symlinkFile = new File(tmpDir.root, "symlink")
|
||||
|
||||
when:
|
||||
file.symlink(symlinkFile, testFile.name)
|
||||
|
||||
then:
|
||||
symlinkFile.file
|
||||
symlinkFile.text == "hi"
|
||||
symlinkFile.canonicalFile == testFile.canonicalFile
|
||||
}
|
||||
|
||||
def "can read symbolic link"() {
|
||||
def symlinkFile = new File(tmpDir.root, "symlink")
|
||||
|
||||
when:
|
||||
file.symlink(symlinkFile, "target")
|
||||
|
||||
then:
|
||||
file.readLink(symlinkFile) == "target"
|
||||
}
|
||||
|
||||
def "cannot read a symlink that does not exist"() {
|
||||
def symlinkFile = new File(tmpDir.root, "symlink")
|
||||
|
||||
when:
|
||||
file.readLink(symlinkFile)
|
||||
|
||||
then:
|
||||
NativeException e = thrown()
|
||||
e.message == "Could not read symlink $symlinkFile: could not lstat file (ENOENT errno 2)"
|
||||
}
|
||||
|
||||
def "cannot read a symlink that is not a symlink"() {
|
||||
def symlinkFile = tmpDir.newFile("not-a-symlink.txt")
|
||||
|
||||
when:
|
||||
file.readLink(symlinkFile)
|
||||
|
||||
then:
|
||||
NativeException e = thrown()
|
||||
e.message == "Could not read symlink $symlinkFile: could not readlink (errno 22)"
|
||||
}
|
||||
|
||||
def "can create and read symlink with unicode in its name"() {
|
||||
def testFile = new File(tmpDir.root, "target\u03b2\u2295")
|
||||
testFile.text = 'hi'
|
||||
def symlinkFile = new File(tmpDir.root, "symlink\u03b2\u2296")
|
||||
|
||||
when:
|
||||
file.symlink(symlinkFile, testFile.name)
|
||||
|
||||
then:
|
||||
file.readLink(symlinkFile) == testFile.name
|
||||
symlinkFile.file
|
||||
symlinkFile.canonicalFile == testFile.canonicalFile
|
||||
}
|
||||
|
||||
def "can get details of a symlink"() {
|
||||
def testFile = new File(tmpDir.newFolder("parent"), fileName)
|
||||
|
||||
given:
|
||||
file.symlink(testFile, "target")
|
||||
|
||||
when:
|
||||
def stat = file.stat(testFile)
|
||||
|
||||
then:
|
||||
stat.type == PosixFile.Type.Symlink
|
||||
stat.mode != 0
|
||||
|
||||
where:
|
||||
fileName << ["test.txt", "test\u03b1\u2295.txt"]
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.rubygrapefruit.platform
|
||||
|
||||
import spock.lang.Specification
|
||||
|
||||
class ProcessLauncherTest extends Specification {
|
||||
final ProcessLauncher launcher = Native.get(ProcessLauncher)
|
||||
|
||||
def "can start a child process"() {
|
||||
def javaHome = System.getProperty("java.home")
|
||||
def exe = "${javaHome}/bin/java"
|
||||
ProcessBuilder builder = new ProcessBuilder(exe, "-version")
|
||||
builder.redirectErrorStream(true)
|
||||
|
||||
when:
|
||||
def process = launcher.start(builder)
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
def stdoutThread = process.consumeProcessOutputStream(stdout)
|
||||
def result = process.waitFor()
|
||||
stdoutThread.join()
|
||||
|
||||
then:
|
||||
result == 0
|
||||
stdout.toString().contains(System.getProperty('java.vm.version'))
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.rubygrapefruit.platform
|
||||
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import spock.lang.Specification
|
||||
|
||||
class ProcessTest extends Specification {
|
||||
@Rule TemporaryFolder tmpDir
|
||||
final Process process = Native.get(Process.class)
|
||||
|
||||
def "caches process instance"() {
|
||||
expect:
|
||||
Native.get(Process.class) == process
|
||||
}
|
||||
|
||||
def "can get PID"() {
|
||||
expect:
|
||||
process.getProcessId() != 0
|
||||
}
|
||||
|
||||
def "can get and change working directory"() {
|
||||
def newDir = tmpDir.newFolder(dir).canonicalFile
|
||||
assert newDir.directory
|
||||
|
||||
when:
|
||||
def original = process.workingDirectory
|
||||
|
||||
then:
|
||||
original == new File(".").canonicalFile
|
||||
original == new File(System.getProperty("user.dir"))
|
||||
|
||||
when:
|
||||
process.workingDirectory = newDir
|
||||
|
||||
then:
|
||||
process.workingDirectory == newDir
|
||||
new File(".").canonicalFile == newDir
|
||||
new File(System.getProperty("user.dir")) == newDir
|
||||
|
||||
cleanup:
|
||||
process.workingDirectory = original
|
||||
|
||||
where:
|
||||
dir << ['dir', 'dir\u03b1\u2295']
|
||||
}
|
||||
|
||||
def "cannot set working directory to a directory that does not exist"() {
|
||||
def newDir = new File(tmpDir.root, "does not exist");
|
||||
|
||||
when:
|
||||
process.workingDirectory = newDir
|
||||
|
||||
then:
|
||||
NativeException e = thrown()
|
||||
e.message.startsWith("Could not set process working directory")
|
||||
}
|
||||
|
||||
def "can get and set and remove environment variable"() {
|
||||
when:
|
||||
def value = process.getEnvironmentVariable(varName)
|
||||
|
||||
then:
|
||||
value == null
|
||||
System.getenv(varName) == null
|
||||
System.getenv()[varName] == null
|
||||
|
||||
when:
|
||||
process.setEnvironmentVariable(varName, varValue)
|
||||
|
||||
then:
|
||||
process.getEnvironmentVariable(varName) == varValue
|
||||
System.getenv(varName) == varValue
|
||||
System.getenv()[varName] == varValue
|
||||
|
||||
when:
|
||||
process.setEnvironmentVariable(varName, null)
|
||||
|
||||
then:
|
||||
process.getEnvironmentVariable(varName) == null
|
||||
System.getenv(varName) == null
|
||||
System.getenv()[varName] == null
|
||||
|
||||
where:
|
||||
varName | varValue
|
||||
'TEST_ENV_VAR' | 'test value'
|
||||
'TEST_ENV_VAR\u2295\u03b1' | 'value\u03b2\u2296'
|
||||
}
|
||||
|
||||
def "setting environment variable to null or empty string remove the environment variable"() {
|
||||
when:
|
||||
def value = process.getEnvironmentVariable(varName)
|
||||
|
||||
then:
|
||||
value == null
|
||||
System.getenv(varName) == null
|
||||
System.getenv()[varName] == null
|
||||
|
||||
when:
|
||||
process.setEnvironmentVariable(varName, varValue)
|
||||
|
||||
then:
|
||||
process.getEnvironmentVariable(varName) == null
|
||||
System.getenv(varName) == null
|
||||
System.getenv()[varName] == null
|
||||
|
||||
where:
|
||||
varName | varValue
|
||||
'TEST_ENV_VAR_EMPTY' | ''
|
||||
'TEST_ENV_VAR_NULL' | null
|
||||
}
|
||||
|
||||
def "can remove environment variable that does not exist"() {
|
||||
assert process.getEnvironmentVariable("TEST_ENV_UNKNOWN") == null
|
||||
|
||||
when:
|
||||
process.setEnvironmentVariable("TEST_ENV_UNKNOWN", null)
|
||||
|
||||
then:
|
||||
notThrown(NativeException)
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.rubygrapefruit.platform
|
||||
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import spock.lang.Specification
|
||||
|
||||
class SystemInfoTest extends Specification {
|
||||
@Rule TemporaryFolder tmpDir
|
||||
final SystemInfo systemInfo = Native.get(SystemInfo.class)
|
||||
|
||||
def "caches system info instance"() {
|
||||
expect:
|
||||
Native.get(SystemInfo.class) == systemInfo
|
||||
}
|
||||
|
||||
def "can query OS details"() {
|
||||
expect:
|
||||
systemInfo.kernelName
|
||||
systemInfo.kernelVersion
|
||||
systemInfo.architectureName
|
||||
systemInfo.architecture
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.rubygrapefruit.platform
|
||||
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import spock.lang.Specification
|
||||
import net.rubygrapefruit.platform.internal.Platform
|
||||
import spock.lang.IgnoreIf
|
||||
|
||||
class TerminalsTest extends Specification {
|
||||
@Rule TemporaryFolder tmpDir
|
||||
final Terminals terminals = Native.get(Terminals.class)
|
||||
|
||||
def "caches terminals instance"() {
|
||||
expect:
|
||||
Native.get(Terminals.class) == terminals
|
||||
}
|
||||
|
||||
def "can check if attached to terminal"() {
|
||||
expect:
|
||||
!terminals.isTerminal(Terminals.Output.Stdout);
|
||||
!terminals.isTerminal(Terminals.Output.Stderr);
|
||||
}
|
||||
|
||||
@IgnoreIf({Platform.current().windows})
|
||||
def "cannot access posix terminal from a test"() {
|
||||
when:
|
||||
terminals.getTerminal(Terminals.Output.Stdout)
|
||||
|
||||
then:
|
||||
NativeException e = thrown()
|
||||
e.message == 'Could not open terminal for stdout: not a terminal'
|
||||
}
|
||||
|
||||
@IgnoreIf({!Platform.current().windows})
|
||||
def "cannot access windows console from a test"() {
|
||||
when:
|
||||
terminals.getTerminal(Terminals.Output.Stdout)
|
||||
|
||||
then:
|
||||
NativeException e = thrown()
|
||||
e.message == 'Could not open console for stdout: not a console'
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package net.rubygrapefruit.platform
|
||||
|
||||
import net.rubygrapefruit.platform.internal.Platform
|
||||
import spock.lang.IgnoreIf
|
||||
import spock.lang.Specification
|
||||
|
||||
@IgnoreIf({!Platform.current().windows})
|
||||
class WindowsRegistryTest extends Specification {
|
||||
def windowsRegistry = Native.get(WindowsRegistry)
|
||||
|
||||
def "can read string value"() {
|
||||
expect:
|
||||
def currentVersion = windowsRegistry.getStringValue(WindowsRegistry.Key.HKEY_LOCAL_MACHINE, /SOFTWARE\Microsoft\Windows NT\CurrentVersion/, "CurrentVersion")
|
||||
currentVersion.matches("\\d+\\.\\d+")
|
||||
def path = new File(windowsRegistry.getStringValue(WindowsRegistry.Key.HKEY_CURRENT_USER, "Volatile Environment", "APPDATA"))
|
||||
path.directory
|
||||
}
|
||||
|
||||
def "cannot read value that does not exist"() {
|
||||
when:
|
||||
windowsRegistry.getStringValue(WindowsRegistry.Key.HKEY_LOCAL_MACHINE, /SOFTWARE\Microsoft\Windows NT\CurrentVersion/, "Unknown")
|
||||
|
||||
then:
|
||||
def e = thrown(MissingRegistryEntryException)
|
||||
e.message == /Could not get value 'Unknown' of registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion' as it does not exist./
|
||||
}
|
||||
|
||||
def "cannot read value of key that does not exist"() {
|
||||
when:
|
||||
windowsRegistry.getStringValue(WindowsRegistry.Key.HKEY_LOCAL_MACHINE, /SOFTWARE\Unknown/, "Value")
|
||||
|
||||
then:
|
||||
def e = thrown(MissingRegistryEntryException)
|
||||
e.message == /Could not get value 'Value' of registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Unknown' as it does not exist./
|
||||
}
|
||||
|
||||
def "can list subkeys of a key"() {
|
||||
expect:
|
||||
windowsRegistry.getSubkeys(WindowsRegistry.Key.HKEY_LOCAL_MACHINE, /SOFTWARE\Microsoft/).flatten().contains("Windows NT")
|
||||
}
|
||||
|
||||
def "cannot list subkeys of key that does not exist"() {
|
||||
when:
|
||||
windowsRegistry.getSubkeys(WindowsRegistry.Key.HKEY_LOCAL_MACHINE, /SOFTWARE\Unknown/)
|
||||
|
||||
then:
|
||||
def e = thrown(MissingRegistryEntryException)
|
||||
e.message == /Could not list the subkeys of registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Unknown' as it does not exist./
|
||||
}
|
||||
|
||||
def "cannot list values of a key"() {
|
||||
expect:
|
||||
windowsRegistry.getValueNames(WindowsRegistry.Key.HKEY_LOCAL_MACHINE, /SOFTWARE\Microsoft\Windows NT\CurrentVersion/).flatten().contains("CurrentVersion")
|
||||
}
|
||||
|
||||
def "cannot list values of key that does not exist"() {
|
||||
when:
|
||||
windowsRegistry.getValueNames(WindowsRegistry.Key.HKEY_LOCAL_MACHINE, /SOFTWARE\Unknown/)
|
||||
|
||||
then:
|
||||
def e = thrown(MissingRegistryEntryException)
|
||||
e.message == /Could not list the values of registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Unknown' as it does not exist./
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
apply plugin: 'application'
|
||||
|
||||
mainClassName = 'net.rubygrapefruit.platform.test.Main'
|
||||
applicationName = 'native-platform-test'
|
||||
archivesBaseName = 'native-platform-test'
|
||||
|
||||
if (project.hasProperty('release')) {
|
||||
repositories {
|
||||
maven { url "$rootProject.buildDir/repo" }
|
||||
}
|
||||
dependencies {
|
||||
compile "net.rubygrapefruit:native-platform:${version}"
|
||||
}
|
||||
} else {
|
||||
dependencies {
|
||||
compile project(':')
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'net.sf.jopt-simple:jopt-simple:4.2'
|
||||
}
|
||||
|
||||
configurations.archives.artifacts.clear()
|
||||
artifacts {
|
||||
archives distZip
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Adam Murdoch
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.rubygrapefruit.platform.test;
|
||||
|
||||
import joptsimple.OptionException;
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
import net.rubygrapefruit.platform.*;
|
||||
import net.rubygrapefruit.platform.Process;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws IOException {
|
||||
OptionParser optionParser = new OptionParser();
|
||||
optionParser.accepts("cache-dir", "The directory to cache native libraries in").withRequiredArg();
|
||||
|
||||
OptionSet result = null;
|
||||
try {
|
||||
result = optionParser.parse(args);
|
||||
} catch (OptionException e) {
|
||||
System.err.println(e.getMessage());
|
||||
System.err.println();
|
||||
optionParser.printHelpOn(System.err);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
if (result.has("cache-dir")) {
|
||||
Native.init(new File(result.valueOf("cache-dir").toString()));
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("* JVM: " + System.getProperty("java.vm.vendor") + ' ' + System.getProperty("java.version"));
|
||||
System.out.println("* OS (JVM): " + System.getProperty("os.name") + ' ' + System.getProperty("os.version") + ' ' + System.getProperty("os.arch"));
|
||||
|
||||
SystemInfo systemInfo = Native.get(SystemInfo.class);
|
||||
System.out.println("* OS (Kernel): " + systemInfo.getKernelName() + ' ' + systemInfo.getKernelVersion() + ' ' + systemInfo.getArchitectureName() + " (" + systemInfo.getArchitecture() + ")");
|
||||
|
||||
Process process = Native.get(Process.class);
|
||||
System.out.println("* PID: " + process.getProcessId());
|
||||
|
||||
FileSystems fileSystems = Native.get(FileSystems.class);
|
||||
System.out.println("* File systems: ");
|
||||
for (FileSystem fileSystem : fileSystems.getFileSystems()) {
|
||||
System.out.println(String.format(" * %s -> %s (type: %s %s, case sensitive: %s, case preserving: %s)",
|
||||
fileSystem.getMountPoint(), fileSystem.getDeviceName(), fileSystem.getFileSystemType(),
|
||||
fileSystem.isRemote() ? "remote" : "local", fileSystem.isCaseSensitive(), fileSystem.isCasePreserving()));
|
||||
}
|
||||
|
||||
Terminals terminals = Native.get(Terminals.class);
|
||||
boolean stdoutIsTerminal = terminals.isTerminal(Terminals.Output.Stdout);
|
||||
boolean stderrIsTerminal = terminals.isTerminal(Terminals.Output.Stderr);
|
||||
System.out.println("* Stdout: " + (stdoutIsTerminal ? "terminal" : "not a terminal"));
|
||||
System.out.println("* Stderr: " + (stderrIsTerminal ? "terminal" : "not a terminal"));
|
||||
if (stdoutIsTerminal) {
|
||||
Terminal terminal = terminals.getTerminal(Terminals.Output.Stdout);
|
||||
TerminalSize terminalSize = terminal.getTerminalSize();
|
||||
System.out.println("* Terminal implementation: " + terminal);
|
||||
System.out.println("* Terminal size: " + terminalSize.getCols() + " cols x " + terminalSize.getRows() + " rows");
|
||||
System.out.println("* Text attributes: " + (terminal.supportsTextAttributes() ? "yes" : "no"));
|
||||
System.out.println("* Color: " + (terminal.supportsColor() ? "yes" : "no"));
|
||||
System.out.println("* Cursor motion: " + (terminal.supportsCursorMotion() ? "yes" : "no"));
|
||||
System.out.println();
|
||||
System.out.println("TEXT ATTRIBUTES");
|
||||
System.out.print("[normal] ");
|
||||
terminal.bold();
|
||||
System.out.print("[bold]");
|
||||
terminal.normal();
|
||||
System.out.println(" [normal]");
|
||||
System.out.println();
|
||||
|
||||
System.out.println("COLORS");
|
||||
for (Terminal.Color color : Terminal.Color.values()) {
|
||||
terminal.foreground(color);
|
||||
terminal.bold();
|
||||
System.out.print(String.format("[%s] ", color.toString().toLowerCase()));
|
||||
terminal.normal();
|
||||
System.out.print(String.format("[%s]", color.toString().toLowerCase()));
|
||||
System.out.println();
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
terminal.reset();
|
||||
|
||||
if (terminal.supportsCursorMotion()) {
|
||||
System.out.println("CURSOR MOVEMENT");
|
||||
System.out.println(" ");
|
||||
System.out.println(" ");
|
||||
System.out.print("[delete me]");
|
||||
|
||||
terminal.cursorLeft(11);
|
||||
terminal.cursorUp(1);
|
||||
terminal.cursorRight(10);
|
||||
System.out.print("[4]");
|
||||
terminal.cursorUp(1);
|
||||
terminal.cursorLeft(3);
|
||||
System.out.print("[2]");
|
||||
terminal.cursorLeft(13);
|
||||
System.out.print("[1]");
|
||||
terminal.cursorLeft(3);
|
||||
terminal.cursorDown(1);
|
||||
System.out.print("[3]");
|
||||
terminal.cursorDown(1);
|
||||
terminal.cursorStartOfLine();
|
||||
terminal.foreground(Terminal.Color.Blue).bold();
|
||||
System.out.print("done");
|
||||
terminal.clearToEndOfLine();
|
||||
System.out.println("!");
|
||||
System.out.println();
|
||||
}
|
||||
} else if (stderrIsTerminal) {
|
||||
Terminal terminal = terminals.getTerminal(Terminals.Output.Stderr);
|
||||
System.err.print("* this is ");
|
||||
terminal.bold().foreground(Terminal.Color.Red);
|
||||
System.err.print("red");
|
||||
terminal.reset();
|
||||
System.err.print(" text on ");
|
||||
terminal.bold();
|
||||
System.err.print("stderr");
|
||||
terminal.reset();
|
||||
System.err.println(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user