Adding a compiler to run a java code and show the output - java

I am making an android app which can run c, c++ and java programs. The app stores the respective files in a folder and is made to execute with the following code. Whenever I click on compile button it shows an IO Exception saying "error=13 permission denied".
try {
p = Runtime.getRuntime().exec(path + "/PocketIDE/JavaPrograms/"+ filename);
BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output2.append(line).append("\n");
p.waitFor();
}
String response = output2.toString();
output.setText(response);
} catch (IOException | InterruptedException e) {
output.setText(e.toString());
e.printStackTrace();
}
Is the above method the correct way to execute the program? or do I need to change the code?

p = Runtime.getRuntime().exec(path + "/PocketIDE/JavaPrograms/"+ filename);
You shouldn't run arbitrary Java code with the runtime that controls the execution of your app. This opens a massive security flaw, so Android disallows it. Instead, you should find a way to execute the Java code in its own environment and runtime.

The statement in your code can be used to execute other programs, but it is not necessarily a good idea.
The exec method internally forks the application`s process and creates a new one, which immediately executes the system command you give it.
From the path in your code I assume that you try to execute a binary executable, which is not allowed anymore by Android since API level 28:
Untrusted apps that target Android 10 cannot invoke exec() on files within the app's home directory. This execution of files from the writable app home directory is a W^X violation. Apps should load only the binary code that's embedded within an app's APK file.
The only possible solution is to reduce the API level to 28 or include the binary in the APK file during packaging.

Related

how to build a jar with the resource file by intellij 2020 or terminal or maven plugins

Here is my simple app that I am reading a resource file and it works fine:-
public class App {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader =
new BufferedReader(
new FileReader(
Objects.requireNonNull(
Objects.requireNonNull(
App.class.getClassLoader().getResource("file.txt")
).getFile()
)
)
);
String line = "";
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
}
I want to make a executable jar file with the resource file. I follow this. Unfortunately when I run the jar it can't find. Error:- ReadFileExample.jar!/file.txt (No such file or directory). Actually, I don't need to use IDE if it is easier to do it from the terminal or maven plugins, please let me know how can I add my resource file in the jar either by the IDE or by terminal or any maven plugin ?
new FileReader(
This bit means it will never work. FileReader reads files. And only files. Hence the name. You 'luck' into it working during dev, as the resource is an actual file at that point.
There's good news though. Your code is incredibly complicated and can be made much simpler:
.getClassLoader().getResource(...) is more code AND worse than just .getResource. getCL can return null in exotic cases. Make sure to adjust the parameter; it is now relative to the place your class is in, and you can get back to 'go from root' by putting a slash in front.
Don't use FileREader, obviously. Actually, never use that class.
Your code fails to specify encoding. This is bad; the encoding will thus default to whatever the system you run it on has as default encoding which therefore by definition is not guaranteed to match what you stuck in that jar file. Always be explicit.
These are 25 year old APIs, java has nicer ones these days. Let's use them to try to make this code easier to read.
The requireNonNull calls are useless here; you already get an NPE if you try to pass a null ref to e.g. FileReader's constructor.
Your code opens a resource and doesn't safely close it. This causes you to leak handles, which means your app will soon be 'dead' - it has a bunch of objects still in memory that are holding open OS-level file handles and the OS simply won't give any further handles to your process. Any attempt to do anything that interacts with the OS (make network connections, open files, etcetera) will just flat out not work anymore, until you shut down the VM and start it up again. That's why try-with-resources exists, to protect from this. This problem is hard to catch with trivial apps and tests.
Putting it all together:
try (var raw = App.class.getResourceAsStream("/file.txt");
var in = new BufferedReader(new InputStreamReader(raw, StandardCharsets.UTF_8))) {
String line = "";
while ((line = in.readLine()) != null) {
// process line here.
}
}

Compiling and communication with shell application in Android/Java

I have a command line application (also it's source code in C language). I want to use it in my first android application.
Here are my questions:
I have a compiled executable for mac. Should I recompile it for android? If yes, how?
Is it possible to have a two way communication with an executable in shell in Java/Android?
I'm looking for something like:
Runtime.getRuntime().exec(cmd);
After a lot of googling, that line of code was only thing that I found. But I don't want to close the executable after each call (it communicates with a server on the internet). Here is what I want to do:
1. Open shell executable
2. write AAA
3. read line
4. write BBB
5. read line
6. write CCC
...
98. write XYZ
99. read line
100. close executable
Note that there may be nothing to read, and it shouldn't wait for it.
Yes, you need recompile it with NDK. How: you can find more information on official Android site, where examples also present.
Yes its also possible to do that, and there are two ways exist:
a) JNI. You need to write a wrapper for for you function, and compile a shared library
b) You can compile executable file, run it and communicate via input/output stream. Something like:
try {
Process pb = Runtime.getRuntime().exec(cmd);
String line;
BufferedReader input = new BufferedReader(new InputStreamReader(pb.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println("Input from your C/C++ app: " + line);
}
input.close();
} catch (IOException e) {
e.printStackTrace();
}

Unzipping an archive won't work when using Java, works in Terminal - Linux

I'm trying to unpack/extract an archive, which is supplied in my program, containing binaries.
The copy from within the jar to the file works just fine, but when I try to extract the zip, it returns unexpectedly and only copies half of a file, and ignores the other file completely.
Here's a bit more detailed description:
I'm trying to unzip an archive copied to a folder, from within the program's .jar.
The program I'm using to unzip is "unzip" (comes with Linux).
The command used to extract is:
unzip -o <file>.zip
which is exactly what I'm using in following code:
ProcessBuilder process = new ProcessBuilder();
process.command("unzip", "-o", adb_tools.toString());
process.redirectErrorStream(true);
Process pr = process.start();
String line;
BufferedReader processReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((line = processReader.readLine()) != null)
log(Level.INFO, "Extracting Android Debugging Bridge: " + line, true);
log(Level.INFO, "Android Debugging Bridge has been extracted and installed to system. Marking files as executable...", true);
pr.destroy();
processReader.close();
When I use the command directly via the Terminal, everything works fine, both files are extracted and inflated, and are executable, however, as mentioned above, when I use the command in Java, only one file gets copied (and even that only goes half way), and the other file is completely ignored.
How can I fix this problem, and prevent this happening again, with different programs?
Thanks in advance!
If you need to do a common task in Java, there is always a library out there which does what you need better than yourself. So use an external library for unzipping. Check here:
What is a good Java library to zip/unzip files?
It looks like you can use zip4j like this (from djangofan's answer):
public static void unzip(){
String source = "some/compressed/file.zip";
String destination = "some/destination/folder";
String password = "password";
try {
ZipFile zipFile = new ZipFile(source);
if (zipFile.isEncrypted()) {
zipFile.setPassword(password);
}
zipFile.extractAll(destination);
} catch (ZipException e) {
e.printStackTrace();
}
}

Imagemagick can't open file when executed from Java Servlet

I'm trying to convert files from png's to pdf using imagemagick and Java. I've got everything working to a place when I'm executing imagemagick command to actually merge multiple png's into one pdf. The command itself looks properly, and it works fine when executed in the terminal but my application gives me error showing that imgck can't open the file (even though it exists and I've set permissions to the folder to 777 :
line: convert: unable to open image `"/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/print-1357784001005.png"': No such file or directory # error/blob.c/OpenBlob/2642.
This is my command :
/opt/local/bin/convert "/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/print-1357784001005.png" "/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/print-1357784001219.png" "/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/complete-exportedPanel2013-01-1003:13:17.212.pdf"
And my Java code :
String filesString = "";
for (String s : pdfs){
filesString += "\""+ s + "\" ";
}
Process imgkProcess = null;
BufferedReader br = null;
File f1 = new File(pdfs[0]);
//returns true
System.out.println("OE: "+f1.exists());
String cmd = imgkPath+"convert "+ filesString+ " \""+outputPath+outName+"\"";
try {
imgkProcess = Runtime.getRuntime().exec(cmd);
InputStream stderr = imgkProcess.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
br = new BufferedReader(isr);
} catch (IOException e1) {
msg = e1.getMessage();
}
imgkProcess.waitFor();
while( (line=br.readLine() ) != null){
System.out.println("line: "+line);
}
The whole code is executed from a java servlet controller after getting request from a form. Any ideas what can cause this ? I'm using latest imgck, jdk, and osx 10.7 .
A few things:
When spawning anything but really trivial processes, it's usually better to use ProcessBuilder than Runtime.exec() - it gives you much better control
Even with ProcessBuilder, it often works better to write a shell script that does what you need. Then spawn a process to run the script. You get a lot more control in shell script than you do in ProcessBuilder
Remember that a spawned process is not a shell. It can't, for instance, evaluate expressions, or expand shell variables. If you need that, then you must execute a shell (like sh or bash). Better yet, write a shell script as described above
If all you need to do is to execute some ImageMagick commands, it would probably be easier to jmagick, a Java interface to ImageMagick - see http://www.jmagick.org/
Actually, since the you're assembling images into a PDF, the iText library - http://itextpdf.com is probably the best tool for the job, as it is native Java code, does not require spawning a native process, and will therefore be much more portable.
Solved it by adding all arguments to an arrayList and then casting it to String array.
ArrayList<String> cmd = new ArrayList<String>();
cmd.add(imgkPath+"convert");
for (int i=0, l=pdfs.length; i<l; i++){
cmd.add(pdfs[i]);
}
cmd.add(outputPath+outName);
imgkProcess = Runtime.getRuntime().exec(cmd.toArray(new String[cmd.size()]));

