| /******************************************************************************* |
| * Copyright (c) 2009, 2016 Andrew Gvozdev 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: |
| * Andrew Gvozdev - Initial API and implementation |
| * James Blackburn (Broadcom Corp.) |
| * Liviu Ionescu - bug 392416 |
| *******************************************************************************/ |
| package org.eclipse.jdt.core.tests.nd.util; |
| |
| import java.io.BufferedReader; |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.Reader; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.nio.charset.Charset; |
| import java.util.HashSet; |
| import java.util.Set; |
| import java.util.UUID; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| 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.Path; |
| import org.eclipse.core.runtime.Platform; |
| import org.junit.Assert; |
| |
| /** |
| * This class contains utility methods for creating resources |
| * such as projects, files, folders etc. which are being used |
| * in test fixture of unit tests. |
| * |
| * Some classes with similar idea worth to look at: |
| * org.eclipse.core.filebuffers.tests.ResourceHelper, |
| * org.eclipse.cdt.ui.tests.text.ResourceHelper. |
| */ |
| public class ResourceHelper { |
| private final static IProgressMonitor NULL_MONITOR = new NullProgressMonitor(); |
| private static final int MAX_RETRY= 5; |
| |
| private final static Set<String> externalFilesCreated = new HashSet<String>(); |
| private final static Set<IResource> resourcesCreated = new HashSet<IResource>(); |
| |
| /** |
| * Creates a plain Eclipse project. |
| * |
| * @param projectName |
| * @return the project handle |
| * @throws CoreException if project could not be created |
| */ |
| public static IProject createProject(String projectName) throws CoreException { |
| IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); |
| IProject project= root.getProject(projectName); |
| if (!project.exists()) { |
| project.create(NULL_MONITOR); |
| } else { |
| project.refreshLocal(IResource.DEPTH_INFINITE, null); |
| } |
| |
| if (!project.isOpen()) |
| project.open(NULL_MONITOR); |
| |
| resourcesCreated.add(project); |
| return project; |
| } |
| |
| /** |
| * Deletes project by name. |
| * |
| * @param projectName |
| * @throws CoreException |
| */ |
| public static void deleteProject(String projectName) throws CoreException { |
| IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); |
| IProject project= root.getProject(projectName); |
| if (project.exists()) |
| delete(project); |
| } |
| |
| /** |
| * Deletes given project with content. |
| * |
| * @param project |
| * @throws CoreException |
| */ |
| public static void delete(final IProject project) throws CoreException { |
| delete(project, true); |
| } |
| |
| /** |
| * Deletes project. |
| * |
| * @param project |
| * @param deleteContent whether to delete project content |
| * @throws CoreException |
| */ |
| public static void delete(final IProject project, boolean deleteContent) throws CoreException { |
| for (int i= 0; i < MAX_RETRY; i++) { |
| try { |
| project.delete(deleteContent, true, NULL_MONITOR); |
| i= MAX_RETRY; |
| } catch (CoreException x) { |
| if (i == MAX_RETRY - 1) { |
| Package.log(x.getStatus()); |
| } |
| try { |
| Thread.sleep(1000); // sleep a second |
| } catch (InterruptedException e) { |
| } |
| } |
| } |
| } |
| |
| /** |
| * Creates a file with specified content. |
| * |
| * @param file - file name. |
| * @param contents - contents of the file. |
| * @return file handle. |
| * @throws CoreException - if the file can't be created. |
| */ |
| public static IFile createFile(IFile file, String contents) throws CoreException { |
| if (contents == null) { |
| contents= ""; |
| } |
| |
| InputStream inputStream = new ByteArrayInputStream(contents.getBytes()); |
| file.create(inputStream, true, NULL_MONITOR); |
| resourcesCreated.add(file); |
| return file; |
| } |
| |
| /** |
| * Creates new file from project root with empty content. The filename |
| * can include relative path as a part of the name but the the path |
| * has to be present on disk. |
| * |
| * @param project - project where to create the file. |
| * @param name - filename. |
| * @return file handle. |
| * @throws CoreException if something goes wrong. |
| */ |
| public static IFile createFile(IProject project, String name) throws CoreException { |
| if (new Path(name).segmentCount() > 1) |
| createFolder(project, new Path(name).removeLastSegments(1).toString()); |
| return createFile(project.getFile(name), null); |
| } |
| |
| /** |
| * Creates new file from workspace root with empty content. The filename |
| * can include relative path as a part of the name but the the path |
| * has to be present on disk. |
| * The intention of the method is to create files which do not belong to any project. |
| * |
| * @param name - filename. |
| * @return full path of the created file. |
| * |
| * @throws CoreException... |
| * @throws IOException... |
| */ |
| public static IPath createWorkspaceFile(String name) throws CoreException, IOException { |
| IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); |
| IPath fullPath = workspaceRoot.getLocation().append(name); |
| java.io.File file = new java.io.File(fullPath.toOSString()); |
| if (!file.exists()) { |
| boolean result = file.createNewFile(); |
| Assert.assertTrue(result); |
| } |
| Assert.assertTrue(file.exists()); |
| |
| externalFilesCreated.add(fullPath.toOSString()); |
| workspaceRoot.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); |
| return fullPath; |
| } |
| |
| /** |
| * Creates new folder from project root. The folder name |
| * can include relative path as a part of the name. |
| * Nonexistent parent directories are being created. |
| * |
| * @param project - project where to create the folder. |
| * @param name - folder name. |
| * @return folder handle. |
| * @throws CoreException if something goes wrong. |
| */ |
| public static IFolder createFolder(IProject project, String name) throws CoreException { |
| final IPath p = new Path(name); |
| IContainer folder = project; |
| for (String seg : p.segments()) { |
| folder = folder.getFolder(new Path(seg)); |
| if (!folder.exists()) |
| ((IFolder)folder).create(true, true, NULL_MONITOR); |
| } |
| resourcesCreated.add(folder); |
| return (IFolder)folder; |
| } |
| |
| /** |
| * Creates new folder from workspace root. The folder name |
| * can include relative path as a part of the name. |
| * Nonexistent parent directories are being created as per {@link File#mkdirs()}. |
| * The intention of the method is to create folders which do not belong to any project. |
| * |
| * @param name - folder name. |
| * @return absolute location of the folder on the file system. |
| * @throws IOException if something goes wrong. |
| */ |
| public static IPath createWorkspaceFolder(String name) throws CoreException, IOException { |
| IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); |
| IPath fullPath = workspaceRoot.getLocation().append(name); |
| java.io.File folder = new java.io.File(fullPath.toOSString()); |
| if (!folder.exists()) { |
| boolean result = folder.mkdirs(); |
| Assert.assertTrue(result); |
| } |
| Assert.assertTrue(folder.exists()); |
| |
| externalFilesCreated.add(fullPath.toOSString()); |
| workspaceRoot.refreshLocal(IResource.DEPTH_INFINITE, NULL_MONITOR); |
| return fullPath; |
| } |
| |
| /** |
| * Creates new temporary folder with generated name from workspace root. |
| * |
| * @return absolute location of the folder on the file system. |
| * @throws IOException if something goes wrong. |
| */ |
| public static IPath createTemporaryFolder() throws CoreException, IOException { |
| return ResourceHelper.createWorkspaceFolder("tmp/" + System.currentTimeMillis() + '.' + UUID.randomUUID()); |
| } |
| |
| /** |
| * Creates new eclipse file-link from project root to file system file. The filename |
| * can include relative path as a part of the name but the the path |
| * has to be present on disk. |
| * |
| * @param project - project where to create the file. |
| * @param fileLink - filename of the link being created. |
| * @param realFile - file on the file system, the target of the link. |
| * @return file handle. |
| * @throws CoreException if something goes wrong. |
| */ |
| public static IFile createLinkedFile(IProject project, String fileLink, IPath realFile) throws CoreException { |
| IFile file = project.getFile(fileLink); |
| file.createLink(realFile, IResource.REPLACE, null); |
| Assert.assertTrue(file.exists()); |
| resourcesCreated.add(file); |
| return file; |
| } |
| |
| /** |
| * Creates new eclipse file-link from project root to file system file. The filename |
| * can include relative path as a part of the name but the the path |
| * has to be present on disk. |
| * |
| * @param project - project where to create the file. |
| * @param fileLink - filename of the link being created. |
| * @param realFile - file on the file system, the target of the link. |
| * @return file handle. |
| * @throws CoreException if something goes wrong. |
| */ |
| public static IFile createLinkedFile(IProject project, String fileLink, String realFile) throws CoreException { |
| return createLinkedFile(project, fileLink, new Path(realFile)); |
| } |
| |
| /** |
| * Creates new eclipse file-link from project root to EFS file. |
| * |
| * @param project - project where to create the file. |
| * @param fileLink - filename of the link being created. |
| * @param realFile - file on the EFS file system, the target of the link. |
| * @return file handle. |
| * @throws CoreException if something goes wrong. |
| */ |
| public static IFile createEfsFile(IProject project, String fileLink, URI realFile) throws CoreException { |
| IFile file= project.getFile(fileLink); |
| file.createLink(realFile, IResource.ALLOW_MISSING_LOCAL, NULL_MONITOR); |
| resourcesCreated.add(file); |
| return file; |
| } |
| |
| /** |
| * Creates new eclipse file-link from project root to EFS file. |
| * |
| * @param project - project where to create the file. |
| * @param fileLink - filename of the link being created. |
| * @param realFile - file on the EFS file system, the target of the link. |
| * @return file handle. |
| * @throws CoreException if something goes wrong. |
| * @throws URISyntaxException if wrong URI syntax |
| */ |
| public static IFile createEfsFile(IProject project, String fileLink, String realFile) throws CoreException, URISyntaxException { |
| return createEfsFile(project,fileLink,new URI(realFile)); |
| } |
| |
| /** |
| * Creates new eclipse folder-link from project root to file system folder. The folder name |
| * can include relative path as a part of the name but the the path |
| * has to be present on disk. |
| * |
| * @param project - project where to create the file. |
| * @param folderLink - name of the link being created. |
| * @param realFolder - folder on the file system, the target of the link. |
| * @return file handle. |
| * @throws CoreException if something goes wrong. |
| */ |
| public static IFolder createLinkedFolder(IProject project, String folderLink, IPath realFolder) throws CoreException { |
| IFolder folder = project.getFolder(folderLink); |
| folder.createLink(realFolder, IResource.REPLACE | IResource.ALLOW_MISSING_LOCAL, null); |
| Assert.assertTrue(folder.exists()); |
| resourcesCreated.add(folder); |
| return folder; |
| } |
| |
| /** |
| * Creates new eclipse folder-link from project root to file system folder. The folder name |
| * can include relative path as a part of the name but the the path |
| * has to be present on disk. |
| * |
| * @param project - project where to create the file. |
| * @param folderLink - name of the link being created. |
| * @param realFolder - folder on the file system, the target of the link. |
| * @return file handle. |
| * @throws CoreException if something goes wrong. |
| */ |
| public static IFolder createLinkedFolder(IProject project, String folderLink, String realFolder) throws CoreException { |
| return createLinkedFolder(project, folderLink, new Path(realFolder)); |
| } |
| |
| /** |
| * Creates new eclipse folder-link from project root to EFS folder. |
| * |
| * @param project - project where to create the folder. |
| * @param folderLink - folder name of the link being created. |
| * @param realFolder - folder on the EFS file system, the target of the link. |
| * @return folder handle. |
| * @throws CoreException if something goes wrong. |
| */ |
| public static IFolder createEfsFolder(IProject project, String folderLink, URI realFolder) throws CoreException { |
| IFolder folder= project.getFolder(folderLink); |
| if (folder.exists()) { |
| Assert.assertEquals("Folder with the same name but different location already exists", |
| realFolder, folder.getLocationURI()); |
| return folder; |
| } |
| |
| folder.createLink(realFolder, IResource.ALLOW_MISSING_LOCAL, new NullProgressMonitor()); |
| resourcesCreated.add(folder); |
| return folder; |
| } |
| |
| /** |
| * Creates new eclipse folder-link from project root to EFS folder. |
| * |
| * @param project - project where to create the folder. |
| * @param folderLink - folder name of the link being created. |
| * @param realFolder - folder on the EFS file system, the target of the link. |
| * @return folder handle. |
| * @throws CoreException if something goes wrong. |
| * @throws URISyntaxException if wrong URI syntax |
| */ |
| public static IFolder createEfsFolder(IProject project, String folderLink, String realFolder) throws CoreException, URISyntaxException { |
| return createEfsFolder(project,folderLink,new URI(realFolder)); |
| } |
| |
| /** |
| * Checks if symbolic links are supported on the system. |
| * Used in particular by method {@link #createSymbolicLink(IPath, IPath)} |
| * and other flavors to create symbolic links. |
| * |
| * Note that Windows links .lnk are not supported here. |
| * @return {@code true} if symbolic links are suppoted, {@code false} otherwise. |
| */ |
| public static boolean isSymbolicLinkSupported() { |
| return ! Platform.getOS().equals(Platform.OS_WIN32); |
| } |
| |
| /** |
| * Creates new symbolic file system link from file or folder on project root |
| * to another file system file. The filename can include relative path |
| * as a part of the name but the the path has to be present on disk. |
| * |
| * @param project - project where to create the file. |
| * @param linkName - name of the link being created. |
| * @param realPath - file or folder on the file system, the target of the link. |
| * @return file handle. |
| * |
| * @throws UnsupportedOperationException on Windows where links are not supported. |
| * @throws IOException... |
| * @throws CoreException... |
| */ |
| public static IResource createSymbolicLink(IProject project, String linkName, IPath realPath) |
| throws IOException, CoreException, UnsupportedOperationException { |
| if (!isSymbolicLinkSupported()) { |
| throw new UnsupportedOperationException("Windows links .lnk are not supported."); |
| } |
| |
| Assert.assertTrue("Path for symbolic link does not exist: [" + realPath.toOSString() + "]", |
| new File(realPath.toOSString()).exists()); |
| |
| IPath linkedPath = project.getLocation().append(linkName); |
| createSymbolicLink(linkedPath, realPath); |
| |
| IResource resource = project.getFile(linkName); |
| resource.refreshLocal(IResource.DEPTH_ZERO, null); |
| |
| if (!resource.exists()) { |
| resource = project.getFolder(linkName); |
| resource.refreshLocal(IResource.DEPTH_ZERO, null); |
| } |
| Assert.assertTrue("Failed to create resource form symbolic link", resource.exists()); |
| |
| externalFilesCreated.add(linkedPath.toOSString()); |
| ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, NULL_MONITOR); |
| return resource; |
| } |
| |
| /** |
| * Creates new symbolic file system link from file or folder to another filesystem file. |
| * The target path has to be present on disk. |
| * |
| * @param linkPath - filesystem path of the link being created. |
| * @param realPath - file or folder on the file system, the target of the link. |
| * |
| * @throws UnsupportedOperationException on Windows where links are not supported. |
| * @throws IOException if execution of the command fails. |
| */ |
| public static void createSymbolicLink(IPath linkPath, IPath realPath) throws IOException { |
| if (!isSymbolicLinkSupported()) { |
| throw new UnsupportedOperationException("Windows links .lnk are not supported."); |
| } |
| |
| String command[] = { "ln", "-s", realPath.toOSString(), linkPath.toOSString()}; |
| Process process = Runtime.getRuntime().exec(command); |
| |
| // Wait for up to 2.5s... |
| for (int i = 0; i < 5; i++) { |
| try { |
| Assert.assertTrue("ln process exited with non-zero status", process.waitFor() == 0); |
| // If exitValue succeeded, then the process has exited successfully. |
| break; |
| } catch (InterruptedException e) { |
| // Clear interrupted state, see Java bug http://bugs.sun.com/view_bug.do?bug_id=6420270 |
| Thread.interrupted(); |
| } |
| // Wait for a 500ms before checking again. |
| try { Thread.sleep(500); } catch (InterruptedException e) {/*don't care*/} |
| } |
| Assert.assertTrue("Symbolic link not created, command=[" + command + "]", linkPath.toFile().exists()); |
| } |
| |
| /** |
| * Creates new symbolic file system link from file or folder on project root |
| * to another file system file. The filename can include relative path |
| * as a part of the name but the the path has to be present on disk. |
| * |
| * @param project - project where to create the file. |
| * @param linkName - name of the link being created. |
| * @param realPath - file or folder on the file system, the target of the link. |
| * @return file handle. |
| * |
| * @throws UnsupportedOperationException on Windows where links are not supported. |
| * @throws IOException... |
| * @throws CoreException... |
| */ |
| public static IResource createSymbolicLink(IProject project, String linkName, String realPath) |
| throws IOException, CoreException, UnsupportedOperationException { |
| return createSymbolicLink(project, linkName, new Path(realPath)); |
| } |
| |
| /** |
| * Get contents of file on file-system. |
| * |
| * @param fullPath - full path to the file on the file-system. |
| * @return contents of the file. |
| * @throws IOException on IO problem. |
| */ |
| public static String getContents(IPath fullPath) throws IOException { |
| FileInputStream stream = new FileInputStream(fullPath.toFile()); |
| try { |
| // Avoid using java.nio.channels.FileChannel, |
| // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154 |
| Reader reader = new BufferedReader(new InputStreamReader(stream, Charset.defaultCharset())); |
| StringBuilder builder = new StringBuilder(); |
| char[] buffer = new char[8192]; |
| int read; |
| while ((read = reader.read(buffer, 0, buffer.length)) > 0) { |
| builder.append(buffer, 0, read); |
| } |
| return builder.toString(); |
| } finally { |
| stream.close(); |
| } |
| } |
| |
| /** |
| * Get contents of file on file-system. |
| * |
| * @param fullPath - full path to the file on the file-system. |
| * @return contents of the file. |
| * @throws IOException on IO problem. |
| */ |
| public static String getContents(String fullPath) throws IOException { |
| return getContents(new Path(fullPath)); |
| } |
| |
| /** |
| * Clean-up any files created as part of a unit test. |
| * This method removes *all* Workspace IResources and any external |
| * files / folders created with the #createWorkspaceFile #createWorkspaceFolder |
| * methods in this class |
| */ |
| public static void cleanUp() throws CoreException, IOException { |
| IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); |
| root.refreshLocal(IResource.DEPTH_INFINITE, NULL_MONITOR); |
| |
| // Delete all external files & folders created using ResourceHelper |
| for (String loc : externalFilesCreated) { |
| File f = new File(loc); |
| if (f.exists()) |
| deleteRecursive(f); |
| } |
| externalFilesCreated.clear(); |
| |
| // Remove IResources created by this helper |
| for (IResource r : resourcesCreated) { |
| if (r.exists()) { |
| try { |
| r.delete(true, NULL_MONITOR); |
| } catch (CoreException e) { |
| // Ignore |
| } |
| } |
| } |
| resourcesCreated.clear(); |
| } |
| |
| /** |
| * Recursively delete a directory / file |
| * |
| * For safety this method only deletes files created under the workspace |
| */ |
| private static final void deleteRecursive(File f) throws IllegalArgumentException { |
| // Ensure that the file being deleted is a child of the workspace |
| // root to prevent anything nasty happening |
| if (!f.getAbsolutePath().startsWith( |
| ResourcesPlugin.getWorkspace().getRoot().getLocation().toFile().getAbsolutePath())) { |
| throw new IllegalArgumentException("File must exist within the workspace!"); |
| } |
| |
| if (f.isDirectory()) { |
| for (File f1 : f.listFiles()) { |
| deleteRecursive(f1); |
| } |
| } |
| f.delete(); |
| } |
| } |