Implemented SystemInfo for windows.
This commit is contained in:
332
build.gradle
332
build.gradle
@@ -1,166 +1,166 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'groovy'
|
||||
apply plugin: 'cpp'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'application'
|
||||
apply plugin: 'maven'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
groovy 'org.codehaus.groovy:groovy:1.8.7'
|
||||
testCompile 'org.spockframework:spock-core:0.6-groovy-1.8'
|
||||
}
|
||||
|
||||
group = 'net.rubygrapefruit'
|
||||
version = '0.1'
|
||||
|
||||
mainClassName = 'net.rubygrapefruit.platform.Main'
|
||||
def nativeHeadersDir = file("$buildDir/nativeHeaders")
|
||||
sourceCompatibility = 1.5
|
||||
targetCompatibility = 1.5
|
||||
|
||||
configurations.compile.extendsFrom = []
|
||||
|
||||
cpp {
|
||||
sourceSets {
|
||||
main
|
||||
}
|
||||
}
|
||||
|
||||
libraries {
|
||||
if (org.gradle.internal.os.OperatingSystem.current().macOsX) {
|
||||
universal.spec {
|
||||
baseName = 'native-platform-osx-universal'
|
||||
includes(['/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/'])
|
||||
args("-lcurses", "-arch", "x86_64", "-arch", "i386", "-o", outputFile)
|
||||
}
|
||||
} else if (org.gradle.internal.os.OperatingSystem.current().windows) {
|
||||
main.spec {
|
||||
baseName = 'native-platform-win32'
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include"])
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"])
|
||||
args("/DWIN32")
|
||||
}
|
||||
} else if (org.gradle.internal.os.OperatingSystem.current().linux) {
|
||||
all {
|
||||
spec {
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include"])
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include/linux"])
|
||||
args("-lcurses")
|
||||
}
|
||||
}
|
||||
if (System.getProperty('os.arch') == 'i386' || project.hasProperty('multiarch')) {
|
||||
i386.spec {
|
||||
baseName = 'native-platform-linux-i386'
|
||||
args("-m32")
|
||||
}
|
||||
}
|
||||
if (System.getProperty('os.arch') == 'amd64' || project.hasProperty('multiarch')) {
|
||||
amd64.spec {
|
||||
baseName = 'native-platform-linux-amd64'
|
||||
args("-m64")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
baseName = "native-platform-solaris"
|
||||
main.spec {
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include"])
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include/solaris"])
|
||||
args("-DSOLARIS", "-lcurses")
|
||||
}
|
||||
}
|
||||
all {
|
||||
spec {
|
||||
includes([nativeHeadersDir])
|
||||
}
|
||||
sourceSets << cpp.sourceSets.main
|
||||
}
|
||||
}
|
||||
|
||||
task nativeHeaders {
|
||||
def outputFile = file("$nativeHeadersDir/native.h")
|
||||
inputs.files sourceSets.main.output
|
||||
outputs.file outputFile
|
||||
doLast {
|
||||
outputFile.parentFile.mkdirs()
|
||||
exec {
|
||||
executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
|
||||
args '-o', outputFile
|
||||
args '-classpath', sourceSets.main.output.classesDir
|
||||
args 'net.rubygrapefruit.platform.internal.jni.NativeLibraryFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.PosixFileFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.PosixFileSystemFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.PosixProcessFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.PosixTerminalFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.TerminfoFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.WindowsConsoleFunctions'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def deployer = null
|
||||
uploadArchives {
|
||||
repositories {
|
||||
deployer = mavenDeployer {
|
||||
repository(url: uri("$buildDir/repo"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libraries.all { lib ->
|
||||
def nativeJar = task("nativeJar${lib.name.capitalize()}", type: Jar) {
|
||||
from lib.spec.task
|
||||
baseName = lib.spec.baseName
|
||||
}
|
||||
startScripts.classpath += nativeJar.outputs.files
|
||||
applicationDistribution.from(nativeJar) {
|
||||
into 'lib'
|
||||
}
|
||||
lib.spec.task.dependsOn nativeHeaders
|
||||
test.dependsOn lib.spec.task
|
||||
artifacts {
|
||||
archives nativeJar
|
||||
}
|
||||
def jniPom = deployer.addFilter(lib.name) { artifact, file ->
|
||||
return file == nativeJar.archivePath
|
||||
}
|
||||
jniPom.groupId = project.group
|
||||
jniPom.artifactId = lib.spec.baseName
|
||||
jniPom.version = project.version
|
||||
jniPom.scopeMappings.mappings.clear()
|
||||
}
|
||||
|
||||
javadoc {
|
||||
exclude '**/internal/**'
|
||||
}
|
||||
|
||||
applicationDistribution.from(javadoc) {
|
||||
into 'javadoc'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives distZip
|
||||
}
|
||||
|
||||
def mainPom = deployer.addFilter('main') { artifact, file ->
|
||||
return file == distZip.archivePath || file == jar.archivePath
|
||||
}
|
||||
mainPom.groupId = project.group
|
||||
mainPom.artifactId = jar.baseName
|
||||
mainPom.version = project.version
|
||||
mainPom.scopeMappings.mappings.clear()
|
||||
mainPom.withXml { provider ->
|
||||
def node = provider.asNode()
|
||||
def deps = node.appendNode('dependencies')
|
||||
def dep = deps.appendNode('dependency')
|
||||
dep.appendNode('groupId', project.group)
|
||||
dep.appendNode('artifactId', 'native-platform-osx-universal')
|
||||
dep.appendNode('version', project.version)
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = "1.3-20120907220018+0000"
|
||||
}
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'groovy'
|
||||
apply plugin: 'cpp'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'application'
|
||||
apply plugin: 'maven'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
groovy 'org.codehaus.groovy:groovy:1.8.7'
|
||||
testCompile 'org.spockframework:spock-core:0.6-groovy-1.8'
|
||||
}
|
||||
|
||||
group = 'net.rubygrapefruit'
|
||||
version = '0.1'
|
||||
|
||||
mainClassName = 'net.rubygrapefruit.platform.Main'
|
||||
def nativeHeadersDir = file("$buildDir/nativeHeaders")
|
||||
sourceCompatibility = 1.5
|
||||
targetCompatibility = 1.5
|
||||
|
||||
configurations.compile.extendsFrom = []
|
||||
|
||||
cpp {
|
||||
sourceSets {
|
||||
main
|
||||
}
|
||||
}
|
||||
|
||||
libraries {
|
||||
if (org.gradle.internal.os.OperatingSystem.current().macOsX) {
|
||||
universal.spec {
|
||||
baseName = 'native-platform-osx-universal'
|
||||
includes(['/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/'])
|
||||
args("-lcurses", "-arch", "x86_64", "-arch", "i386", "-o", outputFile)
|
||||
}
|
||||
} else if (org.gradle.internal.os.OperatingSystem.current().windows) {
|
||||
i386.spec {
|
||||
baseName = 'native-platform-windows-i386'
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include"])
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"])
|
||||
args("/DWIN32")
|
||||
}
|
||||
} else if (org.gradle.internal.os.OperatingSystem.current().linux) {
|
||||
all {
|
||||
spec {
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include"])
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include/linux"])
|
||||
args("-lcurses")
|
||||
}
|
||||
}
|
||||
if (System.getProperty('os.arch') == 'i386' || project.hasProperty('multiarch')) {
|
||||
i386.spec {
|
||||
baseName = 'native-platform-linux-i386'
|
||||
args("-m32")
|
||||
}
|
||||
}
|
||||
if (System.getProperty('os.arch') == 'amd64' || project.hasProperty('multiarch')) {
|
||||
amd64.spec {
|
||||
baseName = 'native-platform-linux-amd64'
|
||||
args("-m64")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
baseName = "native-platform-solaris"
|
||||
main.spec {
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include"])
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include/solaris"])
|
||||
args("-DSOLARIS", "-lcurses")
|
||||
}
|
||||
}
|
||||
all {
|
||||
spec {
|
||||
includes([nativeHeadersDir])
|
||||
}
|
||||
sourceSets << cpp.sourceSets.main
|
||||
}
|
||||
}
|
||||
|
||||
task nativeHeaders {
|
||||
def outputFile = file("$nativeHeadersDir/native.h")
|
||||
inputs.files sourceSets.main.output
|
||||
outputs.file outputFile
|
||||
doLast {
|
||||
outputFile.parentFile.mkdirs()
|
||||
exec {
|
||||
executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
|
||||
args '-o', outputFile
|
||||
args '-classpath', sourceSets.main.output.classesDir
|
||||
args 'net.rubygrapefruit.platform.internal.jni.NativeLibraryFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.PosixFileFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.PosixFileSystemFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.PosixProcessFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.PosixTerminalFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.TerminfoFunctions'
|
||||
args 'net.rubygrapefruit.platform.internal.jni.WindowsConsoleFunctions'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def deployer = null
|
||||
uploadArchives {
|
||||
repositories {
|
||||
deployer = mavenDeployer {
|
||||
repository(url: uri("$buildDir/repo"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libraries.all { lib ->
|
||||
def nativeJar = task("nativeJar${lib.name.capitalize()}", type: Jar) {
|
||||
from lib.spec.task
|
||||
baseName = lib.spec.baseName
|
||||
}
|
||||
startScripts.classpath += nativeJar.outputs.files
|
||||
applicationDistribution.from(nativeJar) {
|
||||
into 'lib'
|
||||
}
|
||||
lib.spec.task.dependsOn nativeHeaders
|
||||
test.dependsOn lib.spec.task
|
||||
artifacts {
|
||||
archives nativeJar
|
||||
}
|
||||
def jniPom = deployer.addFilter(lib.name) { artifact, file ->
|
||||
return file == nativeJar.archivePath
|
||||
}
|
||||
jniPom.groupId = project.group
|
||||
jniPom.artifactId = lib.spec.baseName
|
||||
jniPom.version = project.version
|
||||
jniPom.scopeMappings.mappings.clear()
|
||||
}
|
||||
|
||||
javadoc {
|
||||
exclude '**/internal/**'
|
||||
}
|
||||
|
||||
applicationDistribution.from(javadoc) {
|
||||
into 'javadoc'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives distZip
|
||||
}
|
||||
|
||||
def mainPom = deployer.addFilter('main') { artifact, file ->
|
||||
return file == distZip.archivePath || file == jar.archivePath
|
||||
}
|
||||
mainPom.groupId = project.group
|
||||
mainPom.artifactId = jar.baseName
|
||||
mainPom.version = project.version
|
||||
mainPom.scopeMappings.mappings.clear()
|
||||
mainPom.withXml { provider ->
|
||||
def node = provider.asNode()
|
||||
def deps = node.appendNode('dependencies')
|
||||
def dep = deps.appendNode('dependency')
|
||||
dep.appendNode('groupId', project.group)
|
||||
dep.appendNode('artifactId', 'native-platform-osx-universal')
|
||||
dep.appendNode('version', project.version)
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = "1.3-20120907220018+0000"
|
||||
}
|
||||
|
||||
296
readme.md
296
readme.md
@@ -1,149 +1,147 @@
|
||||
|
||||
# Native-platform: Java bindings for various native APIs
|
||||
|
||||
A collection of cross-platform Java APIs for various native APIs. Supports OS X, Linux, Solaris and Windows.
|
||||
|
||||
These APIs support Java 5 and later. Some of these APIs overlap with APIs available in later Java versions.
|
||||
|
||||
## Available bindings
|
||||
|
||||
### Generic
|
||||
|
||||
* Get PID of current process.
|
||||
* Get kernel name and version.
|
||||
* Get machine architecture.
|
||||
|
||||
### Terminal and console
|
||||
|
||||
These bindings work for both the UNIX terminal and the Windows console:
|
||||
|
||||
* Determine if stdout/stderr are attached to a terminal.
|
||||
* Query the terminal size.
|
||||
* Switch between bold and normal mode on the terminal.
|
||||
* Change foreground color on the terminal.
|
||||
* Move terminal cursor up, down, left, right, start of line.
|
||||
* Clear to end of line.
|
||||
|
||||
### File systems
|
||||
|
||||
* Get and set UNIX file mode.
|
||||
* Create and read symbolic links.
|
||||
* List the available file systems on the machine
|
||||
* Query file system mount point.
|
||||
* Query file system type.
|
||||
* Query file system device name.
|
||||
* Query whether a file system is local or remote.
|
||||
|
||||
## Supported platforms
|
||||
|
||||
Currently ported to OS X, Linux, Solaris and Windows. Tested on:
|
||||
|
||||
* OS X 10.7.4, 10.8 (x86_64), 10.6.7 (i386)
|
||||
* Ubunutu 12.04 (amd64), 8.04.4 (i386, amd64)
|
||||
* Solaris 11 (x86)
|
||||
* Windows 7 (amd64)
|
||||
|
||||
## Using
|
||||
|
||||
Include `native-platform.jar` and `native-platform-jni.jar` in your classpath.
|
||||
|
||||
import net.rubygrapefruit.platform.Native;
|
||||
import net.rubygrapefruit.platform.Terminals;
|
||||
import net.rubygrapefruit.platform.Terminal;
|
||||
import static net.rubygrapefruit.platform.Terminals.Output.*;
|
||||
|
||||
Terminals terminals = Native.get(Terminals.class);
|
||||
|
||||
// check if terminal
|
||||
terminals.isTerminal(Stdout);
|
||||
|
||||
// use terminal
|
||||
Terminal stdout = terminals.getTerminal(Stdout);
|
||||
stdout.bold();
|
||||
System.out.println("bold text");
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
You will need to use the Gradle wrapper. Just run `gradlew` in the root directory.
|
||||
|
||||
### Ubuntu
|
||||
|
||||
The g++ compiler is required to build the native library. You will need the `g++` package for this. Usually this is already installed.
|
||||
|
||||
You need to install the `libncurses5-dev` package to pick up the ncurses header files. Also worth installing the `ncurses-doc` package too.
|
||||
|
||||
#### 64-bit machines with multi-arch support
|
||||
|
||||
Where multi-arch support is available (e.g. recent Ubuntu releases), you can build the i386 and amd64 versions of the library on the
|
||||
same machine.
|
||||
|
||||
You need to install the `gcc-multilib` and `g++-multilib` packages to pick up i386 support.
|
||||
|
||||
You need to install the `lib32ncurses5-dev` package to pick up the ncurses i386 version.
|
||||
|
||||
To build, include `-Pmultiarch` on the command-line.
|
||||
|
||||
### Windows
|
||||
|
||||
You need to install Visual studio, and build from a Visual studio command prompt.
|
||||
|
||||
### OS X
|
||||
|
||||
The g++ compiler is required to build the native library. You will need to install the XCode tools for this.
|
||||
|
||||
### Solaris
|
||||
|
||||
For Solaris 11, you need to install the `development/gcc-45` and `system/header` packages.
|
||||
|
||||
## Running
|
||||
|
||||
Run `gradle install` to install into `build/install/native-platform`. Or `gradle distZip` to create an application distribtion
|
||||
in `build/distributions/native-platform.zip`.
|
||||
|
||||
You can run `$INSTALL_DIR/bin/native-platform` to run the test application.
|
||||
|
||||
## Testing
|
||||
|
||||
* Test on IBM JVM.
|
||||
* Test on Java 5, 6, 7.
|
||||
* Test on Windows 7, Windows XP
|
||||
|
||||
## TODO
|
||||
|
||||
### Fixes
|
||||
|
||||
* Windows: build 32 bit and 64 bit libraries.
|
||||
* Windows: fail for unsupported architecture.
|
||||
* Linux: detect remote filesystems.
|
||||
* Solaris: fix unicode file name handling.
|
||||
* Solaris: fail for unsupported architecture.
|
||||
* Solaris: build 32 bit and 64 bit libraries.
|
||||
* Freebsd: finish port.
|
||||
* Freebsd: fail for unsupported architecture.
|
||||
* Freebsd: build 32 bit and 64 bit libraries.
|
||||
|
||||
### Improvements
|
||||
|
||||
* Cache class, method and field lookups (in particular for String conversions).
|
||||
* Determine C charset once at startup
|
||||
* Change readLink() implementation so that it does not need to NULL terminate the encoded content
|
||||
* Implement java_to_char_str()
|
||||
* Use iconv() to convert from C char string to UTF-16 when converting from C char string to Java String.
|
||||
* Support for cygwin terminal
|
||||
* Use TERM=xtermc instead of TERM=xterm on Solaris.
|
||||
* Add diagnostics for terminal.
|
||||
* Split out separate native library for terminal handling.
|
||||
* Version each native interface separately.
|
||||
* String names for errno values.
|
||||
* Split into multiple projects.
|
||||
* Convert to c.
|
||||
* Make native library extraction multi-process safe.
|
||||
* Initial release.
|
||||
* Use fully decomposed form for unicode file names on hfs+ filesystems.
|
||||
* Handle string encoding for file system details.
|
||||
* Handle string encoding for system info.
|
||||
|
||||
### Ideas
|
||||
|
||||
* Expose platform-specific HTTP proxy configuration. Query registry on windows to determine IE settings.
|
||||
|
||||
# Native-platform: Java bindings for various native APIs
|
||||
|
||||
A collection of cross-platform Java APIs for various native APIs. Supports OS X, Linux, Solaris and Windows.
|
||||
|
||||
These APIs support Java 5 and later. Some of these APIs overlap with APIs available in later Java versions.
|
||||
|
||||
## Available bindings
|
||||
|
||||
### Generic
|
||||
|
||||
* Get PID of current process.
|
||||
* Get kernel name and version.
|
||||
* Get machine architecture.
|
||||
|
||||
### Terminal and console
|
||||
|
||||
These bindings work for both the UNIX terminal and the Windows console:
|
||||
|
||||
* Determine if stdout/stderr are attached to a terminal.
|
||||
* Query the terminal size.
|
||||
* Switch between bold and normal mode on the terminal.
|
||||
* Change foreground color on the terminal.
|
||||
* Move terminal cursor up, down, left, right, start of line.
|
||||
* Clear to end of line.
|
||||
|
||||
### File systems
|
||||
|
||||
* Get and set UNIX file mode.
|
||||
* Create and read symbolic links.
|
||||
* List the available file systems on the machine
|
||||
* Query file system mount point.
|
||||
* Query file system type.
|
||||
* Query file system device name.
|
||||
* Query whether a file system is local or remote.
|
||||
|
||||
## Supported platforms
|
||||
|
||||
Currently ported to OS X, Linux, Solaris and Windows. Tested on:
|
||||
|
||||
* OS X 10.7.4, 10.8 (x86_64), 10.6.7 (i386)
|
||||
* Ubunutu 12.04 (amd64), 8.04.4 (i386, amd64)
|
||||
* Solaris 11 (x86)
|
||||
* Windows 7 (amd64)
|
||||
|
||||
## Using
|
||||
|
||||
Include `native-platform.jar` and `native-platform-jni.jar` in your classpath.
|
||||
|
||||
import net.rubygrapefruit.platform.Native;
|
||||
import net.rubygrapefruit.platform.Terminals;
|
||||
import net.rubygrapefruit.platform.Terminal;
|
||||
import static net.rubygrapefruit.platform.Terminals.Output.*;
|
||||
|
||||
Terminals terminals = Native.get(Terminals.class);
|
||||
|
||||
// check if terminal
|
||||
terminals.isTerminal(Stdout);
|
||||
|
||||
// use terminal
|
||||
Terminal stdout = terminals.getTerminal(Stdout);
|
||||
stdout.bold();
|
||||
System.out.println("bold text");
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
You will need to use the Gradle wrapper. Just run `gradlew` in the root directory.
|
||||
|
||||
### Ubuntu
|
||||
|
||||
The g++ compiler is required to build the native library. You will need the `g++` package for this. Usually this is already installed.
|
||||
|
||||
You need to install the `libncurses5-dev` package to pick up the ncurses header files. Also worth installing the `ncurses-doc` package too.
|
||||
|
||||
#### 64-bit machines with multi-arch support
|
||||
|
||||
Where multi-arch support is available (e.g. recent Ubuntu releases), you can build the i386 and amd64 versions of the library on the
|
||||
same machine.
|
||||
|
||||
You need to install the `gcc-multilib` and `g++-multilib` packages to pick up i386 support.
|
||||
|
||||
You need to install the `lib32ncurses5-dev` package to pick up the ncurses i386 version.
|
||||
|
||||
To build, include `-Pmultiarch` on the command-line.
|
||||
|
||||
### Windows
|
||||
|
||||
You need to install Visual studio, and build from a Visual studio command prompt.
|
||||
|
||||
### OS X
|
||||
|
||||
The g++ compiler is required to build the native library. You will need to install the XCode tools for this.
|
||||
|
||||
### Solaris
|
||||
|
||||
For Solaris 11, you need to install the `development/gcc-45` and `system/header` packages.
|
||||
|
||||
## Running
|
||||
|
||||
Run `gradle install` to install into `build/install/native-platform`. Or `gradle distZip` to create an application distribtion
|
||||
in `build/distributions/native-platform.zip`.
|
||||
|
||||
You can run `$INSTALL_DIR/bin/native-platform` to run the test application.
|
||||
|
||||
## Testing
|
||||
|
||||
* Test on IBM JVM.
|
||||
* Test on Java 5, 6, 7.
|
||||
* Test on Windows 7, Windows XP
|
||||
|
||||
## TODO
|
||||
|
||||
### Fixes
|
||||
|
||||
* Windows: build 32 bit and 64 bit libraries.
|
||||
* Windows: fail for unsupported architecture.
|
||||
* Linux: detect remote filesystems.
|
||||
* Solaris: fix unicode file name handling.
|
||||
* Solaris: fail for unsupported architecture.
|
||||
* Solaris: build 32 bit and 64 bit libraries.
|
||||
* Freebsd: finish port.
|
||||
* Freebsd: fail for unsupported architecture.
|
||||
* Freebsd: build 32 bit and 64 bit libraries.
|
||||
|
||||
### Improvements
|
||||
|
||||
* Cache class, method and field lookups (in particular for String conversions).
|
||||
* Determine C charset once at startup
|
||||
* Change readLink() implementation so that it does not need to NULL terminate the encoded content
|
||||
* Don't use NewStringUTF() anywhere
|
||||
* Use iconv() to convert from C char string to UTF-16 when converting from C char string to Java String.
|
||||
* Support for cygwin terminal
|
||||
* Use TERM=xtermc instead of TERM=xterm on Solaris.
|
||||
* Add diagnostics for terminal.
|
||||
* Split out separate native library for terminal handling.
|
||||
* Version each native interface separately.
|
||||
* String names for errno values.
|
||||
* Split into multiple projects.
|
||||
* Convert to c.
|
||||
* Make native library extraction multi-process safe.
|
||||
* Initial release.
|
||||
* Use fully decomposed form for unicode file names on hfs+ filesystems.
|
||||
|
||||
### Ideas
|
||||
|
||||
* Expose platform-specific HTTP proxy configuration. Query registry on windows to determine IE settings.
|
||||
|
||||
@@ -1,240 +1,266 @@
|
||||
#ifdef WIN32
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <windows.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(), result);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getPlatform(JNIEnv *env, jclass target) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Process functions
|
||||
*/
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
|
||||
return GetCurrentProcessId();
|
||||
}
|
||||
|
||||
/*
|
||||
* Console functions
|
||||
*/
|
||||
|
||||
HANDLE getHandle(JNIEnv *env, int output, jobject result) {
|
||||
HANDLE handle = output == 1 ? 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;
|
||||
SetConsoleTextAttribute(current_console, current_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_reset(JNIEnv *env, jclass target, jobject result) {
|
||||
SetConsoleTextAttribute(current_console, 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;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(current_console, current_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_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;
|
||||
}
|
||||
for (int i = console_info.dwCursorPosition.X; i < console_info.dwSize.X; i++) {
|
||||
WriteConsole(current_console, " ", 1, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <windows.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(), result);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
* Console functions
|
||||
*/
|
||||
|
||||
HANDLE getHandle(JNIEnv *env, int output, jobject result) {
|
||||
HANDLE handle = output == 1 ? 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;
|
||||
SetConsoleTextAttribute(current_console, current_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_reset(JNIEnv *env, jclass target, jobject result) {
|
||||
SetConsoleTextAttribute(current_console, 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;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(current_console, current_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_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;
|
||||
}
|
||||
for (int i = console_info.dwCursorPosition.X; i < console_info.dwSize.X; i++) {
|
||||
WriteConsole(current_console, " ", 1, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
74
src/main/java/net/rubygrapefruit/platform/internal/MutableSystemInfo.java
Normal file → Executable file
74
src/main/java/net/rubygrapefruit/platform/internal/MutableSystemInfo.java
Normal file → Executable file
@@ -1,21 +1,53 @@
|
||||
package net.rubygrapefruit.platform.internal;
|
||||
|
||||
import net.rubygrapefruit.platform.SystemInfo;
|
||||
|
||||
public class MutableSystemInfo implements SystemInfo {
|
||||
public String osName;
|
||||
public String osVersion;
|
||||
public String machineArchitecture;
|
||||
|
||||
public String getKernelName() {
|
||||
return osName;
|
||||
}
|
||||
|
||||
public String getKernelVersion() {
|
||||
return osVersion;
|
||||
}
|
||||
|
||||
public String getMachineArchitecture() {
|
||||
return machineArchitecture;
|
||||
}
|
||||
}
|
||||
package net.rubygrapefruit.platform.internal;
|
||||
|
||||
import net.rubygrapefruit.platform.SystemInfo;
|
||||
|
||||
public class MutableSystemInfo implements SystemInfo {
|
||||
public String osName;
|
||||
public String osVersion;
|
||||
public String machineArchitecture;
|
||||
|
||||
public String getKernelName() {
|
||||
return osName;
|
||||
}
|
||||
|
||||
public String getKernelVersion() {
|
||||
return osVersion;
|
||||
}
|
||||
|
||||
public String getMachineArchitecture() {
|
||||
return machineArchitecture;
|
||||
}
|
||||
|
||||
void windows(int major, int minor, int build, boolean workstation, String arch) {
|
||||
osName = toWindowsVersionName(major, minor, workstation);
|
||||
osVersion = String.format("%s.%s (build %s)", major, minor, build);
|
||||
machineArchitecture = arch;
|
||||
}
|
||||
|
||||
private String toWindowsVersionName(int major, int minor, boolean workstation) {
|
||||
switch (major) {
|
||||
case 5:
|
||||
switch (minor) {
|
||||
case 0:
|
||||
return "Windows 2000";
|
||||
case 1:
|
||||
return "Windows XP";
|
||||
case 2:
|
||||
return "Windows Server 2003";
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (minor) {
|
||||
case 0:
|
||||
return workstation ? "Windows Vista" : "Windows Server 2008";
|
||||
case 1:
|
||||
return workstation ? "Windows 7" : "Windows Server 2008 R2";
|
||||
case 2:
|
||||
return workstation ? "Windows 8" : "Windows Server 2012";
|
||||
}
|
||||
break;
|
||||
}
|
||||
return "Windows (unknown version)";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,145 +1,152 @@
|
||||
package net.rubygrapefruit.platform.internal;
|
||||
|
||||
import net.rubygrapefruit.platform.*;
|
||||
import net.rubygrapefruit.platform.Process;
|
||||
|
||||
public abstract class Platform {
|
||||
private static Platform platform;
|
||||
|
||||
public static Platform current() {
|
||||
synchronized (Platform.class) {
|
||||
if (platform == null) {
|
||||
String osName = getOperatingSystem().toLowerCase();
|
||||
String arch = getArchitecture();
|
||||
if (osName.contains("windows")) {
|
||||
platform = new Windows();
|
||||
} else if (osName.contains("linux")) {
|
||||
platform = new Linux();
|
||||
} else if (osName.contains("os x") && (arch.equals("i386") || arch.equals("x86_64"))) {
|
||||
platform = new OsX();
|
||||
} else if (osName.contains("sunos")) {
|
||||
platform = new Solaris();
|
||||
} else {
|
||||
platform = new Unsupported();
|
||||
}
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWindows() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
throw new NativeIntegrationUnavailableException(String.format("Native integration %s is not supported on this operating system (%s %s)",
|
||||
type.getSimpleName(), getOperatingSystem(), getArchitecture()));
|
||||
}
|
||||
|
||||
public abstract String getLibraryName() throws NativeIntegrationUnavailableException;
|
||||
|
||||
private static class Windows extends Platform {
|
||||
@Override
|
||||
public boolean isWindows() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLibraryName() {
|
||||
return "native-platform-win32.dll";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
if (type.equals(net.rubygrapefruit.platform.Process.class)) {
|
||||
return type.cast(new DefaultProcess());
|
||||
}
|
||||
if (type.equals(Terminals.class)) {
|
||||
return type.cast(new WindowsTerminals());
|
||||
}
|
||||
return super.get(type);
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class Posix extends Platform {
|
||||
@Override
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
if (type.equals(PosixFile.class)) {
|
||||
return type.cast(new DefaultPosixFile());
|
||||
}
|
||||
if (type.equals(Process.class)) {
|
||||
return type.cast(new DefaultProcess());
|
||||
}
|
||||
if (type.equals(Terminals.class)) {
|
||||
return type.cast(new TerminfoTerminals());
|
||||
}
|
||||
if (type.equals(SystemInfo.class)) {
|
||||
return type.cast(new DefaultSystemInfo());
|
||||
}
|
||||
return super.get(type);
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class Unix extends Posix {
|
||||
}
|
||||
|
||||
private static class Linux extends Unix {
|
||||
@Override
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
if (type.equals(FileSystems.class)) {
|
||||
return type.cast(new PosixFileSystems());
|
||||
}
|
||||
return super.get(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLibraryName() {
|
||||
if (getArchitecture().equals("amd64")) {
|
||||
return "libnative-platform-linux-amd64.so";
|
||||
}
|
||||
if (getArchitecture().equals("i386") || getArchitecture().equals("x86")) {
|
||||
return "libnative-platform-linux-i386.so";
|
||||
}
|
||||
throw new NativeIntegrationUnavailableException(String.format(
|
||||
"Native integration is not available for this architecture (%s) on Linux.", getArchitecture()));
|
||||
}
|
||||
}
|
||||
|
||||
private static String getArchitecture() {
|
||||
return System.getProperty("os.arch");
|
||||
}
|
||||
|
||||
private static class Solaris extends Unix {
|
||||
@Override
|
||||
public String getLibraryName() {
|
||||
return "libnative-platform-solaris.so";
|
||||
}
|
||||
}
|
||||
|
||||
private static class OsX extends Posix {
|
||||
@Override
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
if (type.equals(FileSystems.class)) {
|
||||
return type.cast(new PosixFileSystems());
|
||||
}
|
||||
return super.get(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLibraryName() {
|
||||
return "libnative-platform-osx-universal.dylib";
|
||||
}
|
||||
}
|
||||
|
||||
private static class Unsupported extends Platform {
|
||||
public String getLibraryName() {
|
||||
throw new NativeIntegrationUnavailableException(String.format(
|
||||
"Native integration is not available for this operating system (%s %s)", getOperatingSystem(),
|
||||
getArchitecture()));
|
||||
}
|
||||
}
|
||||
|
||||
private static String getOperatingSystem() {
|
||||
return System.getProperty("os.name");
|
||||
}
|
||||
}
|
||||
package net.rubygrapefruit.platform.internal;
|
||||
|
||||
import net.rubygrapefruit.platform.*;
|
||||
import net.rubygrapefruit.platform.Process;
|
||||
|
||||
public abstract class Platform {
|
||||
private static Platform platform;
|
||||
|
||||
public static Platform current() {
|
||||
synchronized (Platform.class) {
|
||||
if (platform == null) {
|
||||
String osName = getOperatingSystem().toLowerCase();
|
||||
String arch = getArchitecture();
|
||||
if (osName.contains("windows")) {
|
||||
platform = new Windows();
|
||||
} else if (osName.contains("linux")) {
|
||||
platform = new Linux();
|
||||
} else if (osName.contains("os x") && (arch.equals("i386") || arch.equals("x86_64"))) {
|
||||
platform = new OsX();
|
||||
} else if (osName.contains("sunos")) {
|
||||
platform = new Solaris();
|
||||
} else {
|
||||
platform = new Unsupported();
|
||||
}
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWindows() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
throw new NativeIntegrationUnavailableException(String.format("Native integration %s is not supported on this operating system (%s %s)",
|
||||
type.getSimpleName(), getOperatingSystem(), getArchitecture()));
|
||||
}
|
||||
|
||||
public abstract String getLibraryName() throws NativeIntegrationUnavailableException;
|
||||
|
||||
private static class Windows extends Platform {
|
||||
@Override
|
||||
public boolean isWindows() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLibraryName() {
|
||||
if (getArchitecture().equals("x86")) {
|
||||
return "native-platform-windows-i386.dll";
|
||||
}
|
||||
throw new NativeIntegrationUnavailableException(String.format(
|
||||
"Native integration is not available for this architecture (%s) on Windows.", getArchitecture()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
if (type.equals(net.rubygrapefruit.platform.Process.class)) {
|
||||
return type.cast(new DefaultProcess());
|
||||
}
|
||||
if (type.equals(Terminals.class)) {
|
||||
return type.cast(new WindowsTerminals());
|
||||
}
|
||||
if (type.equals(SystemInfo.class)) {
|
||||
return type.cast(new DefaultSystemInfo());
|
||||
}
|
||||
return super.get(type);
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class Posix extends Platform {
|
||||
@Override
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
if (type.equals(PosixFile.class)) {
|
||||
return type.cast(new DefaultPosixFile());
|
||||
}
|
||||
if (type.equals(Process.class)) {
|
||||
return type.cast(new DefaultProcess());
|
||||
}
|
||||
if (type.equals(Terminals.class)) {
|
||||
return type.cast(new TerminfoTerminals());
|
||||
}
|
||||
if (type.equals(SystemInfo.class)) {
|
||||
return type.cast(new DefaultSystemInfo());
|
||||
}
|
||||
return super.get(type);
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class Unix extends Posix {
|
||||
}
|
||||
|
||||
private static class Linux extends Unix {
|
||||
@Override
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
if (type.equals(FileSystems.class)) {
|
||||
return type.cast(new PosixFileSystems());
|
||||
}
|
||||
return super.get(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLibraryName() {
|
||||
if (getArchitecture().equals("amd64")) {
|
||||
return "libnative-platform-linux-amd64.so";
|
||||
}
|
||||
if (getArchitecture().equals("i386") || getArchitecture().equals("x86")) {
|
||||
return "libnative-platform-linux-i386.so";
|
||||
}
|
||||
throw new NativeIntegrationUnavailableException(String.format(
|
||||
"Native integration is not available for this architecture (%s) on Linux.", getArchitecture()));
|
||||
}
|
||||
}
|
||||
|
||||
private static String getArchitecture() {
|
||||
return System.getProperty("os.arch");
|
||||
}
|
||||
|
||||
private static class Solaris extends Unix {
|
||||
@Override
|
||||
public String getLibraryName() {
|
||||
return "libnative-platform-solaris.so";
|
||||
}
|
||||
}
|
||||
|
||||
private static class OsX extends Posix {
|
||||
@Override
|
||||
public <T extends NativeIntegration> T get(Class<T> type) {
|
||||
if (type.equals(FileSystems.class)) {
|
||||
return type.cast(new PosixFileSystems());
|
||||
}
|
||||
return super.get(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLibraryName() {
|
||||
return "libnative-platform-osx-universal.dylib";
|
||||
}
|
||||
}
|
||||
|
||||
private static class Unsupported extends Platform {
|
||||
public String getLibraryName() {
|
||||
throw new NativeIntegrationUnavailableException(String.format(
|
||||
"Native integration is not available for this operating system (%s %s)", getOperatingSystem(),
|
||||
getArchitecture()));
|
||||
}
|
||||
}
|
||||
|
||||
private static String getOperatingSystem() {
|
||||
return System.getProperty("os.name");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user