blob: cf07e06f51a4ba276098b8322e813e86964359f0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2011 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);
}
}