/*******************************************************************************
* Copyright (c) 2001, 2010 Mathew A. Nelson and Robocode contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://robocode.sourceforge.net/license/epl-v10.html
*
* Contributors:
* Mathew A. Nelson
* - Initial API and implementation
* Flemming N. Larsen
* - Moved the former robocode.util.Constants and all file operations from
* robocode.util.Utils into this new class
* - Added/updated JavaDoc for all methods
* - Added the quoteFileName(), createDir(), getRobotsDir(), getConfigDir(),
* getRobocodeConfigFile(), getWindowConfigFile(), getCompilerConfigFile()
*******************************************************************************/
package net.sf.robocode.io;
import static net.sf.robocode.io.Logger.logError;
import java.io.*;
/**
* This is a class for file utilization.
*
* @author Mathew A. Nelson (original)
* @author Flemming N. Larsen (contributor)
*/
public class FileUtil {
// Current working directory
private static File cwd;
// Initializes the current working directory
static {
try {
final String wd = System.getProperty("WORKINGDIRECTORY", "");
FileUtil.setCwd(new File(wd));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Returns the current working directory.
*
* @return a File for the current working directory
*/
public static File getCwd() {
return cwd;
}
/**
* Changes the current working directory.
*
* @param cwd a File that is the new working directory
* @throws IOException if an I/O exception occurs
*/
public static void setCwd(File cwd) throws IOException {
FileUtil.cwd = cwd.getCanonicalFile();
}
/**
* Returns the file type of a file, i.e. it's extension.
*
* @param file the file
* @return the file type of the file, e.g. ".class", ".jar" or "" if the
* file name does not contain an extension.
*/
public static String getFileType(File file) {
return getFileType(file.getName());
}
/**
* Returns the file type of a file name, i.e. it's extension.
*
* @param fileName the file name
* @return the file type of the file name, e.g. ".class", ".jar" or "" if
* the file name does not contain an extension.
*/
public static String getFileType(String fileName) {
int lastdot = fileName.lastIndexOf('.');
return (lastdot < 0) ? "" : fileName.substring(lastdot);
}
/**
* Quotes a file name if it contains white spaces and has not already been
* quoted.
*
* @param filename the file to quote
* @return a quoted version of the specified filename
*/
public static String quoteFileName(String filename) {
if (filename.startsWith("\"") && filename.endsWith("\"")) {
return filename;
}
if (System.getProperty("os.name").toLowerCase().startsWith("windows") && filename.startsWith("file://")) {
filename = filename.substring(7);
}
if (filename.matches(".*\\s+?.*")) {
return '"' + filename + '"';
}
return filename;
}
/**
* Copies a file into another file.
*
* @param srcFile the input file to copy
* @param destFile the output file to copy to
* @throws IOException if an I/O exception occurs
*/
public static void copy(File srcFile, File destFile) throws IOException {
if (srcFile.equals(destFile)) {
throw new IOException("You cannot copy a file onto itself");
}
byte buf[] = new byte[4096];
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(srcFile);
out = new FileOutputStream(destFile);
while (in.available() > 0) {
out.write(buf, 0, in.read(buf, 0, buf.length));
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
/**
* Deletes a directory.
*
* @param dir the file for the directory to delete
* @return true if success
*/
public static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
try {
// Test for symlink and ignore.
// Robocode won't create one, but just in case a user does...
if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) {
deleteDir(file);
if (file.exists() && !file.delete()) {
Logger.logError("Cannot delete: " + file);
}
} else {
Logger.logWarning(file + " may be a symlink. Ignoring.");
}
} catch (IOException e) {
Logger.logWarning("Cannot determine canonical file for " + file + ". Ignoring.");
}
} else {
if (file.exists() && !file.delete()) {
Logger.logError("Cannot delete: " + file);
}
}
}
return dir.delete();
}
return false;
}
/**
* Creates a directory if it does not exist already
*
* @param dir the File that represents the new directory to create.
* @return the created directory
*/
public static File createDir(File dir) {
if (dir != null && !dir.exists()) {
if (!dir.mkdir()) {
Logger.logError("Cannot create dir: " + dir);
}
}
return dir;
}
/**
* Returns the class name of the specified filename.
*
* @param fileName the filename to extract the class name from
* @return the class name of the specified filename
*/
public static String getClassName(String fileName) {
int lastdot = fileName.lastIndexOf('.');
if (lastdot < 0) {
return fileName;
}
if (fileName.length() - 1 == lastdot) {
return fileName.substring(0, fileName.length() - 1);
}
return fileName.substring(0, lastdot);
}
/**
* Returns the directory containing the robots.
*
* @return a File that is the directory containing the robots
*/
public static File getRobotsDir() {
String robotPath = System.getProperty("ROBOTPATH");
File file;
if (robotPath != null) {
file = new File(robotPath);
} else {
file = new File(cwd, "/robots");
}
return createDir(file);
}
/**
* Returns the robot database file.
*
* @return a File that is the directory containing the robot cache.
*/
public static File getRobotDatabaseFile() {
return new File(getRobotsDir(), "/robot.database");
}
/**
* Returns the directory containing data files of robots.
*
* @return a File that is the directory containing the robot data.
*/
public static File getRobotsDataDir() {
return createDir(new File(getRobotsDir(), "/.data/"));
}
/**
* Returns the directory containing the battle files.
*
* @return a File that is the directory containing the battle files
*/
public static File getBattlesDir() {
return createDir(new File(cwd, "/battles"));
}
/**
* Returns the directory containing the configuration files.
* If the directory does not exist, it will be created automatically.
*
* @return a File that is the directory containing configuration files
*/
public static File getConfigDir() {
return createDir(new File(cwd, "/config"));
}
/**
* Returns the directory containing the screen shot files.
* If the directory does not exist, it will be created automatically.
*
* @return a File that is the directory containing screen shot files
*/
public static File getScreenshotsDir() {
return createDir(new File(cwd, "/screenshots"));
}
/**
* Returns the Robocode configuration file.
*
* @return a File that is the Robocode configuration file.
*/
public static File getRobocodeConfigFile() {
return new File(getConfigDir(), "robocode.properties");
}
/**
* Returns the window configuration file.
*
* @return a File that the window configuration file.
*/
public static File getWindowConfigFile() {
return new File(getConfigDir(), "window.properties");
}
/**
* Returns the compiler configuration file.
*
* @return a File that the compiler configuration file.
*/
public static File getCompilerConfigFile() {
return new File(getConfigDir(), "compiler.properties");
}
/**
* Cleans up a stream by flushing it and closing it if it is not null.
*
* @param stream the stream to clean up.
*/
public static void cleanupStream(Object stream) {
if (stream == null) {
return;
}
if (stream instanceof Flushable) {
try {
((Flushable) stream).flush();
} catch (IOException e) {
logError(e);
}
}
if (stream instanceof Closeable) {
try {
((Closeable) stream).close();
} catch (IOException e) {
logError(e);
}
}
}
}