//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 IBM Corporation and others.
// 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://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.eclipse.epf.common.CommonPlugin;

/**
 * Utility class for managing directories and files.
 * 
 * @author Kelvin Low
 * @author Jinhua Xi
 * @since 1.0
 */
public class FileUtil {

	/**
	 * Platform-specific line separator.
	 */
	public static final String LINE_SEP = System.getProperty("line.separator"); //$NON-NLS-1$

	/**
	 * Platform-specific file separator.
	 */
	public static final String FILE_SEP = System.getProperty("file.separator"); //$NON-NLS-1$

	/**
	 * Platform-specific line separator length.
	 */
	public static final int LINE_SEP_LENGTH = LINE_SEP.length();

	/**
	 * UNC path prefix.
	 */
	public static final String UNC_PATH_PREFIX = "\\\\"; //$NON-NLS-1$

	/**
	 * UNC path prefix length.
	 */
	public static final int UNC_PATH_PREFIX_LENGTH = UNC_PATH_PREFIX.length();

	/**
	 * ISO-8859-1 encoding.
	 */
	public static final String ENCODING_ISO_8859_1 = "ISO-8859-1"; //$NON-NLS-1$

	/**
	 * UTF-8 encoding.
	 */
	public static final String ENCODING_UTF_8 = "UTF-8";//$NON-NLS-1$

	/**
	 * Private constructor to prevent this class from being instantiated. All
	 * methods in this class should be static.
	 */
	private FileUtil() {
	}

	/**
	 * Returns the absolute path for the given file or directory.
	 * 
	 * @param file
	 *            The given file or directory.
	 * @return The absolute path of the given file or directory.
	 */
	public static String getAbsolutePath(File file) {
		return file.getAbsolutePath().replace('\\', '/');
	}

	/**
	 * Returns the absolute path for the given file or directory.
	 * 
	 * @param file
	 *            The given file or directory name.
	 * @return The absolute path of the given file or directory.
	 */
	public static String getAbsolutePath(String file) {
		return getAbsolutePath(new File(file));
	}

	/**
	 * Returns the absolute path for the given URL.
	 * 
	 * @param url
	 *            The given URL.
	 * @return The absolute path of the given URL.
	 */
	public static String getAbsolutePath(URL url) {
		String pathName = url.getFile().substring(1);
		String result = NetUtil.decodeUrl(pathName, null);
		return result;
	}

	/**
	 * Returns the parent directory of the given path.
	 * 
	 * @param path
	 *            The path name.
	 * @return The name of the parent directory.
	 */
	public static String getParentDirectory(String path) {
		return (new File(path)).getParent();
	}

	/**
	 * Returns the file name and extension from the given path.
	 * 
	 * @param path
	 *            The path name.
	 * @return The file name and the file extension.
	 */
	public static String getFileName(String path) {
		return getFileName(path, true);
	}

	/**
	 * Returns the file name from the given path, with or without the file
	 * extension.
	 * 
	 * @param path
	 *            The path name.
	 * @param withExtension
	 *            If true, include the file extension in the result.
	 * @return The file name with or without the file extension.
	 */
	public static String getFileName(String path, boolean withExtension) {
		String normalizedPath = path.replace('\\', '/');

		int prefixLength = 0;
		if (normalizedPath.startsWith(NetUtil.FILE_URI_PREFIX)) {
			prefixLength = NetUtil.FILE_URI_PREFIX_LENGTH;
		} else if (normalizedPath.startsWith(NetUtil.HTTP_URI_PREFIX)) {
			prefixLength = NetUtil.HTTP_URI_PREFIX_LENGTH;
		}

		String fileName;
		int index = normalizedPath.lastIndexOf("/"); //$NON-NLS-1$
		if (index < prefixLength) {
			fileName = normalizedPath.substring(prefixLength);
		} else {
			fileName = path.substring(index + 1);
		}

		if (withExtension) {
			return fileName;
		}

		index = fileName.indexOf("."); //$NON-NLS-1$
		return (index > 0) ? fileName.substring(0, index) : fileName;
	}

