1
/*******************************************************************************
2
* Copyright (c) 2004, 2011 QNX Software Systems and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* QNX Software Systems - initial API and implementation
10
* Markus Schorn (Wind River Systems)
12
* Sergey Prigogin (Google)
13
* James Blackburn (Broadcom Corp.)
14
*******************************************************************************/
15
package org.eclipse.cdt.utils;
18
import java.io.IOException;
20
import org.eclipse.cdt.core.CCorePlugin;
21
import org.eclipse.cdt.core.parser.IScannerInfo;
22
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
23
import org.eclipse.core.resources.IProject;
24
import org.eclipse.core.resources.IResource;
25
import org.eclipse.core.resources.IWorkspace;
26
import org.eclipse.core.resources.IWorkspaceRoot;
27
import org.eclipse.core.resources.ResourcesPlugin;
28
import org.eclipse.core.runtime.Assert;
29
import org.eclipse.core.runtime.IPath;
30
import org.eclipse.core.runtime.Path;
31
import org.eclipse.core.runtime.Platform;
34
* @noextend This class is not intended to be subclassed by clients.
35
* @noinstantiate This class is not intended to be instantiated by clients.
37
public class PathUtil {
38
/** Detect whether we're running on Windows (as IPath does) */
39
private static final boolean WINDOWS = java.io.File.separatorChar == '\\';
41
public static boolean isWindowsFileSystem() {
45
public static IWorkspaceRoot getWorkspaceRoot() {
46
IWorkspace workspace = ResourcesPlugin.getWorkspace();
47
if (workspace != null) {
48
return workspace.getRoot();
54
* Return the canonical path (or the passed in path, if one couldn't be found).
56
* @return canonicalized IPath or passed in fullPath.
58
public static IPath getCanonicalPath(IPath fullPath) {
59
if (!fullPath.isAbsolute())
62
File file = fullPath.toFile();
64
String canonPath = file.getCanonicalPath();
65
IPath canonicalPath = new Path(canonPath);
66
if (fullPath.getDevice() == null)
67
canonicalPath = canonicalPath.setDevice(null);
69
} catch (IOException ex) {
75
* On Windows discover the {@link java.io.File#getCanonicalPath()} for
76
* a given absolute path.
77
* On other platforms, and for relative paths returns the passed in fullPath
79
* @return canonicalized IPath or passed in fullPath.
82
public static IPath getCanonicalPathWindows(IPath fullPath) {
85
return getCanonicalPath(fullPath);
88
public static IPath getWorkspaceRelativePath(IPath fullPath) {
89
IWorkspaceRoot workspaceRoot = getWorkspaceRoot();
90
if (workspaceRoot != null) {
91
IPath workspaceLocation = workspaceRoot.getLocation();
92
if (workspaceLocation != null && isPrefix(workspaceLocation, fullPath)) {
93
int segments = matchingFirstSegments(fullPath, workspaceLocation);
94
IPath relPath = fullPath.setDevice(null).removeFirstSegments(segments);
95
return new Path("").addTrailingSeparator().append(relPath); //$NON-NLS-1$
101
public static IPath getProjectRelativePath(IPath fullPath, IProject project) {
102
IPath projectPath = project.getFullPath();
103
if (isPrefix(projectPath, fullPath)) {
104
return fullPath.removeFirstSegments(projectPath.segmentCount());
106
projectPath = project.getLocation();
107
if (isPrefix(projectPath, fullPath)) {
108
return fullPath.removeFirstSegments(projectPath.segmentCount());
110
return getWorkspaceRelativePath(fullPath);
113
public static IPath getWorkspaceRelativePath(String fullPath) {
114
return getWorkspaceRelativePath(new Path(fullPath));
117
public static IPath getRawLocation(IPath wsRelativePath) {
118
IWorkspaceRoot workspaceRoot = getWorkspaceRoot();
119
if (workspaceRoot != null && wsRelativePath != null) {
120
IPath workspaceLocation = workspaceRoot.getLocation();
121
if (workspaceLocation != null && !isPrefix(workspaceLocation, wsRelativePath)) {
122
return workspaceLocation.append(wsRelativePath);
125
return wsRelativePath;
128
public static IPath makeRelativePath(IPath path, IPath relativeTo) {
129
int segments = matchingFirstSegments(relativeTo, path);
131
IPath prefix = relativeTo.removeFirstSegments(segments);
132
IPath suffix = path.removeFirstSegments(segments);
133
IPath relativePath = new Path(""); //$NON-NLS-1$
134
for (int i = 0; i < prefix.segmentCount(); ++i) {
135
relativePath = relativePath.append(".." + IPath.SEPARATOR); //$NON-NLS-1$
137
return relativePath.append(suffix);
142
public static IPath makeRelativePathToProjectIncludes(IPath fullPath, IProject project) {
143
IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project);
144
if (provider != null) {
145
IScannerInfo info = provider.getScannerInformation(project);
147
return makeRelativePathToIncludes(fullPath, info.getIncludePaths());
153
public static IPath makeRelativePathToIncludes(IPath fullPath, String[] includePaths) {
154
IPath relativePath = null;
155
int mostSegments = 0;
156
for (int i = 0; i < includePaths.length; ++i) {
157
IPath includePath = new Path(includePaths[i]);
158
if (isPrefix(includePath, fullPath)) {
159
int segments = includePath.segmentCount();
160
if (segments > mostSegments) {
161
relativePath = fullPath.removeFirstSegments(segments).setDevice(null);
162
mostSegments = segments;
169
public static IProject getEnclosingProject(IPath fullPath) {
170
IWorkspaceRoot root = getWorkspaceRoot();
172
IPath path = getWorkspaceRelativePath(fullPath);
173
while (path.segmentCount() > 0) {
174
IResource res = root.findMember(path);
176
return res.getProject();
178
path = path.removeLastSegments(1);
184
public static IPath getValidEnclosingFolder(IPath fullPath) {
185
IWorkspaceRoot root = getWorkspaceRoot();
187
IPath path = getWorkspaceRelativePath(fullPath);
188
while (path.segmentCount() > 0) {
189
IResource res = root.findMember(path);
190
if (res != null && res.exists() && (res.getType() == IResource.PROJECT || res.getType() == IResource.FOLDER))
193
path = path.removeLastSegments(1);
200
* Checks whether path1 is the same as path2.
201
* @return <code>true</code> if path1 is the same as path2, and <code>false</code> otherwise
203
* Similar to IPath.equals(Object obj), but takes case sensitivity of the file system
206
* @deprecated Use {@link #equalPath(IPath, IPath)} instead.
209
public boolean equal(IPath path1, IPath path2) {
210
// Check leading separators
211
if (path1.isAbsolute() != path2.isAbsolute() || path1.isUNC() != path2.isUNC()) {
214
int i = path1.segmentCount();
215
// Check segment count
216
if (i != path2.segmentCount())
218
// Check segments in reverse order - later segments more likely to differ
220
if (!path1.segment(i).equals(path2.segment(i)))
223
// Check device last (least likely to differ)
224
if (path1.getDevice() == null) {
225
return path2.getDevice() == null;
227
return path1.getDevice().equalsIgnoreCase(path2.getDevice());
232
* Checks whether path1 is the same as path2.
233
* @return <code>true</code> if path1 is the same as path2, and <code>false</code> otherwise
235
* Similar to IPath.equals(Object obj), but takes case sensitivity of the file system
239
public static boolean equalPath(IPath path1, IPath path2) {
240
// Check leading separators
241
if (path1.isAbsolute() != path2.isAbsolute() || path1.isUNC() != path2.isUNC()) {
244
int i = path1.segmentCount();
245
// Check segment count
246
if (i != path2.segmentCount())
248
// Check segments in reverse order - later segments more likely to differ
249
boolean caseSensitive = !isWindowsFileSystem();
251
if (!(caseSensitive ?
252
path1.segment(i).equals(path2.segment(i)) :
253
path1.segment(i).equalsIgnoreCase(path2.segment(i)))) {
257
// Check device last (least likely to differ)
258
if (path1.getDevice() == null) {
259
return path2.getDevice() == null;
261
return path1.getDevice().equalsIgnoreCase(path2.getDevice());
266
* Checks whether path1 is a prefix of path2. To be a prefix, path1's segments
267
* must appear in path1 in the same order, and their device ids must match.
269
* An empty path is a prefix of all paths with the same device; a root path is a prefix of
270
* all absolute paths with the same device.
272
* @return <code>true</code> if path1 is a prefix of path2, and <code>false</code> otherwise
274
* Similar to IPath.isPrefixOf(IPath anotherPath), but takes case sensitivity of the file system
278
public static boolean isPrefix(IPath path1, IPath path2) {
279
if (path1.getDevice() == null) {
280
if (path2.getDevice() != null) {
284
if (!path1.getDevice().equalsIgnoreCase(path2.getDevice())) {
288
if (path1.isEmpty() || (path1.isRoot() && path2.isAbsolute())) {
291
int len1 = path1.segmentCount();
292
if (len1 > path2.segmentCount()) {
295
boolean caseSensitive = !isWindowsFileSystem();
296
for (int i = 0; i < len1; i++) {
297
if (!(caseSensitive ?
298
path1.segment(i).equals(path2.segment(i)) :
299
path1.segment(i).equalsIgnoreCase(path2.segment(i)))) {
307
* Returns the number of segments which match in path1 and path2
308
* (device ids are ignored), comparing in increasing segment number order.
310
* @return the number of matching segments
312
* Similar to IPath.matchingFirstSegments(IPath anotherPath), but takes case sensitivity
313
* of the file system into account.
316
public static int matchingFirstSegments(IPath path1, IPath path2) {
317
Assert.isNotNull(path1);
318
Assert.isNotNull(path2);
319
int len1 = path1.segmentCount();
320
int len2 = path2.segmentCount();
321
int max = Math.min(len1, len2);
323
boolean caseSensitive = !isWindowsFileSystem();
324
for (int i = 0; i < max; i++) {
325
if (!(caseSensitive ?
326
path1.segment(i).equals(path2.segment(i)) :
327
path1.segment(i).equalsIgnoreCase(path2.segment(i)))) {
336
* Find location of the program inspecting each path in the path list.
338
* @param prog - program to find. For Windows, extensions "com" and "exe"
340
* @param pathsStr - the list of paths to inspect separated by path separator
341
* defined in the platform (i.e. ":" in Unix and ";" in Windows).
342
* In case pathStr is {@code null} environment variable ${PATH} is inspected.
343
* @return - absolute location of the file on the file system.
346
public static IPath findProgramLocation(String prog, String pathsStr) {
347
if (prog==null || prog.trim().length()==0)
351
pathsStr = System.getenv("PATH"); //$NON-NLS-1$
353
if (pathsStr.trim().length()==0)
356
String locationStr = null;
357
String[] dirs = pathsStr.split(File.pathSeparator);
359
// try to find "prog.exe" or "prog.com" on Windows
360
if (Platform.getOS().equals(Platform.OS_WIN32)) {
361
for (String dir : dirs) {
362
IPath dirLocation = new Path(dir);
365
file = dirLocation.append(prog+".exe").toFile(); //$NON-NLS-1$
366
if (file.isFile() && file.canRead()) {
367
locationStr = file.getAbsolutePath();
370
file = dirLocation.append(prog+".com").toFile(); //$NON-NLS-1$
371
if (file.isFile() && file.canRead()) {
372
locationStr = file.getAbsolutePath();
378
// check "prog" on Unix and Windows too (if was not found) - could be cygwin or something
379
// do it in separate loop due to performance and correctness of Windows regular case
380
if (locationStr==null) {
381
for (String dir : dirs) {
382
IPath dirLocation = new Path(dir);
385
file = dirLocation.append(prog).toFile();
386
if (file.isFile() && file.canRead()) {
387
locationStr = file.getAbsolutePath();
393
if (locationStr!=null)
394
return new Path(locationStr);
400
* Find location of the program inspecting each path in the path list
401
* defined by environment variable ${PATH}.
403
* @param prog - program to find. For Windows, extensions "com" and "exe"
405
* @return - absolute location of the file on the file system.
408
public static IPath findProgramLocation(String prog) {
409
return findProgramLocation(prog, null);