Some updates.
This commit is contained in:
416
build.gradle
416
build.gradle
@@ -1,208 +1,208 @@
|
||||
apply plugin: 'groovy'
|
||||
apply plugin: 'cpp'
|
||||
|
||||
allprojects {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'maven'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url "https://gradle.artifactoryonline.com/gradle/libs-releases-local" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'org.spockframework:spock-core:0.6-groovy-1.8'
|
||||
}
|
||||
|
||||
group = 'net.rubygrapefruit'
|
||||
version = '0.2'
|
||||
|
||||
sourceCompatibility = 1.5
|
||||
targetCompatibility = 1.5
|
||||
|
||||
configurations.compile.extendsFrom = []
|
||||
|
||||
tasks.withType(Upload) {
|
||||
repositories {
|
||||
mavenDeployer {
|
||||
if (project.hasProperty('release')) {
|
||||
repository(url: uri("https://gradle.artifactoryonline.com/gradle/libs-releases-local")) {
|
||||
authentication(userName: artifactoryUserName, password: artifactoryPassword)
|
||||
}
|
||||
} else {
|
||||
repository(url: uri("$rootProject.buildDir/repo"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
groovy 'org.codehaus.groovy:groovy:1.8.7'
|
||||
}
|
||||
|
||||
def nativeHeadersDir = file("$buildDir/nativeHeaders")
|
||||
|
||||
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) {
|
||||
all {
|
||||
spec {
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include"])
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"])
|
||||
args("/DWIN32")
|
||||
}
|
||||
}
|
||||
|
||||
def out = new ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine "cl.exe", "/?"
|
||||
errorOutput = out
|
||||
standardOutput = new ByteArrayOutputStream()
|
||||
}
|
||||
def header = out.toString().readLines().head()
|
||||
if (header.endsWith("for 80x86") || header.endsWith("for x86")) {
|
||||
i386.spec {
|
||||
baseName = 'native-platform-windows-i386'
|
||||
}
|
||||
} else if (header.endsWith("for x64")) {
|
||||
amd64.spec {
|
||||
baseName = 'native-platform-windows-amd64'
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Cannot determine compiler's target architecture")
|
||||
}
|
||||
|
||||
} 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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
jni
|
||||
}
|
||||
|
||||
def deployer = uploadJni.repositories.mavenDeployer
|
||||
|
||||
libraries.all { lib ->
|
||||
def nativeJar = task("nativeJar${lib.name.capitalize()}", type: Jar) {
|
||||
from lib.spec.task
|
||||
baseName = lib.spec.baseName
|
||||
}
|
||||
lib.spec.task.dependsOn nativeHeaders
|
||||
test.dependsOn lib.spec.task
|
||||
artifacts {
|
||||
jni nativeJar
|
||||
runtime 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/**'
|
||||
}
|
||||
|
||||
task sourceZip(type: Zip) {
|
||||
from sourceSets.main.allSource
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
task javadocZip(type: Zip) {
|
||||
from javadoc
|
||||
classifier = 'javadoc'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives sourceZip
|
||||
archives javadocZip
|
||||
}
|
||||
|
||||
def mainPom = uploadArchives.repositories.mavenDeployer.pom
|
||||
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')
|
||||
['osx-universal', 'linux-amd64', 'linux-i386', 'windows-amd64', 'windows-i386'].each { platform ->
|
||||
def dep = deps.appendNode('dependency')
|
||||
dep.appendNode('groupId', project.group)
|
||||
dep.appendNode('artifactId', "native-platform-${platform}")
|
||||
dep.appendNode('version', project.version)
|
||||
}
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = "1.3-20120907220018+0000"
|
||||
}
|
||||
apply plugin: 'groovy'
|
||||
apply plugin: 'cpp'
|
||||
|
||||
allprojects {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'maven'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url "http://repo.gradle.org/gradle/libs-releases-local" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'org.spockframework:spock-core:0.6-groovy-1.8'
|
||||
}
|
||||
|
||||
group = 'net.rubygrapefruit'
|
||||
version = '0.2'
|
||||
|
||||
sourceCompatibility = 1.5
|
||||
targetCompatibility = 1.5
|
||||
|
||||
configurations.compile.extendsFrom = []
|
||||
|
||||
tasks.withType(Upload) {
|
||||
repositories {
|
||||
mavenDeployer {
|
||||
if (project.hasProperty('release')) {
|
||||
repository(url: uri("https://gradle.artifactoryonline.com/gradle/libs-releases-local")) {
|
||||
authentication(userName: artifactoryUserName, password: artifactoryPassword)
|
||||
}
|
||||
} else {
|
||||
repository(url: uri("$rootProject.buildDir/repo"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
groovy 'org.codehaus.groovy:groovy:1.8.7'
|
||||
}
|
||||
|
||||
def nativeHeadersDir = file("$buildDir/nativeHeaders")
|
||||
|
||||
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) {
|
||||
all {
|
||||
spec {
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include"])
|
||||
includes(["${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"])
|
||||
args("/DWIN32")
|
||||
}
|
||||
}
|
||||
|
||||
def out = new ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine "cl.exe", "/?"
|
||||
errorOutput = out
|
||||
standardOutput = new ByteArrayOutputStream()
|
||||
}
|
||||
def header = out.toString().readLines().head()
|
||||
if (header.endsWith("for 80x86") || header.endsWith("for x86")) {
|
||||
i386.spec {
|
||||
baseName = 'native-platform-windows-i386'
|
||||
}
|
||||
} else if (header.endsWith("for x64")) {
|
||||
amd64.spec {
|
||||
baseName = 'native-platform-windows-amd64'
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Cannot determine compiler's target architecture")
|
||||
}
|
||||
|
||||
} 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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
jni
|
||||
}
|
||||
|
||||
def deployer = uploadJni.repositories.mavenDeployer
|
||||
|
||||
libraries.all { lib ->
|
||||
def nativeJar = task("nativeJar${lib.name.capitalize()}", type: Jar) {
|
||||
from lib.spec.task
|
||||
baseName = lib.spec.baseName
|
||||
}
|
||||
lib.spec.task.dependsOn nativeHeaders
|
||||
test.dependsOn lib.spec.task
|
||||
artifacts {
|
||||
jni nativeJar
|
||||
runtime 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/**'
|
||||
}
|
||||
|
||||
task sourceZip(type: Zip) {
|
||||
from sourceSets.main.allSource
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
task javadocZip(type: Zip) {
|
||||
from javadoc
|
||||
classifier = 'javadoc'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives sourceZip
|
||||
archives javadocZip
|
||||
}
|
||||
|
||||
def mainPom = uploadArchives.repositories.mavenDeployer.pom
|
||||
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')
|
||||
['osx-universal', 'linux-amd64', 'linux-i386', 'windows-amd64', 'windows-i386'].each { platform ->
|
||||
def dep = deps.appendNode('dependency')
|
||||
dep.appendNode('groupId', project.group)
|
||||
dep.appendNode('artifactId', "native-platform-${platform}")
|
||||
dep.appendNode('version', project.version)
|
||||
}
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = "1.3-20120907220018+0000"
|
||||
}
|
||||
|
||||
387
readme.md
387
readme.md
@@ -1,188 +1,199 @@
|
||||
|
||||
# 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 and Windows, with some support for Solaris and FreeBSD. 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 (x64), XP (x86)
|
||||
|
||||
## Using
|
||||
|
||||
Include `native-platform.jar` and `native-platform-${os}-${arch}.jar` in your classpath. From Gradle, you can do
|
||||
this:
|
||||
|
||||
repositories {
|
||||
maven { url "https://gradle.artifactoryonline.com/gradle/libs-releases-local" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "net.rubygrapefruit:native-platform:0.1"
|
||||
}
|
||||
|
||||
Some sample code to use the terminal:
|
||||
|
||||
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");
|
||||
|
||||
## Changes
|
||||
|
||||
### 0.2
|
||||
|
||||
Fixes to make native library extraction multi-process safe.
|
||||
|
||||
### 0.1
|
||||
|
||||
Initial release
|
||||
|
||||
# Development
|
||||
|
||||
## 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 installApp` to install the test application into `test-app/build/install/native-platform-test`. Or
|
||||
`gradle distZip` to create an application distribtion in `test-app/build/distributions/native-platform-test-$version.zip`.
|
||||
|
||||
You can run `$INSTALL_DIR/bin/native-platform-test` to run the test application.
|
||||
|
||||
# Releasing
|
||||
|
||||
1. Create a tag and push.
|
||||
2. Build each variant:
|
||||
1. Checkout tag.
|
||||
2. `./gradlew clean test :uploadJni -Prelease -PartifactoryUserName=<> -PartifactoryPassword=<>`
|
||||
* OS X universal
|
||||
* Linux i386, using Ubunutu 8.04
|
||||
* Linux amd64, using Ubunutu 8.04
|
||||
* Windows x86, using VC++ 2010
|
||||
* Windows x64
|
||||
3. Build Java library and test app:
|
||||
1. Checkout tag.
|
||||
2. `./gradlew clean test :uploadArchives testApp:uploadArchives -Prelease`
|
||||
4. Checkout master
|
||||
5. Increment version number.
|
||||
|
||||
## Testing
|
||||
|
||||
* Test on IBM JVM.
|
||||
* Test on Java 5, 6, 7.
|
||||
* Test on Windows 7, Windows XP
|
||||
|
||||
## TODO
|
||||
|
||||
### Fixes
|
||||
|
||||
* Windows: fix detection of shared drive under VMWare fusion and Windows XP
|
||||
* 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
|
||||
|
||||
* Use wchar_to_java() for windows system and file system info.
|
||||
* Test network file systems on Mac, Linux, Windows
|
||||
* Test mount points on Windows
|
||||
* 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
|
||||
* Don't use NewString() 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.
|
||||
* Use fully decomposed form for unicode file names on hfs+ filesystems.
|
||||
* Extend FileSystem to deal with removable media.
|
||||
|
||||
### 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
|
||||
|
||||
### System information
|
||||
|
||||
* Get kernel name and version.
|
||||
* Get machine architecture.
|
||||
|
||||
### Processes
|
||||
|
||||
* Get the PID of the current process.
|
||||
|
||||
### 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 and Windows. Support for Solaris and FreeBSD is a work in progress. 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 (x64), XP (x86)
|
||||
|
||||
## Using
|
||||
|
||||
Include `native-platform.jar` and `native-platform-${os}-${arch}.jar` in your classpath. From Gradle, you can do
|
||||
this:
|
||||
|
||||
repositories {
|
||||
maven { url "http://repo.gradle.org/gradle/libs-releases-local" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "net.rubygrapefruit:native-platform:0.1"
|
||||
}
|
||||
|
||||
You can also download [here](http://repo.gradle.org/gradle/libs-releases-local/net/rubygrapefruit/native-platform/0.1)
|
||||
|
||||
Some sample code to use the terminal:
|
||||
|
||||
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");
|
||||
|
||||
## Changes
|
||||
|
||||
### 0.2
|
||||
|
||||
Fixes to make native library extraction multi-process safe.
|
||||
|
||||
### 0.1
|
||||
|
||||
Initial release.
|
||||
|
||||
# Development
|
||||
|
||||
## 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 installApp` to install the test application into `test-app/build/install/native-platform-test`. Or
|
||||
`gradle distZip` to create an application distribtion in `test-app/build/distributions/native-platform-test-$version.zip`.
|
||||
|
||||
You can run `$INSTALL_DIR/bin/native-platform-test` to run the test application.
|
||||
|
||||
# Releasing
|
||||
|
||||
1. Create a tag and push.
|
||||
2. Build each variant:
|
||||
1. Checkout tag.
|
||||
2. `./gradlew clean test :uploadJni -Prelease -PartifactoryUserName=<> -PartifactoryPassword=<>`
|
||||
* OS X universal
|
||||
* Linux i386, using Ubunutu 8.04
|
||||
* Linux amd64, using Ubunutu 8.04
|
||||
* Windows x86, using VC++ 2010
|
||||
* Windows x64
|
||||
3. Build Java library and test app:
|
||||
1. Checkout tag.
|
||||
2. `./gradlew clean test :uploadArchives testApp:uploadArchives -Prelease`
|
||||
4. Checkout master
|
||||
5. Increment version number.
|
||||
|
||||
## Testing
|
||||
|
||||
* Test on IBM JVM.
|
||||
* Test on Java 5, 6, 7.
|
||||
* Test on Windows 7, Windows XP
|
||||
|
||||
## TODO
|
||||
|
||||
### Fixes
|
||||
|
||||
* Windows: fix detection of shared drive under VMWare fusion and Windows XP
|
||||
* 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
|
||||
|
||||
* Use wchar_to_java() for windows system and file system info.
|
||||
* Test network file systems on Mac, Linux, Windows
|
||||
* Test mount points on Windows
|
||||
* 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
|
||||
* Don't use NewString() 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.
|
||||
* Use fully decomposed form for unicode file names on hfs+ filesystems.
|
||||
* Extend FileSystem to deal with removable media.
|
||||
|
||||
### Ideas
|
||||
|
||||
* Expose platform-specific HTTP proxy configuration. Query registry on windows to determine IE settings.
|
||||
* Expose native named semaphores, mutexes and condition variables (CreateMutex, CreateSemaphore, CreateEvent, semget, sem_open, etc).
|
||||
* Expose infromation about network interfaces.
|
||||
* Fire events when filesystems or network interfaces change in some way.
|
||||
* Fire events when terminal size changes.
|
||||
* Fire events when files change.
|
||||
* Expose system keystores and authentication services.
|
||||
|
||||
Reference in New Issue
Block a user