How to read the output of a Linux command using JNA - java

I want to call Linux mount command in java using JNA and populate a list of mount points from the call result but cannot understand what should be the actual return type for the interface method.
If I use int then it prints -1 without any errors. Which I think is an indication of some sort of error.
public class MountTest {
private interface CLibrary extends Library {
String[] mount();
}
public static void main(String[] args) {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
System.out.println(INSTANCE.mount());
}
}
I tried to use different return types based on the below doc but nothing works.
Default Type Mappings
I think my problem is the incorrect signature based on
My library sometimes causes a VM crash: Double check the signature of the method causing the crash to ensure all arguments are of the appropriate size and type. Be especially careful with native pointer variations. See also information on debugging structure definitions.
Could anyone help me on this. What return type should I use so that I can get access to the list of mount points.
Update:
I was able to run a Linux command by tweaking the code as below:
public class MountTest {
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int runCommand(String cmd);
}
public static void main(String[] args) {
CLibrary.INSTANCE.runCommand("mount");
}
}
Now, the problem is, Its printing to the stdout. I don't know how to read the result from stdout using JNA

By mount documentation
mount() attaches the filesystem specified by source (which is often a
pathname referring to a device, but can also be the pathname of a
directory or file, or a dummy string) to the location (a directory or
file) specified by the pathname in target.
It means that mount syscall just mount directories, it's different from the mount command. You are probably looking for getmetent, it will list all your filesystem mount points, a implementation bellow:
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
Pointer fopen(String name, String mode);
Mount.ByReference getmntent(Pointer FILE);
}
public static void main(String[] args) {
final Pointer mountFile = CLibrary.INSTANCE.fopen("/etc/mtab", "r");
if (mountFile == null) {
System.err.println("File not exists: " + mountFile);
return;
}
Mount.ByReference mpoint;
while ((mpoint = CLibrary.INSTANCE.getmntent(mountFile)) != null) {
System.out.println(mpoint);
}
}
public static class Mount extends Structure {
public String mnt_fsname;
public String mnt_dir;
public String mnt_type;
public String mnt_opts;
public int mnt_freq;
public int mnt_passno;
#Override
protected List getFieldOrder() {
List<String> fieds = new ArrayList<>();
for (final Field f : Mount.class.getDeclaredFields()) {
if (!f.isSynthetic())
fieds.add(f.getName());
}
return fieds;
}
public static class ByReference extends Mount implements Structure.ByReference {
}
}
Obs: As I know you cannot call compiled programs from JNA, just library functions and system calls, then is impossible to call mount command, if you really want to use this command then you probably want to use Runtime.getRuntime().exec or something like that.
update
Take a look at this answer there you can differentiate what is a program and what is a syscall or library function

Related

java: how jna callback function works