	/**
	 * Returns the relative path for the target path from the base path.
	 * 
	 * @param path
	 *            The target path.
	 * @param basePath
	 *            The base path.
	 * @return The relative path.
	 */
	public static String getRelativePathToBase(File path, File basePath) {
		try {
			String dir = path.toURL().toExternalForm();
			String baseDir = basePath.toURL().toExternalForm();
			StringBuffer result = new StringBuffer();
			if (dir.indexOf(baseDir) == 0) {
				String delta = dir.substring(baseDir.length());
				for (int i = 0; i < delta.length(); i++) {
					if (delta.charAt(i) == '/') {
						result.append("../"); //$NON-NLS-1$
					}
				}
			}
			return result.toString();
		} catch (Exception e) {
			return ""; //$NON-NLS-1$
		}
	}

	public static String getRelativePath(File path, File basePath) {
		try {
			String dir = path.toURL().toExternalForm();
			String baseDir = appendSeparator(basePath.toURL().toExternalForm(),
					"/"); //$NON-NLS-1$
			StringBuffer result = new StringBuffer();
			while (dir.indexOf(baseDir) == -1) {
				basePath = basePath.getParentFile();
				baseDir = appendSeparator(basePath.toURL().toExternalForm(),
						"/"); //$NON-NLS-1$
				result.append("../"); //$NON-NLS-1$
			}
			if (dir.indexOf(baseDir) == 0) {
				String delta = dir.substring(baseDir.length());
				result.append(delta);
			}
			return result.toString();
		} catch (Exception e) {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * Appends the platform specific path separator to the end of the given
	 * path.
	 * 
	 * @param path
	 *            The path name.
	 * @return The path name appended with the platform specific path separator.
	 */
	public static String appendSeparator(String path) {
		return appendSeparator(path, File.separator);
	}

	/**
	 * Appends the given path separator to the end of the given path.
	 * 
	 * @param path
	 *            The path name.
	 * @param separator
	 *            The path separator.
	 * @return The path name appended with the given separator.
	 */
	public static String appendSeparator(String path, String separator) {
		return path.endsWith(separator) ? path : path + separator;
	}

	/**
	 * Removes the ending path separator from the given path.
	 * 
	 * @param path
	 *            The path name.
	 * @return The path name minus the platform specific path separator.
	 */
	public static String removeSeparator(String path) {
		return path.endsWith(File.separator) ? path.substring(0,
				path.length() - 1) : path;
	}

	/**
	 * Removes the ending path separator from the given path.
	 * 
	 * @param path
	 *            The path name.
	 * @return The path name minus the path separator "\\" or "/".
	 */
	public static String removeAllSeparator(String path) {
		return path.endsWith("/") || path.endsWith("\\") ? path.substring(0, path.length() - 1) : path; //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Removes the ending path separator from the given path.
	 * 
	 * @param path
	 *            The path name.
	 * @param separator
	 *            The path separator.
	 * @return The path name minus the separator.
	 */
	public static String removeSeparator(String path, String separator) {
		return path.endsWith(separator) ? path.substring(0, path.length() - 1)
				: path;
	}

	/**
	 * Replaces the file name with another in the given path.
	 * 
	 * @param path
	 *            The path name.
	 * @param oldFileName
	 *            The old file name.
	 * @param newFileName
	 *            The new file name.
	 * @return The new path name with the new file name.
	 */
	public static String replaceFileName(String path, String oldFileName,
			String newFileName) {
		int index = path.lastIndexOf(oldFileName);
		return path.substring(0, index) + newFileName;
	}

	/**
	 * Replaces the file extension with another in the given path.
	 * 
	 * @param path
	 *            The path name.
	 * @param oldFileExt
	 *            The old file extension.
	 * @param newFileExt
	 *            The new file extension.
	 * @return The new path with the new file extension.
	 */
	public static String replaceExtension(String path, String oldExt,
			String newExt) {
		int index = path.lastIndexOf(oldExt);
		return path.substring(0, index) + newExt;
	}

	/**
	 * Returns the locale-specific path of a base path.
	 * 
	 * @param path
	 *            The base path name.
	 * @param localeStr
	 *            The locale string.
	 * @return The locale-specific path.
	 */
	public static String getLocalePath(String path, String localeStr) {
		if (StrUtil.isBlank(localeStr)) {
			return path;
		}
		String fileName = getFileName(path);
		return replaceFileName(path, fileName, localeStr + "/" + fileName); //$NON-NLS-1$
	}

	/**
	 * Returns the locale-specific path of a base path.
	 * 
	 * @param path
	 *            The base path name.
	 * @param locale
	 *            The locale object.
	 * @return The locale-specific path.
	 */
	public static String getLocalePath(String path, Locale locale) {
		return locale == null ? path : getLocalePath(path, locale.toString());
	}

	/**
	 * Writes the given text to a text file.
	 * 
	 * @param fileName
	 *            The target file name.
	 * @param text
	 *            The text to write.
	 * @return true if the given text is written successfully to file.
	 */
	public static boolean writeFile(String filename, String text) {
		FileWriter writer = null;
		try {
			writer = new FileWriter(filename);
			writer.write(text);
			writer.flush();
		} catch (IOException e) {
		} finally {
			if (writer != null) {
				try {
					writer.close();
					return true;
				} catch (Exception e) {
				}
			}
		}
		return false;
	}

	/**
	 * Write the given text to a file with UTF-8 encoding.
	 * 
	 * @param fileName
	 *            The target file name.
	 * @param text
	 *            The text to write.
	 * @param append
	 *            ture to append to the end of the file, false to override the
	 *            file
	 * @return true if the given text is written successfully to file.
	 */
	public static boolean writeUTF8File(String filename, String text) {
		return writeUTF8File(filename, text, false);
	}

	/**
	 * Write the given text to a file with UTF-8 encoding.
	 * 
	 * @param fileName
	 *            The target file name.
	 * @param text
	 *            The text to write.
	 * @param append
	 *            ture to append to the end of the file, false to override the
	 *            file
	 * @return true if the given text is written successfully to file.
	 */
	public static boolean writeUTF8File(String filename, String text,
			boolean append) {
		OutputStreamWriter writer = null;
		FileOutputStream fileOut = null;
		try {
			fileOut = new FileOutputStream(filename, append);
			writer = new OutputStreamWriter(fileOut, ENCODING_UTF_8);
			writer.write(text);
			writer.flush();
			fileOut.flush();
		} catch (IOException e) {
			CommonPlugin.getDefault().getLogger().logError(e);
		} finally {
			if (writer != null) {
				try {
					writer.close();
					return true;
				} catch (Exception e) {
				}
			}
			if (fileOut != null) {
				try {
					fileOut.close();
					return true;
				} catch (Exception e) {
				}
			}
		}
		return false;
	}

	/**
	 * Write the content of the given URI to the given output stream.
	 * 
	 * @param uri
	 *            The source URI.
	 * @param output
	 *            The output stream.
	 */
	public static void writeFile(String uri, OutputStream output)
			throws IOException {
		if (uri == null) {
			return;
		}

		InputStream input = null;
		try {
			input = NetUtil.getInputStream(uri);
			int bytesRead;
			byte[] buf = new byte[4096];
			while ((bytesRead = input.read(buf, 0, 4096)) > 0) {
				output.write(buf, 0, bytesRead);
			}
			output.flush();
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (Exception e) {
				}
			}
		}
	}

	/**
	 * Write the content of the given URI to the given PrintWriter.
	 * 
	 * @param uri
	 *            The source URI.
	 * @param writer
	 *            The PrintWriter obejct.
	 */
	public static void writeFile(String uri, PrintWriter pw) throws IOException {
		if (uri == null) {
			return;
		}

		InputStreamReader input = null;
		try {
			input = new InputStreamReader(NetUtil.getInputStream(uri));
			int charsRead;
			char[] buf = new char[4096];
			while ((charsRead = input.read(buf, 0, 4096)) > 0) {
				pw.write(buf, 0, charsRead);
			}
			pw.flush();
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (Exception e) {
				}
			}
		}
	}

	/**
	 * Recursively delete all sub-directories and files in the given directory.
	 * Does not delete the given directory.
	 * 
	 * @param dir
	 *            The directory containing the sub-directories and files.
	 * @return boolean true if delete successful
	 */
	public static boolean deleteAllFiles(String dir) {
		boolean ret = true;
		File targetDir = new File(dir);
		File[] files = targetDir.listFiles();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				if (files[i].isDirectory()) {
					ret = ret && deleteAllFiles(files[i].getAbsolutePath());
				}
				ret = ret && files[i].delete();
			}
		}

