- Added Process.getPid() and Terminal.isTerminal().

- Added a test command-line app.
This commit is contained in:
Adam Murdoch
2012-07-29 17:05:06 +10:00
parent 1d56f93e64
commit c009527afa
12 changed files with 141 additions and 25 deletions

View File

@@ -2,6 +2,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
void markFailed(JNIEnv *env, jobject result) {
jclass destClass = env->GetObjectClass(result);
@@ -30,4 +31,20 @@ Java_net_rubygrapefruit_platform_internal_PosixFileFunctions_stat(JNIEnv *env, j
jclass destClass = env->GetObjectClass(dest);
jfieldID modeField = env->GetFieldID(destClass, "mode", "I");
env->SetIntField(dest, modeField, 0777 & fileInfo.st_mode);
}
}
JNIEXPORT jint JNICALL
Java_net_rubygrapefruit_platform_internal_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
return getpid();
}
JNIEXPORT jboolean JNICALL
Java_net_rubygrapefruit_platform_internal_PosixTerminalFunctions_isatty(JNIEnv *env, jclass target, jint output) {
switch (output) {
case 0:
case 1:
return isatty(output+1) ? JNI_TRUE : JNI_FALSE;
default:
return JNI_FALSE;
}
}

View File

@@ -0,0 +1,11 @@
package net.rubygrapefruit.platform;
public class Main {
public static void main(String[] args) {
Process process = Platform.get(Process.class);
System.out.println("* PID: " + process.getPid());
Terminal terminal = Platform.get(Terminal.class);
System.out.println("* stdout: " + (terminal.isTerminal(Terminal.Output.Stdout) ? "terminal" : "not a terminal"));
System.out.println("* stderr: " + (terminal.isTerminal(Terminal.Output.Stderr) ? "terminal" : "not a terminal"));
}
}

View File

@@ -1,12 +1,13 @@
package net.rubygrapefruit.platform;
import net.rubygrapefruit.platform.internal.FileStat;
import net.rubygrapefruit.platform.internal.FunctionResult;
import net.rubygrapefruit.platform.internal.PosixFileFunctions;
import net.rubygrapefruit.platform.internal.*;
import java.io.File;
import java.io.IOException;
/**
* Provides access to the native integrations. Use {@link #get(Class)} to load a particular integration.
*/
public class Platform {
private static final Object lock = new Object();
private static boolean loaded;
@@ -23,26 +24,50 @@ public class Platform {
loaded = true;
}
}
return type.cast(new UnixFileMode() {
@Override
public void setMode(File file, int perms) {
FunctionResult result = new FunctionResult();
PosixFileFunctions.chmod(file.getPath(), perms, result);
if (result.isFailed()) {
throw new NativeException(String.format("Could not set UNIX mode on %s. Errno is %d.", file, result.getErrno()));
if (type.equals(PosixFile.class)) {
return type.cast(new DefaultPosixFile());
}
if (type.equals(Process.class)) {
return type.cast(new DefaultProcess());
}
if (type.equals(Terminal.class)) {
return type.cast(new Terminal(){
@Override
public boolean isTerminal(Output output) {
return PosixTerminalFunctions.isatty(output.ordinal());
}
}
});
}
throw new UnsupportedOperationException(String.format("Cannot load unknown native integration %s.",
type.getName()));
}
@Override
public int getMode(File file) {
FunctionResult result = new FunctionResult();
FileStat stat = new FileStat();
PosixFileFunctions.stat(file.getPath(), stat, result);
if (result.isFailed()) {
throw new NativeException(String.format("Could not get UNIX mode on %s. Errno is %d.", file, result.getErrno()));
}
return stat.mode;
private static class DefaultPosixFile implements PosixFile {
@Override
public void setMode(File file, int perms) {
FunctionResult result = new FunctionResult();
PosixFileFunctions.chmod(file.getPath(), perms, result);
if (result.isFailed()) {
throw new NativeException(String.format("Could not set UNIX mode on %s. Errno is %d.", file, result.getErrno()));
}
});
}
@Override
public int getMode(File file) {
FunctionResult result = new FunctionResult();
FileStat stat = new FileStat();
PosixFileFunctions.stat(file.getPath(), stat, result);
if (result.isFailed()) {
throw new NativeException(String.format("Could not get UNIX mode on %s. Errno is %d.", file, result.getErrno()));
}
return stat.mode;
}
}
private static class DefaultProcess implements Process {
@Override
public int getPid() throws NativeException {
return PosixProcessFunctions.getPid();
}
}
}

View File

@@ -2,7 +2,10 @@ package net.rubygrapefruit.platform;
import java.io.File;
public interface UnixFileMode extends NativeIntegration {
/**
* Functions to query and modify a file's POSIX meta-data.
*/
public interface PosixFile extends NativeIntegration {
void setMode(File path, int perms) throws NativeException;
int getMode(File path) throws NativeException;

View File

@@ -0,0 +1,8 @@
package net.rubygrapefruit.platform;
/**
* Functions to query and modify a process' meta-data
*/
public interface Process extends NativeIntegration {
int getPid() throws NativeException;
}

View File

@@ -0,0 +1,7 @@
package net.rubygrapefruit.platform;
public interface Terminal extends NativeIntegration {
enum Output {Stdout, Stderr}
boolean isTerminal(Output output);
}

View File

@@ -0,0 +1,5 @@
package net.rubygrapefruit.platform.internal;
public class PosixProcessFunctions {
public static native int getPid();
}

View File

@@ -0,0 +1,5 @@
package net.rubygrapefruit.platform.internal;
public class PosixTerminalFunctions {
public static native boolean isatty(int fildes);
}