How does USB Disk Ejector work? - java

I have a Java application that is designed to run on removable drives. I would like to add a button to allow the user to safely remove the drive the program runs on as USB Disk Ejector allows. However, I'm not sure how to achieve this (code wise) as the drive cannot be ejected if the program is running from it. I know that this program is open source, but I don't know where to find the code I am looking for and it isn't written in a language I have learnt.
I would therefore very much appreciate it if somebody could help me work out how to achieve this functionality in my Java application. Obviously I don't want to just copy, but the only thing I know at the minute is I have to pass control over to some sort of temporary script that is not on the drive I wish to eject.
Thanks in advance

As far as I know, it is not possible to implement this in pure Java as operations such as ejecting/unmounting drives are operating system-specific and not included in the default Java library which usually only supports the lowest common denominator. You need to execute some platform-specific code either by executing a script/batch file or by running native code written e.g. in C using Java's JNI mechanism.

You're right that you will need to run the application from another drive. I would follow the Java Web Start CD Install guide, which should work just as well for a USB drive or any other media as it does for CDs.
You would need to make your application a Java Web Start application. It's actually much easier than it sounds; your .jar does not need to change, you just create a small XML file with a .jnlp extension and place it next to the .jar file. Information on Java Web Start and JNLP files can be found in the tutorial and in the links at the bottom of that page.
Your external executable which performs the safe removal can be included in your application .jar file. You can copy it from your .jar to a temporary file in order to run it:
Path safeRemovalProgram = Files.createTempFile(null, ".exe");
try (InputStream stream =
MyApp.class.getResourceAsStream("saferemoval.exe")) {
Files.copy(stream, safeRemovalProgram,
StandardCopyOption.REPLACE_EXISTING);
}
safeRemovalProgram.toFile().setExecutable(true);
ProcessBuilder builder =
new ProcessBuilder(safeRemovalProgram.toString());
builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process safeRemovalProcess = builder.start();

Related

java: how to copy the currently executing file

I have a jar. I want the jar to be able to make a copy of itself while running. I understand windows may have problems with this. How would I do this, or am I over thinking it?
Edit: To explain a bit more....
I'm writing a repackagable firmware deployment system... http://code.google.com/p/heimdall-one-click/ The idea is that a ROM developer from XDA can make his own, then pack it up in a cross-platform deployable one-click packaging nearly as easily as it is to deploy the firmware.
My program takes alot of the work out by automating the tasks... I'm trying to automate packaging of the one-click deployable packaging system.... give the developers a form to fill out which will change the header information, then they select their firmware files to be deployed. I'm trying to keep it all in one jar.
As josh says, it would be nice if you tell why do you want to do this in order to help.
Answering only what have you post, copying the jar is just copying another file. There is the issue that it might be blocked by the OS (Windows); another issue is how do you locate it in the machine and if the user running the process has the permissions needed.
Once those two issues are solved, it is just a copy operation, the OS could not care less that if the order to copy comes from the process run from the file or from another one.
EDIT to asnwer changes in the first post.
As I told before, in the end copying a file is a OS issue. If you want to copy the current jar in Windows, then the jar must not be locked by other process so it becomes an OS question rather than a Java one.
Possible workarounds:
The faster (but dirtiest) is to launch a .bat that does a sleep of a few seconds and then does the copy. Immediately after launching it, your close your java app. If you need to continue doing things in Java, after copying the file, the .bat launches the java app again (with the appropiate parameters).
A variant of the previous is slightly sleazier... launch your java app from a .bat, and the first thing that .bat does is copying your jar to the PC temp directory. Be sure to document it well so your users do not get scared!
JNI library to unlock a file. There are several programs that (Unlocker) that try to unlock files; do not know to which point it is effective or how will it affect the JVM.
I believe you can use:
File file = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
to get a reference to the path to the .JAR file.
Then you just make a copy of it:
http://download.oracle.com/javase/tutorial/essential/io/copy.html
Your operating system might not allow this, but I think it should.

Windows Mobile: automatically copy files on reboot

I have a Java app that runs on a Windows mobile device. At startup the app talks to our server to see if any files need updating and downloads them if they do. If any of the files are dlls they need to be stored in a temp directory and the device is rebooted because they might be currently in use. When the app starts it reads an xml file that lists all of the temp files and where they need to go and copies them into place.
A new requirement has come up that involves also updating the JVM files as part of this process. Since the code that does the copying is run on the JVM there is no way to do it since the files will always be in use. So we are looking at writing something in native code to do this copying process.
Before we start, I was just wondering if anyone knew of an already existing application or technique that does this (someone suggested a registry entry that tells the device to copy files on startup for example). Basically the requirement is to read some sort of configuration file that details the location of the source file and the destination then performs the copy. Any ideas before I reinvent the wheel by writing an app myself?
If your target handsets are handheld barcode scanners (Symbol, Intermec, etc.) they already have a framework in place for this. I don't have all the details, but I know from previous projects that they have a "protected" memory location that allows application to essentially re-configure / copy themselves from hard boots and similar problems. It might be worth seeing if any of that would work on your existing targets.
The scanners use either Windows CE or Windows Mobile.
In the absence of another answer, I have written a simple app to do it and put it in the startup directory. Was pretty easy, just didn't want to reinvent the wheel.
You can also rename your running executable file by the running-application itself. After this you can copy the file into the directory and simply restart your application.

