mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-21 00:29:21 +01:00
no-op
Former-commit-id: 0c024f815e7a766b99473f40086f2cfeb4f97aa8
This commit is contained in:
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Dependency-check-core 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 3 of the License, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* Dependency-check-core 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
|
||||||
|
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.concurrency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If thrown, indicates that a problem occurred when locking a directory.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@owasp.org)
|
||||||
|
*/
|
||||||
|
public class DirectoryLockException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default serial version UID.
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Directory Lock Exception.
|
||||||
|
*/
|
||||||
|
public DirectoryLockException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Directory Lock Exception.
|
||||||
|
*
|
||||||
|
* @param msg the message describing the exception
|
||||||
|
*/
|
||||||
|
public DirectoryLockException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Directory Lock Exception.
|
||||||
|
*
|
||||||
|
* @param ex the cause of the exception
|
||||||
|
*/
|
||||||
|
public DirectoryLockException(Throwable ex) {
|
||||||
|
super(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Directory Lock Exception.
|
||||||
|
*
|
||||||
|
* @param msg the message describing the exception
|
||||||
|
* @param ex the cause of the exception
|
||||||
|
*/
|
||||||
|
public DirectoryLockException(String msg, Throwable ex) {
|
||||||
|
super(msg, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Dependency-check-core 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 3 of the License, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* Dependency-check-core 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
|
||||||
|
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.concurrency;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.nio.channels.AsynchronousCloseException;
|
||||||
|
import java.nio.channels.ClosedChannelException;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.channels.FileLock;
|
||||||
|
import java.nio.channels.FileLockInterruptionException;
|
||||||
|
import java.nio.channels.NonWritableChannelException;
|
||||||
|
import java.nio.channels.OverlappingFileLockException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a spin lock on a given directory. If the lock cannot be obtained,
|
||||||
|
* the process will "spin" waiting for an opportunity to obtain the lock
|
||||||
|
* requested.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@owasp.org)
|
||||||
|
*/
|
||||||
|
public class DirectorySpinLock implements Closeable /*, AutoCloseable*/ {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the lock file.
|
||||||
|
*/
|
||||||
|
public static final String LOCK_NAME = "data.lock";
|
||||||
|
/**
|
||||||
|
* The maximum wait period used when attempting to obtain a lock.
|
||||||
|
*/
|
||||||
|
public static final int MAX_SPIN = 100;
|
||||||
|
/**
|
||||||
|
* The file channel used to perform the lock.
|
||||||
|
*/
|
||||||
|
private FileChannel channel = null;
|
||||||
|
/**
|
||||||
|
* The file used to perform the lock.
|
||||||
|
*/
|
||||||
|
private File lockFile = null;
|
||||||
|
/**
|
||||||
|
* The lock object.
|
||||||
|
*/
|
||||||
|
private FileLock lock = null;
|
||||||
|
/**
|
||||||
|
* The maximum number of seconds that the spin lock will wait while trying
|
||||||
|
* to obtain a lock.
|
||||||
|
*/
|
||||||
|
private long maxWait = MAX_SPIN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum wait time, in seconds, that the spin lock will wait while
|
||||||
|
* trying to obtain a lock.
|
||||||
|
*
|
||||||
|
* @return the number of seconds the spin lock will wait
|
||||||
|
*/
|
||||||
|
public long getMaxWait() {
|
||||||
|
return maxWait / 2; //sleep is for 500, so / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum wait time, in seconds, that the spin lock will wait while
|
||||||
|
* trying to obtain a lock.
|
||||||
|
*
|
||||||
|
* @param maxWait the number of seconds the spin lock will wait
|
||||||
|
*/
|
||||||
|
public void setMaxWait(long maxWait) {
|
||||||
|
this.maxWait = maxWait * 2; //sleep is for 500, so * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new spin lock on the given directory.
|
||||||
|
*
|
||||||
|
* @param directory the directory to monitor/lock
|
||||||
|
* @throws InvalidDirectoryException thrown if there is an issue with the
|
||||||
|
* directory provided
|
||||||
|
* @throws DirectoryLockException thrown there is an issue obtaining a
|
||||||
|
* handle to the lock file
|
||||||
|
*/
|
||||||
|
public DirectorySpinLock(File directory) throws InvalidDirectoryException, DirectoryLockException {
|
||||||
|
checkDirectory(directory);
|
||||||
|
lockFile = new File(directory, LOCK_NAME);
|
||||||
|
RandomAccessFile file = null;
|
||||||
|
try {
|
||||||
|
file = new RandomAccessFile(lockFile, "rw");
|
||||||
|
} catch (FileNotFoundException ex) {
|
||||||
|
throw new DirectoryLockException("Lock file not found", ex);
|
||||||
|
}
|
||||||
|
channel = file.getChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to obtain an exclusive lock; an exception is thrown if the lock
|
||||||
|
* could not be obtained. This method may block for a few seconds if a lock
|
||||||
|
* cannot be obtained.
|
||||||
|
*
|
||||||
|
* @throws DirectoryLockException thrown if there is an exception obtaining
|
||||||
|
* the lock
|
||||||
|
*/
|
||||||
|
public void obtainSharedLock() throws DirectoryLockException {
|
||||||
|
obtainLock(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to obtain an exclusive lock; an exception is thrown if the lock
|
||||||
|
* could not be obtained. This method may block for a few seconds if a lock
|
||||||
|
* cannot be obtained.
|
||||||
|
*
|
||||||
|
* @throws DirectoryLockException thrown if there is an exception obtaining
|
||||||
|
* the lock
|
||||||
|
*/
|
||||||
|
public void obtainExclusiveLock() throws DirectoryLockException {
|
||||||
|
obtainLock(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to obtain a lock; an exception is thrown if the lock could not
|
||||||
|
* be obtained. This method may block for a few seconds if a lock cannot be
|
||||||
|
* obtained.
|
||||||
|
*
|
||||||
|
* @param shared true if the lock is shared, otherwise false
|
||||||
|
* @param maxWait the maximum time to wait, in seconds, while trying to
|
||||||
|
* obtain the lock
|
||||||
|
* @throws DirectoryLockException thrown if there is an exception obtaining
|
||||||
|
* the lock
|
||||||
|
*/
|
||||||
|
protected void obtainLock(boolean shared, long maxWait) throws DirectoryLockException {
|
||||||
|
setMaxWait(maxWait);
|
||||||
|
obtainLock(shared);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to obtain a lock; an exception is thrown if the lock could not
|
||||||
|
* be obtained. This method may block for a few seconds if a lock cannot be
|
||||||
|
* obtained.
|
||||||
|
*
|
||||||
|
* @param shared true if the lock is shared, otherwise false
|
||||||
|
* @throws DirectoryLockException thrown if there is an exception obtaining
|
||||||
|
* the lock
|
||||||
|
*/
|
||||||
|
protected void obtainLock(boolean shared) throws DirectoryLockException {
|
||||||
|
if (lock != null) {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
if (channel == null) {
|
||||||
|
throw new DirectoryLockException("Unable to create lock, no file channel exists");
|
||||||
|
}
|
||||||
|
int count = 0;
|
||||||
|
Exception lastException = null;
|
||||||
|
while (lock == null && count++ < maxWait) {
|
||||||
|
try {
|
||||||
|
lock = channel.lock(0, Long.MAX_VALUE, shared);
|
||||||
|
} catch (AsynchronousCloseException ex) {
|
||||||
|
lastException = ex;
|
||||||
|
} catch (ClosedChannelException ex) {
|
||||||
|
lastException = ex;
|
||||||
|
} catch (FileLockInterruptionException ex) {
|
||||||
|
lastException = ex;
|
||||||
|
} catch (OverlappingFileLockException ex) {
|
||||||
|
lastException = ex;
|
||||||
|
} catch (NonWritableChannelException ex) {
|
||||||
|
lastException = ex;
|
||||||
|
} catch (IOException ex) {
|
||||||
|
lastException = ex;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lock == null) {
|
||||||
|
if (lastException == null) {
|
||||||
|
throw new DirectoryLockException("Unable to obtain lock");
|
||||||
|
} else {
|
||||||
|
throw new DirectoryLockException("Unable to obtain lock", lastException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a few simple rudimentary checks on the specified directory.
|
||||||
|
* Specifically, does the file exist and is it a directory.
|
||||||
|
*
|
||||||
|
* @param directory the File object to inspect
|
||||||
|
* @throws InvalidDirectoryException thrown if the directory is null or is
|
||||||
|
* not a directory
|
||||||
|
*/
|
||||||
|
private void checkDirectory(File directory) throws InvalidDirectoryException {
|
||||||
|
if (directory == null) {
|
||||||
|
throw new InvalidDirectoryException("Unable to obtain lock on a null File");
|
||||||
|
}
|
||||||
|
if (!directory.isDirectory()) {
|
||||||
|
final String msg = String.format("File, '%s', does not exist or is not a directory", directory.getAbsolutePath());
|
||||||
|
throw new InvalidDirectoryException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases any locks and closes the underlying channel.
|
||||||
|
*
|
||||||
|
* @throws IOException if an IO Exception occurs
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
release();
|
||||||
|
// TODO uncomment this once support for 1.6 is dropped.
|
||||||
|
// if (lock != null) {
|
||||||
|
// try {
|
||||||
|
// lock.close();
|
||||||
|
// } catch (IOException ex) {
|
||||||
|
// Logger.getLogger(DirectorySpinLock.class.getName()).log(Level.FINEST, "Unable to close file lock due to IO Exception", ex);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (channel != null) {
|
||||||
|
try {
|
||||||
|
channel.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(DirectorySpinLock.class.getName()).log(Level.FINEST, "Unable to close the channel for the file lock", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lockFile != null) {
|
||||||
|
if (lockFile.exists()) {
|
||||||
|
/* yes, this delete could fail which is totally fine. The other
|
||||||
|
* thread holding the lock while delete it.
|
||||||
|
*/
|
||||||
|
lockFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases the lock. Any exceptions that are thrown by the underlying lock
|
||||||
|
* during the release are ignored.
|
||||||
|
*/
|
||||||
|
public void release() {
|
||||||
|
if (lock != null) {
|
||||||
|
try {
|
||||||
|
lock.release();
|
||||||
|
} catch (ClosedChannelException ex) {
|
||||||
|
Logger.getLogger(DirectorySpinLock.class.getName()).log(Level.FINEST, "Uable to release file lock", ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(DirectorySpinLock.class.getName()).log(Level.FINEST, "Unable to release file lock due to IO Exception", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Dependency-check-core 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 3 of the License, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* Dependency-check-core 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
|
||||||
|
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.concurrency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If thrown, indicates that there is a problem with a directory.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@owasp.org)
|
||||||
|
*/
|
||||||
|
public class InvalidDirectoryException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default serial version UID.
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Invalid Directory Exception.
|
||||||
|
*/
|
||||||
|
public InvalidDirectoryException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Invalid Directory Exception.
|
||||||
|
*
|
||||||
|
* @param msg the message describing the exception
|
||||||
|
*/
|
||||||
|
public InvalidDirectoryException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Invalid Directory Exception.
|
||||||
|
*
|
||||||
|
* @param ex the cause of the exception
|
||||||
|
*/
|
||||||
|
public InvalidDirectoryException(Throwable ex) {
|
||||||
|
super(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Invalid Directory Exception.
|
||||||
|
*
|
||||||
|
* @param msg the message describing the exception
|
||||||
|
* @param ex the cause of the exception
|
||||||
|
*/
|
||||||
|
public InvalidDirectoryException(String msg, Throwable ex) {
|
||||||
|
super(msg, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* <html>
|
||||||
|
* <head>
|
||||||
|
* <title>org.owasp.dependencycheck.concurrency</title>
|
||||||
|
* </head>
|
||||||
|
* <body>
|
||||||
|
* Contains classes used to create shared and exclusive locks on directories.
|
||||||
|
* </body>
|
||||||
|
* </html>
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.concurrency;
|
||||||
Reference in New Issue
Block a user