Replaced printlns with logging, moved delete() to FileUtils.

This commit is contained in:
akwizgran
2011-06-27 10:38:30 +01:00
parent eaf52f57e7
commit d193f23e4c
8 changed files with 168 additions and 66 deletions

View File

@@ -1,5 +1,8 @@
package net.sf.briar.db;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.NeighbourId;
@@ -14,6 +17,9 @@ import com.google.inject.Provider;
abstract class DatabaseComponentImpl<Txn> implements DatabaseComponent {
private static final Logger LOG =
Logger.getLogger(DatabaseComponentImpl.class.getName());
protected final Database<Txn> db;
protected final Provider<Batch> batchProvider;
@@ -50,10 +56,10 @@ abstract class DatabaseComponentImpl<Txn> implements DatabaseComponent {
while(freeSpace < MIN_FREE_SPACE) {
// If disk space is critical, disable the storage of new messages
if(freeSpace < CRITICAL_FREE_SPACE) {
System.out.println("Critical cleanup");
if(LOG.isLoggable(Level.FINE)) LOG.fine("Critical cleanup");
writesAllowed = false;
} else {
System.out.println("Normal cleanup");
if(LOG.isLoggable(Level.FINE)) LOG.fine("Normal cleanup");
}
expireMessages(BYTES_PER_SWEEP);
Thread.yield();
@@ -80,15 +86,16 @@ abstract class DatabaseComponentImpl<Txn> implements DatabaseComponent {
synchronized(spaceLock) {
long now = System.currentTimeMillis();
if(bytesStoredSinceLastCheck > MAX_BYTES_BETWEEN_SPACE_CHECKS) {
System.out.println(bytesStoredSinceLastCheck
if(LOG.isLoggable(Level.FINE))
LOG.fine(bytesStoredSinceLastCheck
+ " bytes stored since last check");
bytesStoredSinceLastCheck = 0L;
timeOfLastCheck = now;
return true;
}
if(now - timeOfLastCheck > MAX_MS_BETWEEN_SPACE_CHECKS) {
System.out.println((now - timeOfLastCheck)
+ " ms since last check");
if(LOG.isLoggable(Level.FINE))
LOG.fine((now - timeOfLastCheck) + " ms since last check");
bytesStoredSinceLastCheck = 0L;
timeOfLastCheck = now;
return true;
@@ -192,14 +199,16 @@ abstract class DatabaseComponentImpl<Txn> implements DatabaseComponent {
}
}
}
System.out.println(direct + " messages affected directly, "
if(LOG.isLoggable(Level.FINE))
LOG.fine(direct + " messages affected directly, "
+ indirect + " indirectly");
}
protected void waitForPermissionToWrite() {
synchronized(writeLock) {
while(!writesAllowed) {
System.out.println("Waiting for permission to write");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Waiting for permission to write");
try {
writeLock.wait();
} catch(InterruptedException ignored) {}

View File

@@ -6,6 +6,8 @@ import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.briar.api.crypto.Password;
import net.sf.briar.api.db.DatabaseComponent;
@@ -18,6 +20,9 @@ import com.google.inject.Inject;
class H2Database extends JdbcDatabase {
private static final Logger LOG =
Logger.getLogger(H2Database.class.getName());
private final Password password;
private final File home;
private final String url;
@@ -37,7 +42,7 @@ class H2Database extends JdbcDatabase {
}
public void close() throws DbException {
System.out.println("Closing database");
if(LOG.isLoggable(Level.FINE)) LOG.fine("Closing database");
try {
super.closeAllConnections();
} catch(SQLException e) {
@@ -51,7 +56,7 @@ class H2Database extends JdbcDatabase {
long used = getDiskSpace(dir);
long quota = DatabaseComponent.MAX_DB_SIZE - used;
long min = Math.min(free, quota);
System.out.println("Free space: " + min);
if(LOG.isLoggable(Level.FINE)) LOG.fine("Free space: " + min);
return min;
}

View File

@@ -14,6 +14,8 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
@@ -27,6 +29,7 @@ import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageFactory;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.util.FileUtils;
abstract class JdbcDatabase implements Database<Connection> {
@@ -141,6 +144,9 @@ abstract class JdbcDatabase implements Database<Connection> {
private static final String INDEX_STATUSES_BY_NEIGHBOUR =
"CREATE INDEX statusesByNeighbour ON statuses (neighbourId)";
private static final Logger LOG =
Logger.getLogger(JdbcDatabase.class.getName());
private final MessageFactory messageFactory;
private final String hashType;
private final LinkedList<Connection> connections =
@@ -161,9 +167,10 @@ abstract class JdbcDatabase implements Database<Connection> {
if(resume) {
assert dir.exists();
assert dir.isDirectory();
System.out.println("Resuming from " + dir.getPath());
if(LOG.isLoggable(Level.FINE))
LOG.fine("Resuming from " + dir.getPath());
} else {
if(dir.exists()) delete(dir);
if(dir.exists()) FileUtils.delete(dir);
}
try {
Class.forName(driverClass);
@@ -173,8 +180,10 @@ abstract class JdbcDatabase implements Database<Connection> {
Connection txn = startTransaction("initialize");
try {
// If not resuming, create the tables
if(resume)
System.out.println(getNumberOfMessages(txn) + " messages");
if(resume) {
if(LOG.isLoggable(Level.FINE))
LOG.fine(getNumberOfMessages(txn) + " messages");
}
else createTables(txn);
commitTransaction(txn);
} catch(DbException e) {
@@ -183,40 +192,44 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
private void delete(File f) {
if(f.isDirectory()) for(File child : f.listFiles()) delete(child);
System.out.println("Deleting " + f.getPath());
f.delete();
}
private void createTables(Connection txn) throws DbException {
Statement s = null;
try {
s = txn.createStatement();
System.out.println("Creating localSubscriptions table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating localSubscriptions table");
s.executeUpdate(insertHashType(CREATE_LOCAL_SUBSCRIPTIONS));
System.out.println("Creating messages table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating messages table");
s.executeUpdate(insertHashType(CREATE_MESSAGES));
s.executeUpdate(INDEX_MESSAGES_BY_PARENT);
s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
s.executeUpdate(INDEX_MESSAGES_BY_TIMESTAMP);
s.executeUpdate(INDEX_MESSAGES_BY_SENDABILITY);
System.out.println("Creating neighbours table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating neighbours table");
s.executeUpdate(insertHashType(CREATE_NEIGHBOURS));
System.out.println("Creating batchesToAck table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating batchesToAck table");
s.executeUpdate(insertHashType(CREATE_BATCHES_TO_ACK));
System.out.println("Creating neighbourSubscriptions table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating neighbourSubscriptions table");
s.executeUpdate(insertHashType(CREATE_NEIGHBOUR_SUBSCRIPTIONS));
System.out.println("Creating outstandingBatches table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating outstandingBatches table");
s.executeUpdate(insertHashType(CREATE_OUTSTANDING_BATCHES));
System.out.println("Creating outstandingMessages table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating outstandingMessages table");
s.executeUpdate(insertHashType(CREATE_OUTSTANDING_MESSAGES));
s.executeUpdate(INDEX_OUTSTANDING_MESSAGES_BY_BATCH);
System.out.println("Creating ratings table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating ratings table");
s.executeUpdate(insertHashType(CREATE_RATINGS));
System.out.println("Creating receivedBundles table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating receivedBundles table");
s.executeUpdate(insertHashType(CREATE_RECEIVED_BUNDLES));
System.out.println("Creating statuses table");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Creating statuses table");
s.executeUpdate(insertHashType(CREATE_STATUSES));
s.executeUpdate(INDEX_STATUSES_BY_MESSAGE);
s.executeUpdate(INDEX_STATUSES_BY_NEIGHBOUR);
@@ -268,7 +281,8 @@ abstract class JdbcDatabase implements Database<Connection> {
assert txn != null;
synchronized(connections) {
openConnections++;
System.out.println(openConnections + " open connections");
if(LOG.isLoggable(Level.FINE))
LOG.fine(openConnections + " open connections");
}
}
txn.setAutoCommit(false);
@@ -313,7 +327,8 @@ abstract class JdbcDatabase implements Database<Connection> {
openConnections -= connections.size();
connections.clear();
while(openConnections > 0) {
System.out.println("Waiting for " + openConnections
if(LOG.isLoggable(Level.FINE))
LOG.fine("Waiting for " + openConnections
+ " open connections");
try {
connections.wait();
@@ -810,8 +825,8 @@ abstract class JdbcDatabase implements Database<Connection> {
}
rs.close();
ps.close();
System.out.println(ids.size() + " old messages, " + total
+ " bytes");
if(LOG.isLoggable(Level.FINE))
LOG.fine(ids.size() + " old messages, " + total + " bytes");
return ids;
} catch(SQLException e) {
tryToClose(rs);
@@ -920,7 +935,8 @@ abstract class JdbcDatabase implements Database<Connection> {
rs.close();
ps.close();
if(!ids.isEmpty()) {
System.out.println(ids.size() + " sendable messages, " + total
if(LOG.isLoggable(Level.FINE))
LOG.fine(ids.size() + " sendable messages, " + total
+ " bytes");
}
return ids;

View File

@@ -4,6 +4,8 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.NeighbourId;
@@ -22,6 +24,9 @@ import com.google.inject.Provider;
class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
private static final Logger LOG =
Logger.getLogger(ReadWriteLockDatabaseComponent.class.getName());
/*
* Locks must always be acquired in alphabetical order. See the Database
* interface to find out which calls require which locks. Note: this
@@ -91,7 +96,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void addNeighbour(NeighbourId n) throws DbException {
System.out.println("Adding neighbour " + n);
if(LOG.isLoggable(Level.FINE)) LOG.fine("Adding neighbour " + n);
neighbourLock.writeLock().lock();
try {
Txn txn = db.startTransaction("addNeighbour");
@@ -121,7 +126,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
boolean added = storeMessage(txn, m, null);
assert added;
} else {
System.out.println("Not subscribed");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Not subscribed");
}
db.commitTransaction(txn);
} catch(DbException e) {
@@ -201,7 +207,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void subscribe(GroupId g) throws DbException {
System.out.println("Subscribing to " + g);
if(LOG.isLoggable(Level.FINE)) LOG.fine("Subscribing to " + g);
subscriptionLock.writeLock().lock();
try {
Txn txn = db.startTransaction("subscribe");
@@ -218,7 +224,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void unsubscribe(GroupId g) throws DbException {
System.out.println("Unsubscribing from " + g);
if(LOG.isLoggable(Level.FINE)) LOG.fine("Unsubscribing from " + g);
messageLock.writeLock().lock();
try {
neighbourLock.writeLock().lock();
@@ -245,7 +251,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void generateBundle(NeighbourId n, Bundle b) throws DbException {
System.out.println("Generating bundle for " + n);
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + n);
// Ack all batches received from the neighbour
neighbourLock.writeLock().lock();
try {
@@ -256,7 +262,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
b.addAck(ack);
numAcks++;
}
System.out.println("Added " + numAcks + " acks");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Added " + numAcks + " acks");
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
@@ -275,7 +282,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
b.addSubscription(g);
numSubs++;
}
System.out.println("Added " + numSubs + " subscriptions");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Added " + numSubs + " subscriptions");
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
@@ -296,7 +304,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
if(batch.getSize() * 2 < Batch.CAPACITY) break;
}
b.seal();
System.out.println("Bundle sent, " + b.getSize() + " bytes");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Bundle sent, " + b.getSize() + " bytes");
System.gc();
}
@@ -354,7 +363,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void receiveBundle(NeighbourId n, Bundle b) throws DbException {
System.out.println("Received bundle from " + n + ", "
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received bundle from " + n + ", "
+ b.getSize() + " bytes");
// Mark all messages in acked batches as seen
messageLock.readLock().lock();
@@ -384,7 +394,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
throw e;
}
}
System.out.println("Received " + acks + " acks, " + expired
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received " + acks + " acks, " + expired
+ " expired");
} finally {
neighbourLock.writeLock().unlock();
@@ -403,7 +414,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
subs++;
db.addSubscription(txn, n, g);
}
System.out.println("Received " + subs + " subscriptions");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received " + subs + " subscriptions");
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
@@ -432,7 +444,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
if(storeMessage(txn, m, n)) stored++;
}
}
System.out.println("Received " + received
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received " + received
+ " messages, stored " + stored);
db.addBatchToAck(txn, n, batch.getId());
db.commitTransaction(txn);
@@ -450,7 +463,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
messageLock.writeLock().unlock();
}
}
System.out.println("Received " + batches + " batches");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received " + batches + " batches");
// Find any lost batches that need to be retransmitted
Set<BatchId> lost;
messageLock.readLock().lock();
@@ -478,7 +492,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
try {
Txn txn = db.startTransaction("receiveBundle:removeLost");
try {
System.out.println("Removing lost batch");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Removing lost batch");
db.removeLostBatch(txn, n, batch);
db.commitTransaction(txn);
} catch(DbException e) {

View File

@@ -3,9 +3,8 @@ package net.sf.briar.db;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.NeighbourId;
@@ -19,8 +18,14 @@ import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageId;
import com.google.inject.Inject;
import com.google.inject.Provider;
class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
private static final Logger LOG =
Logger.getLogger(SynchronizedDatabaseComponent.class.getName());
/*
* Locks must always be acquired in alphabetical order. See the Database
* interface to find out which calls require which locks.
@@ -67,7 +72,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void addNeighbour(NeighbourId n) throws DbException {
System.out.println("Adding neighbour " + n);
if(LOG.isLoggable(Level.FINE)) LOG.fine("Adding neighbour " + n);
synchronized(neighbourLock) {
Txn txn = db.startTransaction("addNeighbour");
try {
@@ -91,7 +96,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
boolean added = storeMessage(txn, m, null);
assert added;
} else {
System.out.println("Not subscribed");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Not subscribed");
}
db.commitTransaction(txn);
} catch(DbException e) {
@@ -153,7 +159,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void subscribe(GroupId g) throws DbException {
System.out.println("Subscribing to " + g);
if(LOG.isLoggable(Level.FINE)) LOG.fine("Subscribing to " + g);
synchronized(subscriptionLock) {
Txn txn = db.startTransaction("subscribe");
try {
@@ -167,7 +173,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void unsubscribe(GroupId g) throws DbException {
System.out.println("Unsubscribing from " + g);
if(LOG.isLoggable(Level.FINE)) LOG.fine("Unsubscribing from " + g);
synchronized(messageLock) {
synchronized(neighbourLock) {
synchronized(subscriptionLock) {
@@ -185,7 +191,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void generateBundle(NeighbourId n, Bundle b) throws DbException {
System.out.println("Generating bundle for " + n);
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + n);
// Ack all batches received from the neighbour
synchronized(neighbourLock) {
Txn txn = db.startTransaction("generateBundle:acks");
@@ -195,7 +201,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
b.addAck(ack);
numAcks++;
}
System.out.println("Added " + numAcks + " acks");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Added " + numAcks + " acks");
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
@@ -211,7 +218,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
b.addSubscription(g);
numSubs++;
}
System.out.println("Added " + numSubs + " subscriptions");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Added " + numSubs + " subscriptions");
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
@@ -230,7 +238,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
if(batch.getSize() * 2 < Batch.CAPACITY) break;
}
b.seal();
System.out.println("Bundle sent, " + b.getSize() + " bytes");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Bundle sent, " + b.getSize() + " bytes");
System.gc();
}
@@ -268,7 +277,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
public void receiveBundle(NeighbourId n, Bundle b) throws DbException {
System.out.println("Received bundle from " + n + ", "
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received bundle from " + n + ", "
+ b.getSize() + " bytes");
// Mark all messages in acked batches as seen
synchronized(messageLock) {
@@ -296,7 +306,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
throw e;
}
}
System.out.println("Received " + acks + " acks, " + expired
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received " + acks + " acks, " + expired
+ " expired");
}
}
@@ -310,7 +321,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
subs++;
db.addSubscription(txn, n, g);
}
System.out.println("Received " + subs + " subscriptions");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received " + subs + " subscriptions");
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
@@ -334,7 +346,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
if(storeMessage(txn, m, n)) stored++;
}
}
System.out.println("Received " + received
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received " + received
+ " messages, stored " + stored);
db.addBatchToAck(txn, n, batch.getId());
db.commitTransaction(txn);
@@ -346,7 +359,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
}
}
}
System.out.println("Received " + batches + " batches");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Received " + batches + " batches");
// Find any lost batches that need to be retransmitted
Set<BatchId> lost;
synchronized(messageLock) {
@@ -366,7 +380,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
synchronized(neighbourLock) {
Txn txn = db.startTransaction("receiveBundle:removeLost");
try {
System.out.println("Removing lost batch");
if(LOG.isLoggable(Level.FINE))
LOG.fine("Removing lost batch");
db.removeLostBatch(txn, n, batch);
db.commitTransaction(txn);
} catch(DbException e) {

View File

@@ -15,7 +15,7 @@ class BatchImpl implements Batch {
private long size = 0L;
public void seal() {
System.out.println("FIXME: Calculate batch ID");
// FIXME: Calculate batch ID
byte[] b = new byte[BatchId.LENGTH];
new Random().nextBytes(b);
id = new BatchId(b);

View File

@@ -121,6 +121,43 @@ public class FileUtilsTest extends TestCase {
assertEquals("three three three".length(), dest3.length());
}
@Test
public void testDeleteFile() throws IOException {
File foo = new File(testDir, "foo");
foo.createNewFile();
assertTrue(foo.exists());
FileUtils.delete(foo);
assertFalse(foo.exists());
}
@Test
public void testDeleteDirectory() throws IOException {
File f1 = new File(testDir, "abc/def/1");
File f2 = new File(testDir, "abc/def/2");
File f3 = new File(testDir, "abc/3");
File abc = new File(testDir, "abc");
File def = new File(testDir, "abc/def");
TestUtils.createFile(f1, "one one one");
TestUtils.createFile(f2, "two two two");
TestUtils.createFile(f3, "three three three");
assertTrue(f1.exists());
assertTrue(f2.exists());
assertTrue(f3.exists());
assertTrue(abc.exists());
assertTrue(def.exists());
FileUtils.delete(def);
assertFalse(f1.exists());
assertFalse(f2.exists());
assertTrue(f3.exists());
assertTrue(abc.exists());
assertFalse(def.exists());
}
@After
public void tearDown() throws IOException {
TestUtils.delete(testDir);

View File

@@ -84,6 +84,11 @@ public class FileUtils {
}
}
public static void delete(File f) {
if(f.isDirectory()) for(File child : f.listFiles()) delete(child);
f.delete();
}
public interface Callback {
void processingFile(File f);