Delete file in java

I want to delete file on windows OS using java, how ever some time file may be in use by external process, how can I delete forcefully or by knowing which process use that and kill that process or any how, any code or way?
Java doesn't have any built-in tools to find out what process opened specific file. This is OS-specific. You must run some external tools for that, but I don't know any Windows command-line tool allowing you to do that.
You can call low level Windows routines via JNI (http://www.atwistedweb.com/java/jni.html) or JNA (http://jna.java.net/)
But how about a more simple solution: Download Unlocker and run it with ProcessBuilder.

Proper method to find user's My Documents folder on Windows with Java?

For whatever reason, I sometimes need to find the current user's My Documents folder on Windows in a Java program to read some files. But as far as I can tell, there is no way to do it that isn't severely flawed.
The first wrong way: System.getProperty("user.home");
Why it won't work:
It only returns the \username\ folder; I'd need to add "\Documents\" on to the end to get the Documents folder... and that only works in English.
Sun bugs 6519127 and 4787931. Java finds the user home folder on Windows by reading a deprecated registry key* to find the Desktop then taking the parent; this method has multiple known problems that will easily cause a completely wrong folder to be returned. The bugs are 3.75 years and 8 years old with no fix.
The second wrong way: Using a registry-reading program to get the Personal folder of the user, which is My Documents (but i18n'd).
Why it won't work:
While it fixes the English-only problem, it's still using the same deprecated registry area, so the bugs still apply to it.
The deprecated registry key says to use a native call (SHGetKnownFolderPath) which I obviously can't do from Java.
The third wrong way:
JFileChooser fr = new JFileChooser();
FileSystemView fw = fr.getFileSystemView();
File documents = fw.getDefaultDirectory();
Why it won't work: It works great!
Except when it doesn't. While I had a program that used this open and running in the background, I opened a DirectX game (Fallout: New Vegas). The Java program immediately terminated with no stack trace. Always reproducible (for me on that game, and who knows what else). Couldn't find a Sun bug#.
So is there any method to find a user's Documents folder, on Windows, from Java, that doesn't have known problems?
(This is a nice big question.)
*(The key is "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
There's no pure java way to do it, but you could use the JNA wrapper over JNI to do it without having to write any native code yourself. There's a good example of how to get the Documents folder on Windows halfway down the responses at:
What is the best way to find the users home directory in Java?
A time consuming, but reliable way of finding the 'Documents' folder of a windows user: Make your java app execute a bat script that uses Reg.exe (a windows system file) to find the value of the reg key which has the path in it. Then use a pipeline in the same bat file to send that data to the 'findstr' function which windows command prompt has. Use another pipeline to output the returned value to a text file. Then, simply make your java app read that text file, and delete it once its done :) Worked well enough for me.
Code for the bat file:
# echo off
Title Find Documents Folder
Reg Query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" |findstr "Personal">>DocPath.dat
exit
There is a custom Java API that someone built (their website no longer works), but there code remains on Google Code:
http://winfoldersjava.googlecode.com/files/WinFoldersJava_1.1.zip
There are two DLL's that need to be referenced, one for each architecture(x86 and x64).
user.home is not "my documents", but users home folder, like on Unix ~/.
To get to "My documents" you can use System.getProperty("user.home")+"\Documents"; irrespective of the language system. Try it.

How to call c++ functionality from java

I have a Java program that is mostly GUI and it shows data that is written to an xml file from a c++ command line tool. Now I want to add a button to the java program to refresh the data. This means that my program has to call the c++ functionality.
Is the best way to just call the program from java through a system call?
The c++ program will be compiled for mac os and windows and should always be in the same directory as the java program.
I would like to generate an executable can the c program be stored inside the jar and called from my program?
If you have access to the code and want an 'interactive' experience with the external program (e.g., make call, get results, make additional calls), investigate JNI, which allows you to call C or C++ code from a Java application by including & linking JNI juice to your C or C++ app with .
See:
http://en.wikipedia.org/wiki/Java_Native_Interface
http://www.acm.org/crossroads/xrds4-2/jni.html
If you really just need a "launch app and get results" sort of solution, check out Runtime.exec(), which lets you launch an external program & capture its output.
See:
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1
http://www.rgagnon.com/javadetails/java-0014.html
Assuming no better communication method is available (SOAP, ICE, Sockets, etc), I'd call the executable using Runtime.exec(). JNI can be used to interface directly, but I wouldn't recommended it. No you can't put an executable in the jar. Well you can, but you can't run it, since the shell doesn't know how to run it.
You may also want to look at the Java Native Access API (JNA).
To answer your final question, you can't run an executable from within your jar.
However, you can store it within your jar and extract it to a temporary directory/file prior to running it (check for its presence the first time and extract if necessary). This will simplify your distribution somewhat, in that you only have the jar to distribute, and ensures that you're running an executable that matches your jarred Java code.

Categories