//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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) {
			e.printStackTrace();
		} 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.
	 * 
	 * @param srcFile
	 *            The source file or path.
	 * @param tgtFile
	 *            The target file or path.
	 */
	public static void copyFile(File srcFile, File tgtFile) throws IOException {
		if (srcFile.equals(tgtFile))
			return;

		if (!srcFile.exists() || !srcFile.canRead()) {
			return;
		}

		if (tgtFile.exists() && !tgtFile.canWrite()) {
			return;
		}

		if (!srcFile.isFile()) {
			File[] files = srcFile.listFiles();
			if (files != null) {
				for (int i = 0; i < files.length; i++) {
					copyFile(files[i], tgtFile);
				}
			}
			return;
		}	

		FileInputStream src = null;
		FileOutputStream tgt = null;
		try {
			src = new FileInputStream(srcFile);
			if (tgtFile.isFile()) {
				tgt = new FileOutputStream(tgtFile);
			} else {
				String srcPath = srcFile.toURL().toString();
				int index = srcPath.lastIndexOf("/"); //$NON-NLS-1$
				String srcFileName = srcPath.substring(index + 1);
				String srcCanonicalPath = srcFile.getCanonicalPath();
				String tgtCanonicalPath = new File(tgtFile, srcFileName).getCanonicalPath();
				if (srcCanonicalPath.equals(tgtCanonicalPath)) {
					return;
				}
				tgt = new FileOutputStream(new File(tgtFile, srcFileName));
			}
			byte[] buffer = new byte[4096];
			int bytes_read;
			while ((bytes_read = src.read(buffer)) != -1) {
				tgt.write(buffer, 0, bytes_read);
			}
		} finally {
			if (src != null) {
				try {
					src.close();
				} catch (Exception e) {
				}
			}
			if (tgt != null) {
				try {
					tgt.close();
				} catch (Exception e) {
				}
			}
			tgtFile.setLastModified(srcFile.lastModified());
		}
	}

	/**
	 * 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 void copyFile(String srcFileName, String tgtFileName)
			throws IOException {
		copyFile(new File(srcFileName), new File(tgtFileName));
	}

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

	/**
	 * Copies one file to another - operates ONLY on files, not on directories.
	 * 
	 * @param source
	 * @param dest
	 * @throws IOException
	 */
	public static void copyfile(File source, File dest) throws IOException {
		if (source.equals(dest))
			return;

		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());
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
				}
			}
			if (output != null) {
				try {
					output.close();
				} catch (IOException e) {
				}
			}
		}
	}

	public static void copydirectory(File sourceDir, File destDir)
			throws IOException {
		if (!sourceDir.exists() || !destDir.exists()) {
			return;
		}

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

		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);
				}
			}
		}

	}

	// 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;
	}

	/**
	 * get all files in the specified path
	 * @param path, absolute path of a folder
	 * @param fileList List the list to collect the Files
	 * @param recursive boolean, if true find the files in sub folders as well
	 */
	public static void getAllFiles(File path, List fileList, boolean recursive)
	{
		// get all files in the specified folder
		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 startsWith the given extension
	 * 
	 * @param f
	 * @param extension
	 * @return
	 */
	public static List fileList(File f, String extension) {
		extension = extension.toUpperCase();
		List returnList = new ArrayList();
		try {
			if (f.isDirectory()) { // if dir then recurse
				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 { // ordinary file
				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 ex) {
			ex.printStackTrace();
		}
		return returnList;
	}

	/**
	 * given a directory and extension, returns all files (recursively)whose
	 * extension does not startsWith the given extension
	 * 
	 * @param f
	 * @param extension
	 * @return
	 */
	public static List fileListExcludeExt(File f, String extension) {
		List returnList = new ArrayList();
		try {
			if (f.isDirectory()) { // if dir then recurse
				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 { // ordinary file
				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 ex) {
			ex.printStackTrace();
		}
		return returnList;
	}
	
	/**
	 * get all file paths in the specified path
	 * @param path, absolute path of a folder
	 * @param recursive boolean, if true find the files in sub folders as well
	 */
	public static ArrayList getAllFileAbsolutePaths(File path, boolean recursive) {	
		ArrayList files = new ArrayList();
		getAllFiles(path, files, recursive);
		ArrayList paths = new ArrayList();
		for (int i=0; i<files.size(); i++) {
			String absPath = ((File) files.get(i)).getAbsolutePath();
			paths.add(absPath);
		}
		return paths;
	}
	
	/**
	 * Moves a file
	 * 
	 * Attempts to rename the file first.  If that fails,
	 * will copy the sourceFile to destFile and delete the sourceFile.
	 * @param sourceFile
	 * @param destFile
	 * @return
	 */
	public static boolean moveFile(File sourceFile, File destFile) {
		try {
			// first try the renameTo method
			if (sourceFile.renameTo(destFile)) {
				return true;
			}
			else {
				// try to copy file, delete original
				copyfile(sourceFile, destFile);
				sourceFile.delete();
				return true;
			}
		} catch (Exception t) {
			CommonPlugin.getDefault().getLogger().logError(t);
			return false;
		}
	}
	
}