Reading a log file which is locked by another application - java

I want to access a log file that is locked by a third party Java application. The file is locked for the whole day and will be released the next day. However, my objective is to read it now using RandomAccessFile (must use this class because I need to start/store the last position while reading) without waiting until tomorrow.
Currently, I can read the log only if I unlock it with a file Unlocker software. Can anyone suggest any jar/utilities that I can use in my Java program to meet my objective?

Assuming you're using a Microsoft operating system:
The software Shadow Copy is using using Microsoft's volume-shadow-service (VSS) to copy locked files.
You could use the software from within the Java Runtime Environment or perhaps make use of the VSS-API yourself via Java Native Interface.
My approach would be to shadow-copy the file and then access the content through it's copy. The downside is that you're possibly reading outdated information if the file has been updated since your copy operation.
However, this is just a guess as I'm not familiar with this topic.

You can lock/unlock files and folders in Java but only by application that locked them (you programmed). However there is no Java method/class which can unlock file used by other process.
You should bundle your application with another (native) software. For example you could create shell script for Linux systems and execute it. In Java application detect in which OS it is running so you can execute proper script/software.
When application requires RW lock, system must ensure that no one else have rights to modify it, thats why you need to kill process that is using it.
If you have access to source code of that 3rd party Java application (that is actually locking file you need), then you could implement server side which will listen requests for unlocking file and approval for locking it back again.
By my opinion better approach would be to transfer file by that application to yours, then do what you want and 3rd party app can run without interruption (shouldn't be noticeable). If you need to modify it, then 3rd should wait, your modifies and send back an updated version, 3rd continue to work.

I don't see any reliable tool to do such job, my first mind is to try to avoid the lock while exposing the file as a service through any servlet or any other mechanism. The servlet reads the file once then deliver its contents as plain text (or stream)... No more lock contention
HTH
Jerome

Related

How to make Tomcat wait until web application finishes?

I have a Java web application, packaged as a "war" and deployed in Tomcat. The application uses Jersey to implement REST web services.
This application sometimes updates a text (XML) file. I guess that if Tomcat is stopped while the application is still updating this file, the file may be corrupted. In order to prevent the file corruption I would like Tomcat to wait until the file is closed before the exit. Now I wonder how to implement it.
So, my question is how to make Tomcat wait until a web application finishes.
Have a look at the ServletContextListener is particular the context Destroyed method.
Notification that the servlet context is about to be shut down.
void contextDestroyed(ServletContextEvent sce)
I'd take a different approach in your case (this may not be an answer to your question, but a proposal for your case).
Write the new xml file in a temporal one (conf.xml.tmp), so you still have the original one (conf.xml) untouched.
Once finished generating the xml, just move the newly generated one (conf.xml.tmp) on top off the original(conf.xml).
(You can also make a copy of the original for backup purposes).
This way, if tomcat stops while processing the xml generation you will always have a working xml.
The key here is that moving a file in the same disk is somehow an "atomic" operation, it will be done or not, but it will be not done half done.
Hope it helps
You can modify your shutdown script to take care of this. Make sure that file is in consistent state and then call shutdown.
You can check if file write is under process then sleep the script for say 5 min and then call shutdown.sh/shutdown.bat script.
Apart from this you can also do at java level; but i will prefer controlling it externally. This way you can modify it independent of your core application.

Security for file uploads in Java

I have a web application using Java Servlets in which the user can upload files. What can I do to prevent malicious files and viruses from being uploaded?
The ClamAV antivirus team provide a very easy interface for integrating the clamd daemon into your own programs. It is sockets-based instead of API based, so you might need to write some convenience wrappers to make it look "natural" in your code, but the end result is they do not need to maintain a dozen or more language bindings.
Alternatively, if you have enough access to the machine in question, you could simply call a command line application to do the scanning. There is enough info on starting command line applications and most if not all locally installed virusscanners have a command line option. This has the advantage that not every IP packet has to pass through the scanner (but you will have to read and parse the output of the virusscanner). It also makes sure you got the info available in your Java application so you can warn the user.
You also need to protect from Path Traversal (making sure users cannot upload files to a place they do not belong, such as overwriting a JAR file in the classpath or a DLL in the path)

Can I close file handles opened by code I don't own?

I'm using a third-party commercial library which seems to be leaking file handles (I verified this on Linux using lsof). Eventually the server (Tomcat) starts getting the infamous "Too many open files error", and I have to re-start the JVM.
I've already contacted the vendor. In the meantime, however, I would like to find a workaround for this. I do not have access to their source code. Is there any way, in Java, to clean up file handles without having access to the original File object (or FileWriter, FileOutputStream, etc.)?
a fun way would be to write a dynamic library and use LD_PRELOAD to load it for the java instance you are launching ... this DLL could override the appropriate underlying open(2) system call (or use some other logic) to close existing file descriptors of the process before passing the call to the libc implementation (or the kernel). You need to do some serious accounting and possibly deal with threads; but it can be done. Especially if you take hints from /proc/pid/fd/ for figuring whether or not a close is appropriate for the target fd.
You could, on startup, open a bunch of files and use File*putStream.getFD() to obtain a bunch of java.io.FileDescriptors, then close them, but hold onto the descriptors. Later you might be able to create streams using those stored FileDescriptors and close them.
I have not tested this, so would not be surprised if it did not work on some platforms.

Auto-reload changed files in Java

I have a lot of configuration files that modify how my application behaves. I want to be able to make a change and it gets reflected in the application right away when saving the file. Is there a Java library to help with this?
I could simply keep a list of files with their timestamps and continuously check in a background thread when a timestamp changes. Doesn't seem too difficult, but maybe there's a more efficient way to do this? Custom triggers when certain properties have changed would be nice.
I'm using Spring 3.1, is there a built-in mechanism or solution which works nicely with Spring?
UPDATE: Apparently JDK7 now includes this functionality through its Watch Service API: "Most file system implementations have native support for file change notification. The Watch Service API takes advantage of this support where available. However, when a file system does not support this mechanism, the Watch Service will poll the file system, waiting for events." So this'll be my motivation to migrate to JDK7.
Edited:
http://commons.apache.org/configuration/userguide/howto_filebased.html

How to safely update a file that has many readers and one writer?

I have a set of files. The set of files is read-only off a NTFS share, thus can have many readers. Each file is updated occasionally by one writer that has write access.
How do I ensure that:
If the write fails, that the previous file is still readable
Readers cannot hold up the single writer
I am using Java and my current solution is for the writer to write to a temporary file, then swap it out with the existing file using File.renameTo(). The problem is on NTFS, renameTo fails if target file already exists, so you have to delete it yourself. But if the writer deletes the target file and then fails (computer crash), I don't have a readable file.
nio's FileLock only work with the same JVM, so it useless to me.
How do I safely update a file with many readers using Java?
According to the JavaDoc:
This file-locking API is intended to
map directly to the native locking
facility of the underlying operating
system. Thus the locks held on a file
should be visible to all programs that
have access to the file, regardless of
the language in which those programs
are written.
I don't know if this is applicable, but if you are running in a pure Vista/Windows Server 2008 solution, I would use TxF (transactional NTFS) and then make sure you open the file handle and perform the file operations by calling the appropriate file APIs through JNI.
If that is not an option, then I think you need to have some sort of service that all clients access which is responsible to coordinate the reading/writing of the file.
On a Unix system, I'd remove the file and then open it for writing. Anybody who had it open for reading would still see the old one, and once they'd all closed it it would vanish from the file system. I don't know if NTFS has similar semantics, although I've heard that it's losely based on BSD's file system so maybe it does.
Something that should always work, no matter what OS etc, is changing your client software.
If this is an option, then you could have a file "settings1.ini" and if you want to change it, you create a file "settings2.ini.wait", then write your stuff to it and then rename it to "settings2.ini" and then delete "settings1.ini".
Your changed client software would simply always check for settings2.ini if it has read settings1.ini last, and vice versa.
This way you have always a working copy.
There might be no need for locking. I am not too familiar with the FS API on Windows, but as NTFS supports both hard links and soft links, AFAIK, you can try this if your setup allows it:
Use a hard or soft link to point to the actual file, and name the file diferently. Let everyone access the file using the link's name.
Write the new file under a different name, in the same folder.
Once it is finished, have the file point to the new file. Optimally, Windows would allow you to create the new link with replacing the existing link in one atomic operation. Then you'd effectively have the link always identify a valid file, either the old or the new one. At worst, you'd have to delete the old one first, then create the link to the new file. In that case, there'd be a short time span in which a program would not be able to locate the file. (Also, Mac OS X offers a "ExchangeObjects" function that allows you to swap two items atomically - maybe Windows offers something similar).
This way, any program that has the old file already opened will continue to access the old one, and you won't get into its way creating the new one. Only if an app then notices the existence of the new version, it could then close the current and open it again, this way getting access to the new version.
I don't know, however, how to create links in Java. Maybe you have to use some native API for that.
I hope this helps anyways.
I have been dealing with something similar recently. If you are running Java 5, perhaps you could consider using NIO file locks in conjunction with a ReentrantReadWriteLock? Make sure all code referencing the FileChannel object ALSO references the ReentrantReadWriteLock. This way the NIO locks it at a per-VM level while the reentrant lock locks it at a per-thread level.
FileLock fileLock = filechannel.lock(position, size, shared);
reentrantReadWriteLock.lock();
// do stuff
fileLock.release();
reentrantReadWriteLock.unlock();
Of course, some exception handling would be required.

Categories

Resources