How to correctly run a .bat file from java under a windows service?

From my java project I want to run an external .bat file in another thread. For this purpose I use the following method:
private void posAppRunner(final String path[], final Class targetClass) {
new Thread(new Runnable() {
public void run() {
try {
String line;
Process p = Runtime.getRuntime().exec(path);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
} catch (IOException e) {
LogFactory.getLog(targetClass).warn("Error when starting a PosApplication: " + e.getMessage());
}
}
}).start();
I run the following .bat file:
call chdir %~dp0
start java <_some_arguments>
So when I do it locally from IntelliJ IDEA it works correct - a cmd process appears, after that a java process appears and after that the cmd process disappears.
But when I run my java project with this method through ANT under TeamCity windows service, only cmd process appears and nothing happens after. Java process that must be started from the bat file doesn't appear. It looks like I don't read the process output but I do!
Could you expain me, how to overcome this situation?
I believe that the problem is in current working directory. I am not so familiar with bat files and do not remember by heart what does %~dp0 mean. Anyway as the first attempt try to modify your batch file to contain the hard coded path. I believe that this will work.
In this case decide what is better for you: discover the path in java code and then pass it to batch file, generate batch file on the fly, so that it contains all parameters hard coded or debug the script. for example you can remove the start java <_some_arguments> and put
echo %~dp0 > c:\temp\batlog.log
this will print the parameter to log file. Now run it as service and see what does the log file contain. Probably you will see the problem immediately.

Categories

Resources