		return ret;
	}

	/**
	 * Copies the content of the source file to the target file.
	 * Will overwrite an existing file if it has write permission
	 * 
	 * @param srcFile
	 *            The source file or path.
	 * @param tgtFile
	 *            The target file or path.
	 */
	public static boolean copyFile(File srcFile, File tgtFile) {
		try {
			return copyfile(srcFile, tgtFile);
		} catch (IOException ex) {
			CommonPlugin.getDefault().getLogger().logError(ex);
			return false;
		}
	}
	
	/**
	 * Copies the content of the source file to the target file.
	 * 
	 * @param srcFileName
	 *            The source file name.
	 * @param tgtFileName
	 *            The target file name.
	 */
	public static boolean copyFile(String srcFileName, String tgtFileName) {
		return copyFile(new File(srcFileName), new File(tgtFileName));
	}

	/**
	 * Copies one File to another.
	 * 
	 * if both source and dest are directories, delegates to copydirectory()
	 * 
	 * source must exist and be readable
	 * 
	 * cannot copy a directory to a file
	 * 
	 * will not copy if timestamps and filesize match, will overwrite otherwise
	 * 
	 * @param source
	 * @param dest
	 * @throws IOException
	 */
	private static boolean copyfile(File source, File dest) throws IOException {
		if (source.equals(dest))
			// do not copy equal files
			return false;

		if (!source.exists() || !source.canRead()) {
			// source does not exist or can't read
			return false;
		}
		
		if (dest.exists() && !dest.canWrite()) {
			// dest exists and cannot be written
			return false;
		}
		
		if (source.isDirectory()) {
			if (dest.isFile()) {
				// can't copy a directory to a file
				return false;
			} else {
				// delegate to copydirectory
				return copydirectory(source, dest);
			}
		} else {
			// source is a file
			if (dest.isDirectory()) {
				String sourceFileName = source.getName();
				return copyfile(source, new File(dest, sourceFileName));
			}
			// both source and dest are files
			boolean needCopy = true;
			if (dest.exists()) {
				needCopy = (dest.lastModified() != source.lastModified())
						|| (dest.length() != source.length());
			}
		
			if (needCopy) {
				FileInputStream input = null;
				FileOutputStream output = null;

				try {
					input = new FileInputStream(source);
					FileChannel in = input.getChannel();
					if (!dest.exists()) {
						dest.getParentFile().mkdirs();
					}
					output = new FileOutputStream(dest);
					FileChannel out = output.getChannel();
					out.transferFrom(in, 0, source.length());
					dest.setLastModified(source.lastModified());
					return true;
				} finally {
					if (input != null) {
						try {
							input.close();
						} catch (IOException e) {
						}
					}
					if (output != null) {
						try {
							output.close();
						} catch (IOException e) {
						}
					}
				}
			} else {
				// did not copy
				// return true because dest file is same as source
				return true;
			}
		}		
	}
	
	/**
	 * Copies the content of a directory to another directory.
	 * 
	 * @param srcDirName
	 *            The source directory name.
	 * @param tgtDirName
	 *            The target directory name.
	 */
	public static boolean copyDir(File srcDir, File tgtDir) {
		try {
			return copydirectory(srcDir, tgtDir);
		} catch (IOException ex) {
			CommonPlugin.getDefault().getLogger().logError(ex);
			return false;
		}
	}

	/**
	 * Copies the content of a directory to another directory.
	 * 
	 * @param srcDirName
	 *            The source directory name.
	 * @param tgtDirName
	 *            The target directory name.
	 */
	public static boolean copyDir(String srcDirName, String tgtDirName) {
		return copyDir(new File(srcDirName), new File(tgtDirName));
	}

	/**
	 * Copies one directory to another - operates ONLY on directories.
	 * 
	 * both source and dest must exist
	 * 
	 */
	private static boolean copydirectory(File sourceDir, File destDir)
			throws IOException {
		if (!sourceDir.exists() || !destDir.exists()) {
			return false;
		}

		if (!sourceDir.isDirectory() || !destDir.isDirectory()) {
			return false;
		}

		File[] files = sourceDir.listFiles();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				// calc destination name
				String destName = destDir
						+ File.separator
						+ files[i].getAbsolutePath().substring(
								sourceDir.getAbsolutePath().length() + 1);
				if (files[i].isFile()) {
					// copy the file
					copyfile(files[i], new File(destName));
				} else if (files[i].isDirectory()) {
					// copy directory recursively
					File destFile = new File(destName);
					destFile.mkdirs();
					copydirectory(files[i], destFile);
				}
			}
		}
		return true;
	}

	// for some reason, this guy locks the file, if you try to update the file,
	// got the following exception
	// java.io.FileNotFoundException:
	// (The requested operation cannot be performed on a file with a user-mapped
	// section open)
	// need to handle later
	public static CharBuffer readFile(File file) throws IOException {
		FileInputStream input = null;
		CharBuffer charBuffer = null;
		try {
			input = new FileInputStream(file);
			FileChannel inChannel = input.getChannel();
			int length = (int) inChannel.size();
			MappedByteBuffer byteBuffer = inChannel.map(
					FileChannel.MapMode.READ_ONLY, 0, length);
			Charset charset = Charset.forName(ENCODING_ISO_8859_1);
			CharsetDecoder decoder = charset.newDecoder();
			charBuffer = decoder.decode(byteBuffer);
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
				}
			}
		}
		return charBuffer;
	}

	public static StringBuffer readFile(File file, String encoding)
			throws IOException {

		StringBuffer result = new StringBuffer();
		FileInputStream fis = null;
		InputStreamReader reader = null;
		try {
			char[] buffer = new char[1024];
			fis = new FileInputStream(file);
			reader = new InputStreamReader(fis, encoding);
			int size;
			while ((size = reader.read(buffer, 0, 1024)) > 0) {
				result.append(buffer, 0, size);
			}
		} finally {
			if (fis != null) {
				fis.close();
			}

			if (reader != null) {
				reader.close();
			}
		}

		return result;
	}

	/**
	 * Uses Java 1.4's FileLock class to test for a file lock
	 * 
	 * @param file
	 * @return
	 */
	public static boolean isFileLocked(File file) {
		boolean isLocked = false;
		FileOutputStream input = null;
		FileLock lock = null;

		if (!file.exists()) {
			return false;
		}
		try {
			input = new FileOutputStream(file);
			FileChannel fileChannel = input.getChannel();

			lock = fileChannel.tryLock();

			if (lock == null)
				isLocked = true;
			else
				lock.release();
		} catch (Exception e) {
			if (e instanceof SecurityException)
				// Can't write to file.
				isLocked = true;
			else if (e instanceof FileNotFoundException)
				isLocked = false;
			else if (e instanceof IOException)
				isLocked = true;
			// OverlappingFileLockException means that this JVM has it locked
			// therefore it is not locked to us
			else if (e instanceof OverlappingFileLockException)
				isLocked = false;
			// Could not get a lock for some other reason.
			else
				isLocked = true;
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (Exception ex) {
				}
			}
		}
		return isLocked;
	}

	/**
	 * Locks a file for the current JVM. Will create the file if it does not
	 * exist
	 * 
	 * @param file
	 * @return a FileLock object, or null if file could not be locked
	 */
	public static FileLock lockFile(File file) {
		FileOutputStream input = null;
		FileLock lock = null;
		try {
			input = new FileOutputStream(file);
			FileChannel fileChannel = input.getChannel();
			lock = fileChannel.tryLock();

			if (lock.isValid())
				return lock;
		} catch (Exception e) {
			// Could not get a lock for some reason.
			return null;
		} finally {
			try {
				if (input != null && (lock == null || !lock.isValid())) {
					input.close();
				}
			} catch (Exception ex) {
			}
		}
		return null;
	}

	/**
	 * Gets all files in a specified path.
	 * 
	 * @param path
	 *            absolute path of a folder
	 * @param fileList
	 *            a list to collect the files
	 * @param recursive
	 *            if <code>true</code>, find the files in sub folders as well
	 */
	public static void getAllFiles(File path, List<File> fileList,
			boolean recursive) {
		if (path.isDirectory()) {
			File[] files = path.listFiles();
			if (files != null) {
				for (int i = 0; i < files.length; i++) {
					if (files[i].isFile()) {
						fileList.add(files[i]);
					} else if (recursive) {
						getAllFiles(files[i], fileList, recursive);
					}
				}
			}
		}
	}

	/**
	 * Given a directory and extension, returns all files (recursively) whose
	 * extension starts with a given extension.
	 * 
	 * @param file
	 *            a directory
	 * @param extension
	 *            a file extension
	 * @return a colleciton of <code>File</code> with the given extension
	 */
	public static List<File> fileList(File f, String extension) {
		extension = extension.toUpperCase();
		List<File> returnList = new ArrayList<File>();
		try {
			if (f.isDirectory()) {
				String[] flist = f.list();
				for (int i = 0; i < flist.length; ++i) {
					File fc = new File(f.getPath(), flist[i]);
					returnList.addAll(fileList(fc, extension));
				}
			} else {
				if (extension != null) {
					String name = f.getName().toUpperCase();
					if (name.lastIndexOf(".") != -1) //$NON-NLS-1$
						if (name
								.substring(name.lastIndexOf(".") + 1).startsWith(extension)) { //$NON-NLS-1$
							returnList.add(f);
						}
				} else
					returnList.add(f);
			}
		} catch (Exception e) {
			CommonPlugin.getDefault().getLogger().logError(e);
		}
		return returnList;
	}

	/**
	 * Given a directory and extension, returns all files (recursively) whose
	 * extension does not starts with a given extension.
	 * 
	 * @param file
	 *            a directory
	 * @param extension
	 *            a file extension
	 * @return a colleciton of <code>File</code> without the given extension
	 */
	public static List<File> fileListExcludeExt(File f, String extension) {
		List<File> returnList = new ArrayList<File>();
		try {
			if (f.isDirectory()) {
				String[] flist = f.list();
				for (int i = 0; i < flist.length; ++i) {
					File fc = new File(f.getPath(), flist[i]);
					returnList.addAll(fileListExcludeExt(fc, extension));
				}
			} else {
				if (extension != null) {
					String name = f.getName();
					if (name.lastIndexOf(".") != -1) //$NON-NLS-1$
						if (!(name.substring(name.lastIndexOf(".") + 1).startsWith(extension))) { //$NON-NLS-1$
							returnList.add(f);
						}
				} else
					returnList.add(f);
			}
		} catch (Exception e) {
			CommonPlugin.getDefault().getLogger().logError(e);
		}
		return returnList;
	}

	/**
	 * Gets all file paths in the specified path.
	 * 
	 * @param path,
	 *            absolute path of a folder
	 * @param recursive
	 *            if <code>true</code>, find the files in sub folders as well
	 */
	public static ArrayList<String> getAllFileAbsolutePaths(File path,
			boolean recursive) {
		ArrayList<File> files = new ArrayList<File>();
		getAllFiles(path, files, recursive);
		ArrayList<String> paths = new ArrayList<String>();
		for (int i = 0; i < files.size(); i++) {
			String absPath = ((File) files.get(i)).getAbsolutePath();
			paths.add(absPath);
		}
		return paths;
	}

	/**
	 * Moves a file from a directory to another.
	 * <p>
	 * Attempts to rename the file first. If that fails, will copy the
	 * sourceFile to destFile and delete the sourceFile.
	 * 
	 * @param sourceFile
	 *            the source file
	 * @param destFile
	 *            the destination file
	 * @return
	 */
	public static boolean moveFile(File sourceFile, File destFile) {
		try {
			// Try to rename the source file to the destination file.
			if (sourceFile.renameTo(destFile)) {
				return true;
			} else {
				// Try to copy the source file to the destination file and
				// delete
				// the source file.
				copyfile(sourceFile, destFile);
				sourceFile.delete();
				return true;
			}
		} catch (Exception e) {
			CommonPlugin.getDefault().getLogger().logError(e);
			return false;
		}
	}

}