package org.pmdreports.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.security.InvalidParameterException;

/**
 * FileUtilities.java
 * 
 * Static utilities for file io.
 * 
 * @author Ben Northrop Mar 17, 2007
 * 
 */
public final class FileUtil {

	/**
	 * Private constructor for utilities class.
	 */
	private FileUtil() {
		// do nothing since utilities class.
	}

	/**
	 * Utility method for copying a file from one place to another.
	 */
	public static void copyFile(java.io.File in, java.io.File out)
			throws FileCreationException {
		try {
			FileChannel inChannel = new FileInputStream(in).getChannel();
			FileChannel outChannel = new FileOutputStream(out).getChannel();
			inChannel.transferTo(0, inChannel.size(), outChannel);
			inChannel.close();
			outChannel.close();
		} catch (IOException ioe) {
			throw new FileCreationException("File cannot be created: "
					+ out.getPath(), ioe);
		}
	}

	/**
	 * Create a directory given the full path to it.
	 */
	public static void createDirectory(String fullPath)
			throws DirectoryCreationException {
		if (fullPath == null) {
			throw new InvalidParameterException("path of directory is null!");
		}

		boolean success = (new File(fullPath)).mkdir();
		if (!success) {
			throw new DirectoryCreationException(
					"Directory could not be created: " + fullPath);
		}
	}

	/**
	 * Deletes all files and subdirectories under dir. Returns true if all
	 * deletions were successful. If a deletion fails, the method stops
	 * attempting to delete and returns false.
	 */
	public static boolean deleteDir(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i])); // NOPMD
				if (!success) {
					return false;
				}
			}
		}

		// The directory is now empty so delete it
		return dir.delete();
	}

	/**
	 * Rename a file.
	 */
	public static boolean renameFile(String oldPath, String newPath) {
		File file = new File(oldPath);
		File file2 = new File(newPath);

		if (!file.renameTo(file2)) {
			throw new FileRenameException("Could not rename file from: "
					+ oldPath + " to " + newPath);
		}
		return true;
	}

	/**
	 * Indicates file could not be created.
	 */
	static class FileCreationException extends PMDReportsException {
		private static final long serialVersionUID = 1391609559996670173L;

		public FileCreationException(String message, IOException ioe) {
			super(message, ioe);
		}
	}

	/**
	 * Indicates that a file could not be found.
	 */
	static public class FileNotFoundException extends PMDReportsException {
		private static final long serialVersionUID = -415600521444400341L;

		public FileNotFoundException(String message) {
			super(message);
		}

	}

	/**
	 * Indicates a File could not be renamed.
	 */
	static public class FileRenameException extends PMDReportsException {
		private static final long serialVersionUID = -5790083383105958437L;

		public FileRenameException(String message) {
			super(message);
		}
	}

	/**
	 * Indicates a directory could not be created.
	 */
	static public class DirectoryCreationException extends PMDReportsException {
		private static final long serialVersionUID = -8039484748250527544L;

		/**
		 * Pass in the message.
		 */
		public DirectoryCreationException(String message) {
			super(message);
		}
	}

	/**
	 * Indicates a directory could not be deleted.
	 */
	static public class DirectoryDeletionException extends PMDReportsException {
		private static final long serialVersionUID = -6393201506749354207L;

		public DirectoryDeletionException(String message) {
			super(message);
		}

	}

}
