I'm trying to load a dll file from a jar to work with the applet with this fix:
Extract and load DLL from JAR
I create the file, set it writable and executable, but when I check it with canWrite()/canExecute()
it returns false. The applet is signed.
The code:
private static void loadLib() {
URL res = SystemActivityNotifications.class.getResource("/sys-native
/sysactivitynotifications.dll");
InputStream in = res.openStream();
File dll = new File(path + "sysactivitynotifications.dll");
dll.setExecutable(true);
dll.setWritable(true);
logger.info(dll.canWrite() + " " + dll.canExecute());
FileOutputStream fos = new FileOutputStream(dll);
byte[] array = new byte[1024];
try {
for(int i = in.read(array); i != 1; i=in.read(array)) {
fos.write(array, 0, i);
}
} catch (IOException e) { logger.info("Cannot write to file: " + e.getMessage()); }
fos.close();
in.close();
System.load(dll.getAbsolutePath());
}
The file is created properly, but it throws an exception while trying to write to it.
edit: it writes to the file the second time I run the applet, but if I delete the file and run again the first iteration doesn't work.
Forgot to mention: all the code above is from a catch block after System.load.library(dll); throws the exception.
try
{
System.loadLibrary("sysactivitynotifications");
ptr = allocAndInit();
if (ptr == -1)
ptr = 0;
}
catch (Throwable t)
{
if (t instanceof ThreadDeath)
throw (ThreadDeath) t;
else {
loadLib();
}
}
Edit: it throws me this error:
java.lang.UnsatisfiedLinkError: C:\: The process cannot access the file because it is being used by another process
..trying to load a dll file from a jar to work with the applet..
For deploying Java applets, the best option is usually to launch the applet using Java Web Start. JWS works on Windows, OS X & *nix.
Java Web Start (JWS) is the Oracle Corporation technology used to launch rich client (Swing, Java-FX, AWT, SWT..) desktop applications directly from a network or internet link. It offers 'one click' installation for platforms that support Java.
JWS provides many appealing features including, but not limited to, splash screens, desktop integration, file associations, automatic update (including lazy downloads and programmatic control of updates), partitioning of natives & other resource downloads by platform, architecture or locale, configuration of run-time environment (minimum J2SE version, run-time options, RAM etc.), easy management of common resources using extensions..
Place the natives in the root of a (signed) Jar and put a reference to that Jar in the launch file and they will be placed on the class-path of the app.
Related
Java is the key here. I need to be able to delete files but users expect to be able to "undelete" from the recycle bin. As far as I can tell this isn't possible. Anyone know otherwise?
Ten years later, with Java 9, finally there is a builtin way to move files to the Trash Bin
java.awt.Desktop.moveToTrash(java.io.File):
public boolean moveToTrash(File file)
Moves the specified file to the trash.
Parameters:
file - the file
Returns:
returns true if successfully moved the file to the trash.
The availability of this feature for the underlying platform can be tested with Desktop.isSupported(Desktop.Action.MOVE_TO_TRASH).
For various reasons Windows has no concept of a folder that simply corresponds to the Recycle Bin.
The correct way is to use JNI to invoke the Windows SHFileOperation API, setting the FO_DELETE flag in the SHFILEOPSTRUCT structure.
SHFileOperation documention
Java example for copying a file using SHFileOperation (the Recycle Bin link in the same article doesn't work)
Java 9 has new method but in my case I am restricted to Java 8.
I found Java Native Access Platform that has hasTrash() and moveToTrash() method. I tested it on Win 10 and Mac OS (Worked) for me.
static boolean moveToTrash(String filePath) {
File file = new File(filePath);
FileUtils fileUtils = FileUtils.getInstance();
if (fileUtils.hasTrash()) {
try {
fileUtils.moveToTrash(new File[] { file });
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
} else {
System.out.println("No Trash");
return false;
}
}
Maven Repository
https://mvnrepository.com/artifact/net.java.dev.jna/jna-platform/5.1.0
Don't confuse It is Java Native Access Platform not Java Native Access
See the fileutil incubator project (part of the Java Desktop Integration Components project):
This incubator project is created to host those file utility functionalities, most of which are extensions to the java.io.File class in J2SE. There are frequent requests from Java developers for such features like: sending a file to trash bin, checking free disk space, accessing file attributes etc. This project addresses such frequently requested APIs.
Note, this should work not only on Windows, but on other platforms (Linux, Mac OS X) as well.
My 3 cents - use cmd util Recycle.exe with -f to force recycle (no prompt). Works perfectly.
public class Trash {
public void moveToTrash(File ... file) throws IOException {
moveToTrash(false, file);
}
public void promptMoveToTrash(File ... file) throws IOException {
moveToTrash(true, file);
}
private void moveToTrash(boolean withPrompt, File ... file) throws IOException {
String fileList = Stream.of(file).map(File::getAbsolutePath).reduce((f1, f2)->f1+" "+f2).orElse("");
Runtime.getRuntime().exec("Recycle.exe "+(withPrompt ? "" : "-f ")+fileList);
}
}
In JNA platform, the FileUtils doesn't use Win32 API. You should prefer W32FileUtils which supports Undo (restore the file from recycle bin).
Edit: as of the current version of JNA Platform (5.7.0), with FileUtils.getInstance(), this statement has become incorrect, and FileUtils will use the Win32 API.
In some place I create temporary file:
Files.createTempDirectory("chunk");
In some other place after processsing, I try to delete file:
Files.deleteIfExists(somePath)
and experience following trace:
java.nio.file.FileSystemException: C:\....\Temp\chunk11607697185854596263\chunk-3.csv: The process cannot access the file because it is being used by another process.
at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:92)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108)
at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:270)
at java.base/sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:110)
at java.base/java.nio.file.Files.deleteIfExists(Files.java:1180)
at my.some.project.batch.MyClass.afterStep(MyClass.java:31)
It happens when I start application on my local Windows mashine and doesn't happen in docker. Also I don't experience such error when I run application locally on MacOS. What the problem and how can I fix it ?
Check that the file isn't opened by some other process. This check can be done with Process Explorer. When you have started the program, select Find in the menu and then Find Handle or DLL..., or press Ctrl+F. Enter the name of the file that is being locked by some process and click Search.
There's a difference between Windows and Unix-like operating systems regarding the handling of removal of opened files.
On Unix-like systems a file can be removed even if it's opened by other processes. The actual file is not removed until all other processes has closed the file, but the filename entry on the filesystem is removed. The low-level file remove operation returns success as soon as the first part of the operation succeeds. Removal of the actual file data is delayed until the open count has reached 0.
On Windows the file may not be opened by any process for the low-level file remove operation to be able to succeed.
This could be a reason why you see a different behaviour when running your program on Windows versus Docker or MacOS.
There are quite a few problems around when file is deleted with Java in Windows. The most important thing is to really make sure there are no unclosed streams before trying to delete a file as VGR already mentioned.
For more info about the usual problems you could take a look at this:
delete & GC
and this: file delete
I am using this kind of awful looking "solution" for deleting files, feel free to try:
public static boolean deleteFile(File file)
throws Exception {
if (!file.exists()) {
throw new Exception("File not found: " + file.getName());
}
try {
file.setWritable(true);
} catch (Exception ignored) {
}
int delay = 50;
for (int i = 0; i < 20; i++) {
if (file.delete()) {
return true;
}
System.gc();
try {
Thread.sleep(delay);
} catch (InterruptedException ignored) {
}
delay = delay + 50;
}
throw new Exception("Could not delete the file '"
+ file.getName() + "'");
}
I'm having trouble uploading an image in my website. Sometimes, it uploads. But sometimes it also says can’t create cache file. How do I fix it?
Here's my code:
File file = new File(imagePath);
BufferedImage bi;
try{
bi = ImageIO.read(file);
}catch(javax.imageio.IIOException e){
if(request.getParameter("fi") != null){
file = new File(context.getInitParameter("ImgPath") + "placeholder/150x80.png");
}else if (request.getParameter("li") != null){
file = new File(context.getInitParameter("ImgPath") + "placeholder/150x80.png");
}
bi = ImageIO.read(file);
}
OutputStream outImg = response.getOutputStream();
File cacheDir = new File(context.getInitParameter("ImgPath") + "cache");
try {
ImageIO.setCacheDirectory(cacheDir);
ImageIO.write(bi, "png", outImg);
} catch (Exception ex) {
}
outImg.close();
Problem: Your tomcat installation is failed to create temp folder on startup or temp folder is not writable.
Solution: Make sure temp folder exists under \temp and it is writable.
You can create it manually.
Or
You can override default temp folder location of Tomcat by setting the value for CATALINA_TMPDIR environment variable in catalina.bat (windows) or catalina.sh (linux).
# CATALINA_TMPDIR (Optional) Directory path location of temporary directory
# the JVM should use (java.io.tmpdir). Defaults to
# $CATALINA_BASE/temp.
In which security context are your code in? In some implementation of 'multiple bundle on single virtual machine' framework, there can exist two types of bundles, one has permission to write temp folder, and the other does not. If the former would access ImageIO package first, ImageIO package determined that it would have permission to write temp folder, and trying to use it all of subsequent calls, but, in such frameworks, the latter can call ImageIO as well, and it will fail, since that bundle does not have access to the temp file. The behavior would change either the former would access first or vice versa, and if the latter would call ImageIO first, it won't ever use cache directory for that virtual machine instance and you don't see any troubles.
If your code does not have access to the cache directory and someone which has access to there calls ImageIO first, your code will fail.
And, it seems that your code would call ImageIO.setCacheDirectory() with your local data folder. In such frameworks, there are many cases that other bundles running on the same virtual machine would not have access to the local folder of your bundle. If so, they would have to throw IOException, if your setCacheDirectory() call was successful and you have given the directory only your code can access.
If your code successfully set the cache directory to your local data folder which other bundles cannot access to, your code might work fine, but other bundles would fail when trying to use ImageIO.
Currently, I am using ImageIO.write() in order to write to file. However, this method opens up a Java App on my computer, which then forcefully aborts the Bootstrap process if closed, thereby killing the 'server'. I'm testing locally, using IntelliJ, and the termination of the Bootstrap process means that we are unable to test the functionality without rebooting the server.
My method is below. It runs on an API call from our front-end.
/**
* Saves image to database, assuming that the input is not null or empty.
* #param filename name of file.
* #param fileext extension of file.
* #param uri uri in string form.
*/
public static void saveImageToDisk(String filename, String fileext, String uri) {
try {
String[] components = uri.split(",");
String img64 = components[1];
byte[] decodedBytes = DatatypeConverter.parseBase64Binary(img64);
BufferedImage bfi = ImageIO.read(new ByteArrayInputStream(decodedBytes));
File outputfile = new File(IMAGESTORAGEFOLDER + filename + "." + fileext);
ImageIO.write(bfi, fileext, outputfile);
bfi.flush();
} catch(Exception e) {
e.printStackTrace();
}
}
My question is as follows: How can I save an image (from Raw Data) to file without the server aborting? If my code can be adapted with minimal rewrite, what other improvements can I make to robustify my existing code? I would like a solution with no external dependencies (relying entirely on standard Java libraries).
I am on MacOSX, running IntelliJ IDEA CE. Our server runs with Spark and uses Maven.
Thank you very much.
ImageIO.write() [...] method opens up a Java App on my computer
The issue here is that when you use the ImageIO class, it will also initialize the AWT because of some dependencies in the Java2D class hierarchy. This causes the Java launcher on OS X to also open up an icon in the dock and some other things, and I believe this is what you experience. There's really no new Java application being launched.
You can easily avoid this by passing a system property to the Java launcher at startup, telling it to run in "headless" mode. This is usually appropriate for a server process. Pass the following on the command line (or in the IntelliJ launch dialog):
-Djava.awt.headless=true
Read more about headless mode from Oracle's pages. Headless mode is the cross-platform way of doing this. There's also an OS X/MacOS specific way to hide the icon from the dock (-Dapple.awt.UIElement=true, but I don't recommend that here.
However, for your use case it's better to avoid the usage of ImageIO altogether. It's easier, more compatible, faster, and uses less memory as a bonus. Simply write the Base64 decoded bytes directly to disk. There's no need to treat a file containing an image differently from any other file in this case.
You can rewrite your method as follows:
public static void saveImageToDisk(String filename, String fileext, String uri) {
try {
String[] components = uri.split(",");
String img64 = components[1];
byte[] decodedBytes = DatatypeConverter.parseBase64Binary(img64);
File outputfile = new File(IMAGESTORAGEFOLDER, filename + "." + fileext);
Paths.write(outputFile.toPath(), decodedBytes);
} catch(Exception e) {
// You really shouldn't swallow this exception, but I'll leave that to you...
e.printStackTrace();
}
}
After running multiple users at the same time, running the process multiple times, etc, it seems to just be an artifact of either Java's ImageIO or IntelliJ. As long as the new process is not closed, Bootstrap continues to run properly, even if multiple browsers try to upload images, etc.
First time posting here, will try to be succinct. This is a classic 'can't access file within an Applet' problem, but I'm having a particular difficulty with it.
I'm trying to rewrite this file:
A JavaSound test for libpd
into a template applet to load libpd (https://github.com/libpd/libpd) patches made in PureData (puredata.info)...this already works in a normal Main function in a non-applet Java program (see above), where the main function finds the patch using:
PdBase.openAudio(0, outChans, (int) sampleRate);
int patch = PdBase.openPatch("samples/com/noisepages/nettoyeur/libpd/sample/test.pd");
PdBase.computeAudio(true);
The reason it tries to load the path and file into a int variable is that the core function itself does this with:
public synchronized static int openPatch(File file) throws IOException {
if (!file.exists()) {
throw new FileNotFoundException(file.getPath());
}
String name = file.getName();
File dir = file.getParentFile();
long ptr = openFile(name, (dir != null) ? dir.getAbsolutePath() : ".");
if (ptr == 0) {
throw new IOException("unable to open patch " + file.getPath());
}
int handle = getDollarZero(ptr);
patches.put(handle, ptr);
return handle;
}
public synchronized static int openPatch(String path) throws IOException {
return openPatch(new File(path));
}
This is because PD tries to identify each patch by giving an int 'handle' (dollarZero, for legacy reasons), so that int handle gets passed around to open and close the patch file.
So now. I'm trying to load the same file in an Applet, so since I believe it runs 'in the client' and won't know what path I'm talking about, I read up on java.net.URL and tried to build variations of:
patchURL = new URL("test.pd");
PdBase.openPatch(patchURL.getPath().toString());
and
URL url = this.getClass().getResource("test.pd");
inspired by previous questionsin the init() and start() functions of the applet, turning the original main into a local static method sound().
All I get is null pointers. I would've thought all I needed was a simple getDocumentBase(), but can't seem to make it work. Anyone?
libpd is just a thin wrapper on top of Pure Data, and Pure Data doesn't know about URLs or input streams in Java. The openPatch method merely sends the patch name and directory to Pd, and then Pd will try to open the corresponding file. So, applets are out, unless you're willing to tinker with security policies.
About finding files, the simple sample program is part of the libpd Eclipse project. It's meant to be run in Eclipse, and the hard-coded path to the patch is relative to the project root in Eclipse. If you want your code to run in a different setting, you have to adjust your paths accordingly.