This question already has answers here:
How to check existence of a program in the path
(10 answers)
Closed 9 years ago.
I can print the path using System.getenv("PATH").
Then I probably can traverse those paths and use File to check if the file is exist.
Is there any faster way in Java ?
You can use Runtime.getRuntime().exec("command"); in try ... catch section. If app won't be in PATH you will get an exception.
[EDIT]
But .. this will execute app instead of check. Sorry.
Is there any faster way in Java ?
In terms of performance, no.
In terms of coding effort, probably no. Certainly I'm not aware of any 3rd-party Java library that will search the command search path to see if an executable exists.
Unfortunately searching for an executable on Windows is a little tricky because you have to account for the various types of executable ... based on file suffixes. Even on Linux / Unix you need to use the new Java 7 file attributes APIs to determine if a candidate file has the execute permissions set.
(I am aware that some commands can be run in ways that are harmless; e.g. they may support an option / argument that outputs a version string, or some help info. However, that only works in specific cases. I'm also aware that on Unix / Linux, there is a built-in shell command called "whereis" that can tell you if an executable command with a given name exists on the search path.)
Your approach will work.
I suggest using the File.listFiles(FileFilter filter) method on each directory in the path. This will make searching each directory simpler.
Related
If I have 2 Paths for files, both share the same FileStore, how can I verify with Java 17 whether they are pointing to the same file on disk (are hard-linked)? For Unix-like systems there seems at least to be a way to verify whether a file has other hardlinks (get Hard Link Count in Java), but on Windows/NTFS I haven't yet found a way to get either information, except of invoking fsutil hardlink list <file-path> and parsing the output. If necessary, a workaround using JNA would also fine for me.
PS: I have already searched Stackoverflow, but only found similar questions for Python or C#.
I doubt it can be done within Java alone.
Try to use getCanonicalPath() to at least get around relative and absolute path names. But this hardly gets you around symlinks, or symlinks in parent folders.
For such things in Linux systems there is the readlink command. There is lots to be found here on StackOverflow about it: https://stackoverflow.com/search?q=readlink
For Windows you already mentioned fsutil.
Files.isSameFile(path1, path2) checks whether they are hard-linked.
I used
Files.createTempFile("Hello", "txt");
to create a temporary file and stored the returned Path.
I have an Eclipse IFile resource linked to the temporary file I created:
linkedFile.createLink(tempFile.toUri(), IResource.NONE, null);
If I want to get a Path back from this resource, I call
linkedFile.getLocation().toFile().toPath()
On my local machine, this works 100% fine. But on a remote test machine, I get two different paths:
from Files.createTempFile: C:\Users\USERNA~1\AppData\Local\Temp\Hello3606197456871226795txt
from getLocation().toFile().toPath() C:\Users\Username_Testing\AppData\Local\Temp\Hello3606197456871226795txt
The Folder Username_Testing and only that folder gets turned into a short filename, and only for my direct creation of it as a temporary.
These two paths are not considered equal by Path.equals(...), which is causing a failing of my tests on the remote machine.
In general, this makes me a bit nervous using Path.equals(...) even though in the actual real operation of the application I haven't had any issues yet. Is there a way I can force the system to always use long filenames? Is there something I'm missing that I should be aware of when I do path equality checks, or when converting paths from one form to another?
Update #1: This specific issue is caused by %TEMP% on the target windows machine returning a path using a short filename, that doesn't happen on my local machine. Only test code creates temporary files and folders so this won't affect the real application. The obvious solution to my current problem is fix %TEMP% so the tests run fine in both places, but this solution is not viable in the general sense. It would be nice if there was a way to rectify the situation without modifying the target computer or jumping into native or windows specific code, since I used no such code directly to get both paths.
I found a good, portable solution to my problem, no need to use any platform-specific code. The answer is actually quite simple:
Path.toRealPath()
used something like this:
Path correctedTempFile = tempFile.toRealPath()
Essentially, it is now using the toRealPath() version, which thankfully removes the short filenames, for comparisons against other Paths taken from Eclipse resources. I believe the Eclipse implementation is using only long paths for consistency, so I in turn will use toRealPath to get rid of any potential paths that may use short filenames
This question might help:
Is there a way to generate the 8.3 or 'short' (Windows) version of a file name in Java?
You can get the short path and compare the generated path against both so you know which one to use.
Short version
How do I configure the icedtea-plugin package for ubuntu precise in such a way that it executes all applets with a specific memory limit by default? Preferrably using command line tools and no graphical user interface.
Long version
I'm building a kiosk setup using java applets, and would like to increase the default memory limit for all these applets. The kiosk is based on ubuntu linux, using the icedtea-plugin package as a browser plugin. As building the kiosk is automated and headless, I'd rather configure it from the command line if possible.
Here is what I've found out so far:
I'll probably have to specify a -Xmx… command line argument which will be used when starting the java virtual machine for the plugin.
It is possible to pass such arguments using a parameter in the HTML code, i.e.
<param name="java_arguments" value="-Xmx…">.
But that would mean modifying all my HTML files, which I'd rather avoid. And there is a good chance that I'd have to sign my code to make this work, which adds quite a lot of problems in other places of my project.
On my desktop system, using the Oracle VM, there is an application ControlPanel which I can use to set these command line switches. It seems that the configuration gets written to a file ~/.java/deployment/deployment.properties, where it is associated with the key deployment.javaws.jre.0.args.
That key name is not described in the specs for that file. The number 0 seems to refer to one specific JVM, as represented in one row of the table in the control panel. For each JVM, there are several values besides this args value, all sharing a common index number.
According to this wiki section, IcedTea supports a similar file, located at ~/.icedtea/. Not sure whether that means ~/.icedtea/deployment.properties or rather ~/.icedtea/deployment/deployment.properties. IcedTea does not seem to come with a ControlPanel.
As you can see, there are many hints as to how this might work, but so far I haven't seen any definite answer as to what will work. There are still many open questions:
Do I have to create this icedtea deployment file?
Do I have to include a directory named deployment in the path?
Which is the minimal set of keys that I need to specify to make this file work as intended?
Is the args value even supported by OpenJDK, even if it is not described in the corresponding specification?
I guess I could try out all possible combinations to see whether one of them works, but doing so will take considerable time. So I'm asking here, to see if someone has experience in this, and can provide a quiecker answer. If not, I guess I'll answer my own question eventually, once I've tried things the hard way.
as oracle says: http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-Desktop/html/plugin.html.
following environment variable should be set to add additional arguments to applets:
_JPI_VM_OPTIONS=-Xmx…
Moreover as the reffered site says:
Please note that you need to restart your browser after you set the environment variable. If you are setting this environment variable in the command shell, then you must use the same command shell to launch the browser so that the browser inherits the value of environment variable.
However if you doubt how to set environment variable in ubuntu, following post might be helpful: Make $JAVA_HOME easily changable in Ubuntu
I just had a look at the source code of the icedtea-web plugin. The part of the code which builds the command line seems to have no provision at all for including custom arguments, no matter their origin. So it does not matter which config files, HTML files or environment variables I edit, the code there will build the same command line to call java, disregarding all my whishes.
So if all configuration fails, what remains is hackery. One approach would be to patch the source code of the plugin, and make it include additional words into its command line. For a static addition, i.e. a single size change, this would be fairly easy. A more general fix would include the content of some environment variable, the way Peter's answer suggests. That would mean word-splitting the environment variable in question, and allocating the space for the array of words dynamically. Quite a bit of work at the C level.
As an alternative, one could tackle this at the level of the executed binary. The plugin apparently has the path of the executable hard-coded into it. In my case, this path is /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java. One can rename that binary to java.orig, and put a shell script in its place, with the following content:
#!/bin/bash
for i in "$#"; do
if [[ "${i}" == sun.applet.PluginMain ]]; then
exec "$0.orig" -Xmx512m "$#"
fi
done
exec "$0.orig" "$#"
One consequence of this approach is the fact that ps will no longer print these applets as java but instead as java.orig. Should not be a problem in most cases.
In my Java application I want to implement the option to dump/restore a PostgreSQL database. Some google research showed me that calling pg_dump/pg_restore via Java's ProcessBuilder is probably the best way to achieve this.
Now I'd like to determine the system's directory of pg_dump.exe/pg_restore.exe without asking the user to specify it manually. How can I find the PostgreSQL installation path through Java?
Thanks in advance and
all the best,
Matthias
You can't do that portably. I suggest that you just call the programs without path by default and rely on the user having set an appropriate path, and have a way for the user to configure the paths explicitly. You can also look in some likely directories for a default configuration. But it will be quite fragile in general, especially if you want to cover all of Windows, Linux, and Mac, say.
A good idea would be to simply define an environment variable called PG_HOME and use System.getEnv("PG_HOME"); to retrieve that.
Look inside the default directories first (probably somewhere C:\Program Files (x86)\PostgreSQL\...). Use different combinations to be as tolerable as possible.
If it fails, just search the file system. Nice example here.
Also see How to do a backup from a Postgresql-DB via JDBC?
How do I set the maximal jvm-memory without adding an extra batch-script to my Programm.
Answer is provided below.
It's a good question, but your implmenetation assumes a lot. I presume you have to document the name of your jar for your users to invoke "java -jar xyz.jar" on so can you also include in the documentation that "-Xmx256M" is required?
You may have more luck using a java launcher, such as this one for Windows, where you put the launcher config (path, max memory etc.) in a separate file. For cross platform, there's LaunchAnywhere, and others, which function similarly. See How can I convert my Java program to an .exe file?
To improve upon your existing scheme:
use the java.home system property to resolve the location of the JDK/JRE
use the java.class.path to set up the class path, and similarly for java.library.path if your application requires native code.
pass command arguments passed to your main method to the spanwed process
But still, this seems to be a lot of effort that at best represents a leaky abstraction, when instead simple and clear documentation would suffice.