I'm using a native library coded in C or C++, after a lot of multiple tests i successed to make it work, but i'm not sure if what i do correspond to the correct coding rules, and some parts are not clear for me.
So my question is : could you confirm and complete what i understood.
Thanks
the C prototype function is:
typedef void (*pfHook) (const char *pText);
and the function to set the callback function is:
short LogHookEx(void (*pfHook) (const char*));
So i created an interface for my native dll like that:
So if i understood "interface pfHookCallback" correspond to the C prototype function and "sCscSetApiLogHookEx" is a classic method from my native dll.
public interface Reader extends Library {
Reader INSTANCE = (Reader) Native.load((Platform.isWindows() ? "ReaderDll" : "c"),
Reader.class);
interface pfHookCallback extends Callback {
void invoke(String pText);
}
short LogHookEx(pfHookCallback pfHook);
}
The part that i understand less, is the part that i include in my "main":
public class Principal {
public static void main(String[] args) {
Reader.pfHookCallback pfHook = new Reader.pfHookCallback() {
public void invoke(String pText) {
System.out.println(pText);
}
};
res = Reader.INSTANCE.LogHookEx(pfHook);
To be more clear this callback function is used for tracing from an hardware device.
As described above, it's working, but it's not cleat for me.
And another question is , the goal of my code is to save the logs (so the pText string) into a file. Is there a best practice to do that, because if i create buffered writer, i don't know if it's good or not to do something like that:
public class Principal {
public static void main(String[] args) {
Reader.pfHookCallback pfHook = new Reader.pfHookCallback() {
public void invoke(String pText) {
bw.write(pText);
bw.close;
}
};
res = Reader.INSTANCE.LogHookEx(pfHook);
My question is i don't know if it's really good to open and close a file very quickly every time there is a log to be saved ?

Load data from file in java

I have the following class:
public class DataService {
static <T> void load(Structure structure, String path, DataServiceType dataService) {
//do smth
}
private interface DataServiceType<T> {
//do smth
}
private static class DataServiceInteger implements DataServiceType<Integer> {
//do smth
}
private static class DataServiceString implements DataServiceType<String> {
//do smth
}
}
I want to add there two following methods:
public static void load(Structure<Integer> structure,String path) throws IOException {
load(structure,path,new DataServiceInteger());
}
public static void load(Structure<String> structure,String path) throws IOException {
load(structure,path,new DataServiceString());
}
but both methods have same erasure. How can I achive it without changing methods names?
EDIT
I wasn't accurate. Classes implement DataServiceType have mathod :
void getDataFromString(String in, T out);
(they are paresers)
Reading from file is held in mehod static <T> void load(Structure structure, String path, DataServiceType dataService) from DataService, so M. le Rutte's solution wouldn't be good for me, because I would have to repeat myself. Is it possible to implement berry's soulution for my problem?
As you already found out, due to type erasure the runtime would not be able to distinguish between the different methods. Either the name must be different, or the arguments must be different.
However, you use a static method. My personal choice would to be to use specific instances of a DataService:
public interface DataService<T> {
Structure<T> load(Path path);
}
public StringDataService implements DataService<String> {
public Structure<String> load(Path path) {
...
}
}
public IntDataService implements DataService<Integer> {
public Structure<Integer> load(Path path) {
...
}
}
You cannot. The way type erasure works in Java, is that a 'hidden' (synthetic) method is created by the compiler during compilation which casts the object from some superclass (usually Object) to the correct type. As there are two different types in your example, the Java compiler does not know which to cast since both name and the rest of the parameters match completely.
It might be good practice to name the methods differently either way, as loading a String and loading an integer may not necessarily be handled exactly the same way. For example, you might need to load into memory a list of user input strings: in this case, the string might need to be sanitized first.
As said already, you can't do it exactly as described. However, you could do it by adding generic parameters to the load() method itself, and then making a generic DataServiceClazz type (as oppose to separate DataServiceInteger, DataServiceString classes) that implements your DataServiceType interface:
private static class DataServiceClazz<T> implements DataServiceType<T> { //Replaces DataServiceInteger, DataServiceString, etc.
//do smth
}
public static <T> void load(Structure<T> structure, String path) throws IOException {
load(structure, path, new DataServiceClazz<>());
}
This may not work, depending on your use case, since you won't be able to use different logic based on the type of T - but it's the closest pattern to what you have currently.

how to access a method of C++ library (DLL) in java

I have one c++ dll file. And I know the methods used in it. I need to call these methods from my java code. I don't have access to modify the DLL file. Please provide me a solution to do this.
I created JavaCPP exactly for that purpose. I'll copy/paste some sample code and explanations from the page:
The most common use case involves accessing some legacy library written for C++, for example, inside a file named LegacyLibrary.h containing this C++ class:
#include <string>
namespace LegacyLibrary {
class LegacyClass {
public:
const std::string& get_property() { return property; }
void set_property(const std::string& property) { this->property = property; }
std::string property;
};
}
To get the job done with JavaCPP, we can easily define a Java class such as this one--although one could use the Parser to produce it from the header file as demonstrated below:
import com.googlecode.javacpp.*;
import com.googlecode.javacpp.annotation.*;
#Platform(include="LegacyLibrary.h")
#Namespace("LegacyLibrary")
public class LegacyLibrary {
public static class LegacyClass extends Pointer {
static { Loader.load(); }
public LegacyClass() { allocate(); }
private native void allocate();
// to call the getter and setter functions
public native #StdString String get_property(); public native void set_property(String property);
// to access the member variable directly
public native #StdString String property(); public native void property(String property);
}
public static void main(String[] args) {
// Pointer objects allocated in Java get deallocated once they become unreachable,
// but C++ destructors can still be called in a timely fashion with Pointer.deallocate()
LegacyClass l = new LegacyClass();
l.set_property("Hello World!");
System.out.println(l.property());
}
}
Alternately, we can produce a Java interface by parsing the header file with a config class such as this one:
#Properties(target="LegacyLibrary", value=#Platform(include="LegacyLibrary.h"))
public class LegacyLibraryConfig implements Parser.InfoMapper {
public void map(Parser.InfoMap infoMap) {
}
}
And the following build commands:
$ javac -cp javacpp.jar LegacyLibraryConfig.java
$ java -jar javacpp.jar LegacyLibraryConfig
$ javac -cp javacpp.jar LegacyLibrary.java
$ java -jar javacpp.jar LegacyLibrary
For more complex examples including Maven/IDE integration, check out the JavaCPP Presets!

How to invoke Rhino compiled JavaScript methods (class files) in the Java program?

I compiled following JavaScript file, "test.js", into the "test.class" :
var test = (function () {
var that = {};
that.addNumbers = function (a, b) {
return a+b;
};
return that;
}());
I would like to call the compiled JavaScript function, "test.addNumbers(1,2)", in the simple Java program "run.java" as follows :
public class run {
public static void main(String[] args) throws Exception {
Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
// HOW TO CALL THE METHOD, Test.addNumbers(1,2)? Please help me!
} finally {
Context.exit();
}
}
}
I tried many ways, but failed. I read Rhino tutorial and examined many articles and examples, BUT they only show how to call JavaScript methods from the command line or the source file, "test.js".
I need to call the method from the compiled "test.class" file.
Thanks much in advance for your help!
Using javap, I believe that the JavaScript type test does not mean that the resultant Java type is this class. The generated Java type invokes the script code in its constructor; this will not result in exposing addNumbers as a Java method.
>javap -classpath . test
public class test extends org.mozilla.javascript.NativeFunction implements org.m
ozilla.javascript.Script{
public test(org.mozilla.javascript.Scriptable, org.mozilla.javascript.Contex
t, int);
public test();
public static void main(java.lang.String[]);
public final java.lang.Object exec(org.mozilla.javascript.Context, org.mozil
la.javascript.Scriptable);
public final java.lang.Object call(org.mozilla.javascript.Context, org.mozil
la.javascript.Scriptable, org.mozilla.javascript.Scriptable, java.lang.Object[])
;
public int getLanguageVersion();
public java.lang.String getFunctionName();
public int getParamCount();
public int getParamAndVarCount();
public java.lang.String getParamOrVarName(int);
public java.lang.String getEncodedSource();
public boolean getParamOrVarConst(int);
}
Reading between the lines, I'd say you need to map to Java types to do what you want. From the jsc doc:
-implements java-intf-name
Specifies that a java class
implementing the Java interface
java-intf-name should be generated
from the incoming JavaScript source
file. Each global function in the
source file is made a method of the
generated class, implementing any
methods in the interface by the same
name.
Define this interface:
//Adder.java
public interface Adder {
public int addNumbers(int a, int b);
}
Write this implementation:
//AdderImpl.js
function addNumbers(a, b) {
return a+b;
}
Compile the JavaScript with the arguments -implements Adder AdderImpl.js. Invoke the method like so:
Adder adder = new AdderImpl();
int n = adder.addNumbers(1, 2);
System.out.println(n);
I'd hazard a guess that it was probably necessary to do it this way because of differences in the languages' type systems.
I used Rhino 1.7R2. For the sake of brevity, I've avoided using packages, etc.

How to simplify this logic/code?

I want to write an apps that accepts user command. The user command is used in this format:
command -parameter
For example, the app can have "Copy", "Paste", "Delete" command
I am thinking the program should work like this :
public static void main(String args[]){
if(args[0].equalsIgnoreCase("COPY")){
//handle the copy command
} else if(args[0].equalsIgnoreCase("PASTE")){
//handle the copy command
}/**
code skipped
**/
}
So, it works, but I think it will become more and more complex when I have more command in my program, also, it is different to read. Any ideas to simply the logic?
If you are concerned about handling the command line parameters then Commons CLI is meant for this.
Go through the CommandLineParser
and if you are concerned about the complexity of your if-else then you can use Command Pattern
public interface Command {
void exec();
}
public class Copy implements Command {
void exec() {
// your copy Code
}
}
public class Paste implements Command {
void exec() {
// your Paste Code
}
}
public class Delete implements Command {
void exec() {
// your Delete Code
}
--
then
public static void main(String args[]){
Map commandMap<String,Command> = new HashMap<String,Command>();
commandMap.put("Copy", new Copy());
commandMap.put("Paste", new Paste());
commandMap.put("Delete", new Delete());
if ( commandMap.containsKey(args[0]) ){
commandMap.get(args[0]).exec();
}
}
Depending on how simple your command line syntax is, a simple enum may be your solution
public enum Command {
COPY {
#Override void execute() {
System.out.println("Copying...");
}
},
PASTE {
#Override void execute() {
System.out.println("Pasting...");
}
},
DELETE {
#Override void execute() {
System.out.println("Deleting...");
}
},
;
abstract void execute();
public static void main(String args[]) {
Command c = Command.valueOf(args[0].toUpperCase());
c.execute();
}
}
Compile and run this with java Command paste, java Command bleh, etc. You'll want to pass the rest of args to the enum in your production code. Also, valueOf throws IllegalArgumentException if no enum constant is found with the specified name.
If your syntax grows to be more complex, though, you may want to use libraries specifically designed for command line parsing, e.g. Apache Commons CLI.
Use a library to keep the messiness of command line argument parsing out of your code, for example args4j.
When I see lots of if/then/else code, I immediately think of polymorphism as a possible solution.
A Command interface and a Map would be a fine way to solve this problem. If I were writing this in Java, it might look like this:
public interface Command<T, V>
{
V execute(T parameter) throws Exception;
}
If your operations are multi-threaded, you can simply reuse the Runnable interface for Commands that don't return a value and Callable<T> for ones that do.
In either case, now your if/then/else construct is a Map where the key is the name and the value is the Command object. You look up a Command by providing the name key. You add a new command by writing a new implementation of the Command interface and adding it to the Map. Initializing the Map is something you do on startup. You can even externalize it as configuration so you don't have to modify code to add new ones (Open/Closed Principle).
There are many libraries that can handle this situation instead of writing all the code down.

Categories

Resources