/******************************************************************************* * Copyright (c) 2004, 2014 QNX Software Systems 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: * QNX Software Systems - initial API and implementation * Markus Schorn (Wind River Systems) * Ed Swartz (Nokia) * Sergey Prigogin (Google) * James Blackburn (Broadcom Corp.) *******************************************************************************/ package org.eclipse.cdt.utils; import java.io.File; import java.io.IOException; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfoProvider; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; /** * @noextend This class is not intended to be subclassed by clients. * @noinstantiate This class is not intended to be instantiated by clients. */ public class PathUtil { /** Detect whether we're running on Windows (as IPath does) */ private static final boolean WINDOWS = java.io.File.separatorChar == '\\'; public static boolean isWindowsFileSystem() { return WINDOWS; } public static IWorkspaceRoot getWorkspaceRoot() { IWorkspace workspace = ResourcesPlugin.getWorkspace(); if (workspace != null) { return workspace.getRoot(); } return null; } /** * Return the canonical path (or the passed in path, if one couldn't be found). * @param fullPath * @return canonicalized IPath or passed in fullPath. */ public static IPath getCanonicalPath(IPath fullPath) { if (!fullPath.isAbsolute()) return fullPath; File file = fullPath.toFile(); try { String canonPath = file.getCanonicalPath(); IPath canonicalPath = new Path(canonPath); if (fullPath.getDevice() == null) canonicalPath = canonicalPath.setDevice(null); return canonicalPath; } catch (IOException ex) { } return fullPath; } /** * On Windows returns the {@link java.io.File#getCanonicalPath()} for a given absolute path. * On other platforms, and for relative paths returns the the original path. * * @param fullPath * @return canonicalized IPath or passed in fullPath. * @since 5.3 */ public static IPath getCanonicalPathWindows(IPath fullPath) { if (!WINDOWS) return fullPath; return getCanonicalPath(fullPath); } public static IPath getWorkspaceRelativePath(IPath fullPath) { IWorkspaceRoot workspaceRoot = getWorkspaceRoot(); if (workspaceRoot != null) { IPath workspaceLocation = workspaceRoot.getLocation(); if (workspaceLocation != null && isPrefix(workspaceLocation, fullPath)) { int segments = matchingFirstSegments(fullPath, workspaceLocation); IPath relPath = fullPath.setDevice(null).removeFirstSegments(segments); return new Path("").addTrailingSeparator().append(relPath); //$NON-NLS-1$ } } return fullPath; } public static IPath getProjectRelativePath(IPath fullPath, IProject project) { IPath projectPath = project.getFullPath(); if (isPrefix(projectPath, fullPath)) { return fullPath.removeFirstSegments(projectPath.segmentCount()); } projectPath = project.getLocation(); if (isPrefix(projectPath, fullPath)) { return fullPath.removeFirstSegments(projectPath.segmentCount()); } return getWorkspaceRelativePath(fullPath); } public static IPath getWorkspaceRelativePath(String fullPath) { return getWorkspaceRelativePath(new Path(fullPath)); } public static IPath getRawLocation(IPath wsRelativePath) { IWorkspaceRoot workspaceRoot = getWorkspaceRoot(); if (workspaceRoot != null && wsRelativePath != null) { IPath workspaceLocation = workspaceRoot.getLocation(); if (workspaceLocation != null && !isPrefix(workspaceLocation, wsRelativePath)) { return workspaceLocation.append(wsRelativePath); } } return wsRelativePath; } public static IPath makeRelativePath(IPath path, IPath relativeTo) { int segments = matchingFirstSegments(relativeTo, path); if (segments > 0) { IPath prefix = relativeTo.removeFirstSegments(segments); IPath suffix = path.removeFirstSegments(segments); IPath relativePath = new Path(""); //$NON-NLS-1$ for (int i = 0; i < prefix.segmentCount(); ++i) { relativePath = relativePath.append(".." + IPath.SEPARATOR); //$NON-NLS-1$ } return relativePath.append(suffix); } return null; } public static IPath makeRelativePathToProjectIncludes(IPath fullPath, IProject project) { IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); if (provider != null) { IScannerInfo info = provider.getScannerInformation(project); if (info != null) { return makeRelativePathToIncludes(fullPath, info.getIncludePaths()); } } return null; } public static IPath makeRelativePathToIncludes(IPath fullPath, String[] includePaths) { IPath relativePath = null; int mostSegments = 0; for (int i = 0; i < includePaths.length; ++i) { IPath includePath = new Path(includePaths[i]); if (isPrefix(includePath, fullPath)) { int segments = includePath.segmentCount(); if (segments > mostSegments) { relativePath = fullPath.removeFirstSegments(segments).setDevice(null); mostSegments = segments; } } } return relativePath; } public static IProject getEnclosingProject(IPath fullPath) { IWorkspaceRoot root = getWorkspaceRoot(); if (root != null) { IPath path = getWorkspaceRelativePath(fullPath); while (path.segmentCount() > 0) { IResource res = root.findMember(path); if (res != null) return res.getProject(); path = path.removeLastSegments(1); } } return null; } public static IPath getValidEnclosingFolder(IPath fullPath) { IWorkspaceRoot root = getWorkspaceRoot(); if (root != null) { IPath path = getWorkspaceRelativePath(fullPath); while (path.segmentCount() > 0) { IResource res = root.findMember(path); if (res != null && res.exists() && (res.getType() == IResource.PROJECT || res.getType() == IResource.FOLDER)) return path; path = path.removeLastSegments(1); } } return null; } /** * Checks whether path1 is the same as path2. * <p> * Similar to IPath.equals(Object obj), but takes case sensitivity of the file system * into account. * * @return {@code true} if path1 is the same as path2, and {@code false} otherwise * * @since 5.1 * @deprecated Use {@link #equalPath(IPath, IPath)} instead. */ @Deprecated public boolean equal(IPath path1, IPath path2) { // Check leading separators if (path1.isAbsolute() != path2.isAbsolute() || path1.isUNC() != path2.isUNC()) { return false; } int i = path1.segmentCount(); // Check segment count if (i != path2.segmentCount()) return false; // Check segments in reverse order - later segments more likely to differ while (--i >= 0) { if (!path1.segment(i).equals(path2.segment(i))) return false; } // Check device last (least likely to differ) if (path1.getDevice() == null) { return path2.getDevice() == null; } else { return path1.getDevice().equalsIgnoreCase(path2.getDevice()); } } /** * Checks whether path1 is the same as path2. * <p> * Similar to IPath.equals(Object obj), but takes case sensitivity of the file system * into account. * * @return {@code true} if path1 is the same as path2, and {@code false} otherwise * @since 5.3 */ public static boolean equalPath(IPath path1, IPath path2) { // Check leading separators if (path1.isAbsolute() != path2.isAbsolute() || path1.isUNC() != path2.isUNC()) { return false; } int i = path1.segmentCount(); // Check segment count if (i != path2.segmentCount()) return false; // Check segments in reverse order - later segments more likely to differ boolean caseSensitive = !isWindowsFileSystem(); while (--i >= 0) { if (!(caseSensitive ? path1.segment(i).equals(path2.segment(i)) : path1.segment(i).equalsIgnoreCase(path2.segment(i)))) { return false; } } // Check device last (least likely to differ) if (path1.getDevice() == null) { return path2.getDevice() == null; } else { return path1.getDevice().equalsIgnoreCase(path2.getDevice()); } } /** * Checks whether path1 is a prefix of path2. To be a prefix, path1's segments * must appear in path1 in the same order, and their device ids must match. * <p> * An empty path is a prefix of all paths with the same device; a root path is a prefix of * all absolute paths with the same device. * <p> * Similar to IPath.isPrefixOf(IPath anotherPath), but takes case sensitivity of the file system * into account. * * @return {@code true} if path1 is a prefix of path2, and {@code false} otherwise * @since 5.1 */ public static boolean isPrefix(IPath path1, IPath path2) { if (path1.getDevice() == null) { if (path2.getDevice() != null) { return false; } } else { if (!path1.getDevice().equalsIgnoreCase(path2.getDevice())) { return false; } } if (path1.isEmpty() || (path1.isRoot() && path2.isAbsolute())) { return true; } int len1 = path1.segmentCount(); if (len1 > path2.segmentCount()) { return false; } boolean caseSensitive = !isWindowsFileSystem(); for (int i = 0; i < len1; i++) { if (!(caseSensitive ? path1.segment(i).equals(path2.segment(i)) : path1.segment(i).equalsIgnoreCase(path2.segment(i)))) { return false; } } return true; } /** * Returns the number of segments which match in path1 and path2 * (device ids are ignored), comparing in increasing segment number order. * <p> * Similar to IPath.matchingFirstSegments(IPath anotherPath), but takes case sensitivity * of the file system into account. * * @return the number of matching segments * @since 5.1 */ public static int matchingFirstSegments(IPath path1, IPath path2) { Assert.isNotNull(path1); Assert.isNotNull(path2); int len1 = path1.segmentCount(); int len2 = path2.segmentCount(); int max = Math.min(len1, len2); int count = 0; boolean caseSensitive = !isWindowsFileSystem(); for (int i = 0; i < max; i++) { if (!(caseSensitive ? path1.segment(i).equals(path2.segment(i)) : path1.segment(i).equalsIgnoreCase(path2.segment(i)))) { return count; } count++; } return count; } /** * Finds location of the program inspecting each path in the path list. * * @param prog - program to find. For Windows, extensions "com" and "exe" * can be omitted. * @param pathsStr - the list of paths to inspect separated by path separator * defined in the platform (i.e. ":" in Unix and ";" in Windows). * In case pathStr is {@code null} environment variable ${PATH} is inspected. * @return - absolute location of the file on the file system * or {@code null} if not found. * @since 5.3 */ public static IPath findProgramLocation(String prog, String pathsStr) { if (prog == null || prog.trim().isEmpty()) return null; if (pathsStr == null) pathsStr = System.getenv("PATH"); //$NON-NLS-1$ if (pathsStr.trim().isEmpty()) return null; String locationStr = null; String[] dirs = pathsStr.split(File.pathSeparator); // Try to find "prog.exe" or "prog.com" on Windows if (Platform.getOS().equals(Platform.OS_WIN32)) { for (String dir : dirs) { IPath dirLocation = new Path(dir); File file = null; file = dirLocation.append(prog + ".exe").toFile(); //$NON-NLS-1$ if (file.isFile() && file.canRead()) { locationStr = file.getAbsolutePath(); break; } file = dirLocation.append(prog + ".com").toFile(); //$NON-NLS-1$ if (file.isFile() && file.canRead()) { locationStr = file.getAbsolutePath(); break; } } } // Check "prog" on Unix and Windows too (if was not found) - could be cygwin or something // do it in separate loop due to performance and correctness of Windows regular case if (locationStr == null) { for (String dir : dirs) { IPath dirLocation = new Path(dir); File file = null; file = dirLocation.append(prog).toFile(); if (file.isFile() && file.canRead()) { locationStr = file.getAbsolutePath(); break; } } } if (locationStr != null) return new Path(locationStr); return null; } /** * Finds location of the program inspecting each path in the path list * defined by environment variable ${PATH}. * * @param prog - program to find. For Windows, extensions "com" and "exe" * can be omitted. * @return - absolute location of the file on the file system * or {@code null} if not found. * @since 5.3 */ public static IPath findProgramLocation(String prog) { return findProgramLocation(prog, null); } }