| /******************************************************************************* |
| * Copyright (c) 2005, 2014 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 API and implementation |
| * Serge Beauchamp (Freescale Semiconductor) - [229633] Project Path Variable Support |
| * Sergey Prigogin (Google) - [338010] Resource.createLink() does not preserve symbolic links |
| *******************************************************************************/ |
| package org.eclipse.core.internal.localstore; |
| |
| import java.io.File; |
| import java.net.URI; |
| import org.eclipse.core.filesystem.EFS; |
| import org.eclipse.core.filesystem.IFileStore; |
| import org.eclipse.core.internal.utils.FileUtil; |
| import org.eclipse.core.resources.*; |
| import org.eclipse.core.runtime.*; |
| |
| /** |
| * Represents the root of a file system that is connected to the workspace. |
| * A file system can be rooted on any resource. |
| */ |
| public class FileStoreRoot { |
| private int chop; |
| /** |
| * When a root is changed, the old root object is marked invalid |
| * so that other resources with a cache of the root will know they need to update. |
| */ |
| private boolean isValid = true; |
| /** |
| * If this root represents a resource in the local file system, this path |
| * represents the root location. This value is null if the root represents |
| * a non-local file system |
| */ |
| private IPath localRoot; |
| /** |
| * Canonicalized version of localRoot. Initialized lazily. |
| * @see FileUtil#canonicalPath(IPath) |
| */ |
| private IPath canonicalLocalRoot; |
| |
| private URI root; |
| /** |
| * Canonicalized version of root. Initialized lazily. |
| * @see FileUtil#canonicalURI(URI) |
| */ |
| private URI canonicalRoot; |
| |
| /** |
| * Defines the root of a file system within the workspace tree. |
| * @param rootURI The virtual file representing the root of the file |
| * system that has been mounted |
| * @param workspacePath The workspace path at which this file |
| * system has been mounted |
| */ |
| FileStoreRoot(URI rootURI, IPath workspacePath) { |
| Assert.isNotNull(rootURI); |
| Assert.isNotNull(workspacePath); |
| this.root = rootURI; |
| this.chop = workspacePath.segmentCount(); |
| this.localRoot = toLocalPath(root); |
| } |
| |
| private IPathVariableManager getManager(IPath workspacePath) { |
| IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); |
| IResource resource = workspaceRoot.findMember(workspacePath); |
| if (resource != null) |
| return resource.getPathVariableManager(); |
| return workspaceRoot.getFile(workspacePath).getPathVariableManager(); |
| } |
| |
| /** |
| * Returns the resolved, absolute file system location of the resource |
| * corresponding to the given workspace path, or null if none could |
| * be computed. No canonicalization is applied to the returned URI. |
| */ |
| public URI computeURI(IPath workspacePath) { |
| return computeURI(workspacePath, false); |
| } |
| |
| /** |
| * Returns the resolved, absolute file system location of the resource |
| * corresponding to the given workspace path, or null if none could |
| * be computed. |
| * |
| * @param workspacePath the workspace path to compute the URL for |
| * @param canonical if {@code true}, the prefix of the path of the returned URI |
| * corresponding to this root will be canonicalized |
| */ |
| public URI computeURI(IPath workspacePath, boolean canonical) { |
| IPath childPath = workspacePath.removeFirstSegments(chop); |
| URI rootURI = canonical ? getCanonicalRoot() : root; |
| rootURI = getManager(workspacePath).resolveURI(rootURI); |
| if (childPath.segmentCount() == 0) |
| return rootURI; |
| try { |
| return EFS.getStore(rootURI).getFileStore(childPath).toURI(); |
| } catch (CoreException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Creates an IFileStore for a given workspace path. The prefix of the path of |
| * the returned IFileStore corresponding to this root is canonicalized. |
| * @exception CoreException If the file system for that resource is undefined |
| */ |
| IFileStore createStore(IPath workspacePath, IResource resource) throws CoreException { |
| IPath childPath = workspacePath.removeFirstSegments(chop); |
| // For a linked resource itself we have to use its root, but for its children we prefer |
| // to use the canonical root since it provides for faster file system access. |
| // See http://bugs.eclipse.org/507084 |
| final URI uri = resource.getPathVariableManager().resolveURI(resource.isLinked() ? root : getCanonicalRoot()); |
| if (!uri.isAbsolute()) { |
| // Handles case where resource location cannot be resolved such as |
| // unresolved path variable or invalid file system scheme. |
| return EFS.getNullFileSystem().getStore(workspacePath); |
| } |
| IFileStore rootStore = EFS.getStore(uri); |
| if (childPath.segmentCount() == 0) |
| return rootStore; |
| return rootStore.getFileStore(childPath); |
| } |
| |
| boolean isValid() { |
| return isValid; |
| } |
| |
| /** |
| * Returns the resolved, absolute file system location of the given resource. |
| * Returns null if the location could not be resolved. No canonicalization |
| * is applied to the returned path. |
| * |
| * @param workspacePath the workspace path of the resource |
| * @param resource the resource itself |
| */ |
| IPath localLocation(IPath workspacePath, IResource resource) { |
| return localLocation(workspacePath, resource, false); |
| } |
| |
| /** |
| * Returns the resolved, absolute file system location of the given resource. |
| * Returns null if the location could not be resolved. |
| * |
| * @param workspacePath the workspace path of the resource |
| * @param resource the resource itself |
| * @param canonical if {@code true}, the prefix of the returned path corresponding |
| * to this root will be canonicalized |
| */ |
| IPath localLocation(IPath workspacePath, IResource resource, boolean canonical) { |
| if (localRoot == null) |
| return null; |
| IPath rootPath = canonical ? getCanonicalLocalRoot() : localRoot; |
| IPath location; |
| if (workspacePath.segmentCount() <= chop) |
| location = rootPath; |
| else |
| location = rootPath.append(workspacePath.removeFirstSegments(chop)); |
| location = resource.getPathVariableManager().resolvePath(location); |
| |
| // if path is still relative then path variable could not be resolved |
| // if path is null, it means path variable refers to a non-local filesystem |
| if (location == null || !location.isAbsolute()) |
| return null; |
| return location; |
| } |
| |
| void setValid(boolean value) { |
| this.isValid = value; |
| } |
| |
| /** |
| * Returns the local path for the given URI, or null if not possible. |
| */ |
| private IPath toLocalPath(URI uri) { |
| try { |
| final File localFile = EFS.getStore(uri).toLocalFile(EFS.NONE, null); |
| return localFile == null ? null : new Path(localFile.getAbsolutePath()); |
| } catch (CoreException e) { |
| return FileUtil.toPath(uri); |
| } |
| } |
| |
| private synchronized IPath getCanonicalLocalRoot() { |
| if (canonicalLocalRoot == null && localRoot != null) { |
| canonicalLocalRoot = FileUtil.canonicalPath(localRoot); |
| } |
| return canonicalLocalRoot; |
| } |
| |
| private synchronized URI getCanonicalRoot() { |
| if (canonicalRoot == null) { |
| canonicalRoot = FileUtil.canonicalURI(root); |
| } |
| return canonicalRoot; |
| } |
| } |