/**
* This file is part of muCommander, http://www.mucommander.com
* Copyright (C) 2002-2016 Maxence Bernard
*
* muCommander is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* muCommander 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.mucommander.commons.file;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Random;
/**
* DebugFile is a {@link ProxyFile} to be used for debugging purposes. It allows to track the calls made to
* {@link com.mucommander.commons.file.AbstractFile} methods that are commonly I/O-bound, by logging calls to each of those
* methods. It also allows to slow those methods down to simulate a slow filesytem.
*
* @author Maxence Bernard
*/
public class DebugFile extends ProxyFile {
private static final Logger LOGGER = LoggerFactory.getLogger(DebugFile.class);
/** Maximum latency in milliseconds */
private int maxLatency;
/** Used to randomize the latency for each calls to slowed-down methods */
private static Random random = new Random();
/**
* Creates a DebugFile that proxies the calls made to the given AbstractFile's methods, with no latency.
*
* @param file the AbstractFile to proxy and debug
*/
public DebugFile(AbstractFile file) {
this(file, 0);
}
/**
* Creates a DebugFile that proxies the calls made to the given AbstractFile and slows those methods down by
* simulating latency by making I/O bound methods wait.
*
* @param file the AbstractFile to proxy and debug
* @param maxLatency the maximum amount of latency in milliseconds
*/
public DebugFile(AbstractFile file, int maxLatency) {
super(file);
this.maxLatency = maxLatency;
}
/**
* Sets the the maximum amount of latency in milliseconds to add to calls made to IO-bound AbstractFile methods
* (i.e. those that are overridden by this class). The latency is randomized for each method call and uniformly
* distributed, the specified value serving as the maximum.
*
* @param maxLatency the maximum amount of latency in milliseconds to add to IO-bound AbstractFile method calls
* (those overridden by this class).
*/
public void setMaxLatency(int maxLatency) {
this.maxLatency = maxLatency;
}
/**
* Sleeps a random number of milliseconds, up to {@link #maxLatency}.
*/
private void lag() {
if(maxLatency>0) {
try {
Thread.sleep(random.nextInt(maxLatency));
}
catch(InterruptedException e) {}
}
}
/**
* Returns the debug string printed for all calls made to the AbstractFile methods overridden by this class.
*/
private String getDebugString() {
return "called on "+super.getAbsolutePath()+" ("+file.getClass().getName()+")";
}
/////////////////////////////////////////////////////
// Overridden methods (traced/slowed down methods) //
/////////////////////////////////////////////////////
@Override
public long getDate() {
LOGGER.trace(getDebugString());
lag();
return super.getDate();
}
@Override
public long getSize() {
LOGGER.trace(getDebugString());
lag();
return super.getSize();
}
@Override
public boolean exists() {
LOGGER.trace(getDebugString());
lag();
return super.exists();
}
@Override
public boolean isDirectory() {
LOGGER.trace(getDebugString());
lag();
return super.isDirectory();
}
@Override
public boolean isSymlink() {
LOGGER.trace(getDebugString());
lag();
return super.isSymlink();
}
@Override
public long getFreeSpace() throws IOException, UnsupportedFileOperationException {
LOGGER.trace(getDebugString());
lag();
return super.getFreeSpace();
}
@Override
public long getTotalSpace() throws IOException, UnsupportedFileOperationException {
LOGGER.trace(getDebugString());
lag();
return super.getTotalSpace();
}
@Override
public String getName() {
LOGGER.trace(getDebugString());
lag();
return super.getName();
}
@Override
public String getExtension() {
LOGGER.trace(getDebugString());
lag();
return super.getExtension();
}
@Override
public String getAbsolutePath() {
LOGGER.trace(getDebugString());
lag();
return super.getAbsolutePath();
}
@Override
public String getCanonicalPath() {
LOGGER.trace(getDebugString());
lag();
return super.getCanonicalPath();
}
@Override
public AbstractFile getCanonicalFile() {
LOGGER.trace(getDebugString());
lag();
return super.getCanonicalFile();
}
@Override
public boolean isArchive() {
LOGGER.trace(getDebugString());
lag();
return super.isArchive();
}
@Override
public boolean isHidden() {
LOGGER.trace(getDebugString());
lag();
return super.isHidden();
}
@Override
public FilePermissions getPermissions() {
LOGGER.trace(getDebugString());
lag();
return super.getPermissions();
}
@Override
public String getOwner() {
LOGGER.trace(getDebugString());
lag();
return super.getOwner();
}
@Override
public String getGroup() {
LOGGER.trace(getDebugString());
lag();
return super.getGroup();
}
@Override
public AbstractFile getRoot() {
LOGGER.trace(getDebugString());
lag();
return super.getRoot();
}
@Override
public boolean isRoot() {
LOGGER.trace(getDebugString());
lag();
return super.isRoot();
}
@Override
public boolean equalsCanonical(Object f) {
LOGGER.trace(getDebugString());
lag();
return super.equals(f);
}
public String toString() {
LOGGER.trace(getDebugString());
lag();
return super.toString();
}
@Override
public AbstractFile getParent() {
LOGGER.trace(getDebugString());
lag();
return super.getParent();
}
}