/******************************************************************************* * Copyright (c) 2004, 2008 IBM Corporation and others. * Copyright (C) 2007, Martin Oberhuber (martin.oberhuber@windriver.com) * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com> * * 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 *******************************************************************************/ package de.hub.srcrepo.internal; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.RepositoryCache.FileKey; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; import org.eclipse.osgi.util.NLS; import de.hub.srcrepo.SrcRepoActivator; public class ProjectUtil { public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$ private static final String ProjectUtil_refreshingProjects = "refreshing projects"; private static final String ProjectUtil_refreshing = "refreshing"; private static final String ProjectUtil_taskCheckingDirectory = "checking directory"; public static IProject[] getValidOpenProjects(final File parentFile) throws CoreException { final IProject[] projects = ResourcesPlugin.getWorkspace().getRoot() .getProjects(); List<IProject> result = new ArrayList<IProject>(); for (IProject p : projects) { IPath projectLocation = p.getLocation(); if (!p.isOpen() || projectLocation == null) continue; String projectFilePath = projectLocation.append( IProjectDescription.DESCRIPTION_FILE_NAME).toOSString(); File projectFile = new File(projectFilePath); if (projectFile.exists()) { final File file = p.getLocation().toFile(); if (file.getAbsolutePath().startsWith( parentFile.getAbsolutePath())) { result.add(p); } } } return result.toArray(new IProject[result.size()]); } public static void refreshValidProjects(IProject[] projects, IProgressMonitor monitor) throws CoreException { refreshValidProjects(projects, true, monitor); } public static int refreshValidProjects(IProject[] projects, boolean delete, IProgressMonitor monitor) throws CoreException { int count = 0; try { monitor.beginTask(ProjectUtil_refreshingProjects, projects.length); for (IProject p : projects) { if (monitor.isCanceled()) break; IPath projectLocation = p.getLocation(); if (projectLocation == null) continue; String projectFilePath = projectLocation.append(IProjectDescription.DESCRIPTION_FILE_NAME).toOSString(); File projectFile = new File(projectFilePath); if (projectFile.exists()) { p.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 1)); count++; } else if (delete) { p.delete(false, true, new SubProgressMonitor(monitor, 1)); } else { closeMissingProject(p, projectFile, monitor); } monitor.worked(1); } } finally { monitor.done(); } return count; } private static void closeMissingProject(IProject p, File projectFile, IProgressMonitor monitor) throws CoreException { // Create temporary .project file so it can be closed boolean closeFailed = false; File projectRoot = projectFile.getParentFile(); if (!projectRoot.isFile()) { boolean hasRoot = projectRoot.exists(); try { if (!hasRoot) FileUtils.mkdirs(projectRoot, true); if (projectFile.createNewFile()) p.close(new SubProgressMonitor(monitor, 1)); else closeFailed = true; } catch (IOException e) { closeFailed = true; } finally { // Clean up created .project file try { FileUtils.delete(projectFile, FileUtils.RETRY | FileUtils.SKIP_MISSING); } catch (IOException e) { closeFailed = true; } // Clean up created folder if (!hasRoot) try { FileUtils.delete(projectRoot, FileUtils.RETRY | FileUtils.SKIP_MISSING | FileUtils.RECURSIVE); } catch (IOException e) { closeFailed = true; } } } else closeFailed = true; // Delete projects that can't be closed if (closeFailed) p.delete(false, true, new SubProgressMonitor(monitor, 1)); } public static void refreshResources(IResource[] resources, IProgressMonitor monitor) throws CoreException { try { monitor.beginTask(ProjectUtil_refreshing, resources.length); for (IResource resource : resources) { if (monitor.isCanceled()) break; resource.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 1)); monitor.worked(1); } } finally { monitor.done(); } } public static boolean findProjectFiles(final Collection<File> files, final File directory, final Set<String> visistedDirs, final IProgressMonitor monitor) { if (directory == null) return false; if (directory.getName().equals(Constants.DOT_GIT) && FileKey.isGitRepository(directory, FS.DETECTED)) return false; IProgressMonitor pm = monitor; if (pm == null) pm = new NullProgressMonitor(); else if (pm.isCanceled()) return false; pm.subTask(NLS.bind(ProjectUtil_taskCheckingDirectory, directory.getPath())); final File[] contents = directory.listFiles(); if (contents == null || contents.length == 0) return false; Set<String> directoriesVisited; // Initialize recursion guard for recursive symbolic links if (visistedDirs == null) { directoriesVisited = new HashSet<String>(); try { directoriesVisited.add(directory.getCanonicalPath()); } catch (IOException exception) { SrcRepoActivator.INSTANCE.error(exception.getLocalizedMessage(), exception); } } else directoriesVisited = visistedDirs; // first look for project description files final String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME; for (int i = 0; i < contents.length; i++) { File file = contents[i]; if (file.isFile() && file.getName().equals(dotProject)) { files.add(file); // don't search sub-directories since we can't have nested // projects return true; } } // no project description found, so recurse into sub-directories for (int i = 0; i < contents.length; i++) { // Skip non-directories if (!contents[i].isDirectory()) continue; // Skip .metadata folders if (contents[i].getName().equals(METADATA_FOLDER)) continue; try { String canonicalPath = contents[i].getCanonicalPath(); if (!directoriesVisited.add(canonicalPath)) { // already been here --> do not recurse continue; } } catch (IOException exception) { SrcRepoActivator.INSTANCE.error(exception.getLocalizedMessage(), exception); } findProjectFiles(files, contents[i], directoriesVisited, pm); } return true; } }