net.sourceforge.cobertura.util.FileLocker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cobertura Show documentation
Show all versions of cobertura Show documentation
Cobertura is a free Java tool that calculates the percentage of
code accessed by tests. It can be used to identify which parts of
your Java program are lacking test coverage. It is based on jcoverage.
/* Cobertura - http://cobertura.sourceforge.net/
*
* Copyright (C) 2006 John Lewis
* Copyright (C) 2006 Mark Doliner
* Copyright (C) 2009 Chris van Es
*
* Note: This file is dual licensed under the GPL and the Apache
* Source License 1.1 (so that it can be used from both the main
* Cobertura classes and the ant tasks).
*
* Cobertura is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* Cobertura is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cobertura; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
package net.sourceforge.cobertura.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* This class controls access to any file so that multiple JVMs will
* not be able to write to the file at the same time.
*
* A file called "filename.lock" is created and Java's FileLock class
* is used to lock the file.
*
* The java.nio classes were introduced in Java 1.4, so this class
* does a no-op when used with Java 1.3. The class maintains
* compatability with Java 1.3 by accessing the java.nio classes
* using reflection.
*
* @author John Lewis
* @author Mark Doliner
*/
public class FileLocker {
/**
* An object of type FileLock, created using reflection.
*/
private Object lock = null;
/**
* An object of type FileChannel, created using reflection.
*/
private Object lockChannel = null;
/**
* A file called "filename.lock" that resides in the same directory
* as "filename"
*/
private File lockFile;
public FileLocker(File file) {
String lockFileName = file.getName() + ".lock";
File parent = file.getParentFile();
if (parent == null) {
lockFile = new File(lockFileName);
} else {
lockFile = new File(parent, lockFileName);
}
}
/**
* Obtains a lock on the file. This blocks until the lock is obtained.
*/
public boolean lock() {
String useNioProperty = System.getProperty("cobertura.use.java.nio");
if (System.getProperty("java.version").startsWith("1.3")
|| ((useNioProperty != null) && useNioProperty
.equalsIgnoreCase("false"))) {
return true;
}
try {
Class aClass = Class.forName("java.io.RandomAccessFile");
Method method = aClass.getDeclaredMethod("getChannel",
(Class[]) null);
lockChannel = method.invoke(new RandomAccessFile(lockFile, "rw"),
(Object[]) null);
} catch (FileNotFoundException e) {
System.err.println("Unable to get lock channel for "
+ lockFile.getAbsolutePath() + ": "
+ e.getLocalizedMessage());
return false;
} catch (InvocationTargetException e) {
System.err.println("Unable to get lock channel for "
+ lockFile.getAbsolutePath() + ": "
+ e.getLocalizedMessage());
return false;
} catch (Throwable t) {
System.err
.println("Unable to execute RandomAccessFile.getChannel() using reflection: "
+ t.getLocalizedMessage());
t.printStackTrace();
}
try {
Class aClass = Class.forName("java.nio.channels.FileChannel");
Method method = aClass.getDeclaredMethod("lock", (Class[]) null);
lock = method.invoke(lockChannel, (Object[]) null);
} catch (InvocationTargetException e) {
System.err.println("---------------------------------------");
e.printStackTrace(System.err);
System.err.println("---------------------------------------");
System.err.println("Unable to get lock on "
+ lockFile.getAbsolutePath() + ": "
+ e.getLocalizedMessage());
System.err
.println("This is known to happen on Linux kernel 2.6.20.");
System.err
.println("Make sure cobertura.jar is in the root classpath of the jvm ");
System.err
.println("process running the instrumented code. If the instrumented code ");
System.err
.println("is running in a web server, this means cobertura.jar should be in ");
System.err.println("the web server's lib directory.");
System.err
.println("Don't put multiple copies of cobertura.jar in different WEB-INF/lib directories.");
System.err
.println("Only one classloader should load cobertura. It should be the root classloader.");
System.err.println("---------------------------------------");
return false;
} catch (Throwable t) {
System.err
.println("Unable to execute FileChannel.lock() using reflection: "
+ t.getLocalizedMessage());
t.printStackTrace();
}
return true;
}
/**
* Releases the lock on the file.
*/
public void release() {
if (lock != null)
lock = releaseFileLock(lock);
if (lockChannel != null)
lockChannel = closeChannel(lockChannel);
if (!lockFile.delete()) {
System.err.println("lock file could not be deleted");
}
}
private static Object releaseFileLock(Object lock) {
try {
Class aClass = Class.forName("java.nio.channels.FileLock");
Method method = aClass.getDeclaredMethod("isValid", (Class[]) null);
if (((Boolean) method.invoke(lock, (Object[]) null)).booleanValue()) {
method = aClass.getDeclaredMethod("release", (Class[]) null);
method.invoke(lock, (Object[]) null);
lock = null;
}
} catch (Throwable t) {
System.err.println("Unable to release locked file: "
+ t.getLocalizedMessage());
}
return lock;
}
private static Object closeChannel(Object channel) {
try {
Class aClass = Class
.forName("java.nio.channels.spi.AbstractInterruptibleChannel");
Method method = aClass.getDeclaredMethod("isOpen", (Class[]) null);
if (((Boolean) method.invoke(channel, (Object[]) null))
.booleanValue()) {
method = aClass.getDeclaredMethod("close", (Class[]) null);
method.invoke(channel, (Object[]) null);
channel = null;
}
} catch (Throwable t) {
System.err.println("Unable to close file channel: "
+ t.getLocalizedMessage());
}
return channel;
}
}