| /******************************************************************************* |
| * Copyright (c) 2008, 2015 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 |
| *******************************************************************************/ |
| package org.eclipse.ltk.core.refactoring.tests.resource; |
| |
| import java.io.BufferedReader; |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.net.URI; |
| import java.nio.charset.StandardCharsets; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.commands.ExecutionException; |
| import org.eclipse.core.commands.operations.IOperationHistory; |
| import org.eclipse.core.commands.operations.IUndoContext; |
| import org.eclipse.core.commands.operations.OperationHistoryFactory; |
| import org.eclipse.core.filesystem.EFS; |
| import org.eclipse.core.filesystem.IFileStore; |
| import org.eclipse.core.filesystem.URIUtil; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IMarker; |
| 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.ltk.core.refactoring.CheckConditionsOperation; |
| import org.eclipse.ltk.core.refactoring.PerformRefactoringOperation; |
| import org.eclipse.ltk.core.refactoring.Refactoring; |
| import org.eclipse.ltk.core.refactoring.RefactoringContribution; |
| import org.eclipse.ltk.core.refactoring.RefactoringCore; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| import org.eclipse.ltk.core.refactoring.resource.DeleteResourcesDescriptor; |
| import org.eclipse.ltk.core.refactoring.resource.RenameResourceDescriptor; |
| import org.eclipse.ltk.core.refactoring.tests.FileSystemHelper; |
| import org.eclipse.ltk.core.refactoring.tests.RefactoringCoreTestPlugin; |
| import org.eclipse.ltk.core.refactoring.tests.participants.ElementRenameProcessor; |
| import org.eclipse.ltk.core.refactoring.tests.participants.ElementRenameRefactoring; |
| import org.eclipse.ltk.core.refactoring.tests.util.SimpleTestProject; |
| import org.eclipse.ltk.internal.core.refactoring.RefactoringCorePlugin; |
| |
| import junit.framework.Test; |
| import junit.framework.TestCase; |
| import junit.framework.TestSuite; |
| |
| public class ResourceRefactoringUndoTests extends TestCase { |
| private static final String TEST_NEWPROJECT_NAME= "projectTestNew"; |
| private static final String TEST_FOLDER_NAME= "test"; |
| private static final String TEST_NEWFOLDER_NAME= "testNew"; |
| private static final String TEST_FILE_NAME= "myFile.txt"; |
| private static final String TEST_NEWFILE_NAME= "newFile.txt"; |
| private static final String TEST_LINKEDFOLDER_NAME= "linkedFolder"; |
| private static final String TEST_LINKEDFILE_NAME= "linkedFile.txt"; |
| private static final String TEST_SUBFOLDER_NAME= "subFolder"; |
| private static List<String> fileNameExcludes= new ArrayList<>(); |
| |
| static { |
| fileNameExcludes.add(".project"); |
| } |
| |
| public static Test suite() { |
| TestSuite suite= new TestSuite(ResourceRefactoringUndoTests.class.getName()); |
| suite.addTestSuite(ResourceRefactoringUndoTests.class); |
| return suite; |
| } |
| |
| private static final String CONTENT= "hello"; |
| private SimpleTestProject fProject; |
| private IFolder testFolder; |
| private IFile testFile; |
| private IOperationHistory history; |
| private IUndoContext context; |
| private final Set<IFileStore> storesToDelete= new HashSet<>(); |
| private IFolder testLinkedFolder; |
| private IFile testLinkedFile; |
| private IFolder testSubFolder; |
| |
| @Override |
| protected void setUp() throws Exception { |
| fProject= new SimpleTestProject(); |
| |
| testFolder= fProject.createFolder(TEST_FOLDER_NAME); |
| testFile= fProject.createFile(testFolder, TEST_FILE_NAME, CONTENT); |
| // Create links by first creating the backing content... |
| IFileStore folderStore= getTempStore(); |
| IFileStore fileStore= getTempStore(); |
| IPath folderLocation= URIUtil.toPath(folderStore.toURI()); |
| IPath fileLocation= URIUtil.toPath(fileStore.toURI()); |
| folderStore.mkdir(EFS.NONE, getMonitor()); |
| fileStore.openOutputStream(EFS.NONE, getMonitor()).close(); |
| // Then create the workspace objects |
| testLinkedFolder= testFolder.getFolder(TEST_LINKEDFOLDER_NAME); |
| testLinkedFolder.createLink(folderLocation, IResource.NONE, getMonitor()); |
| assertTrue(testLinkedFolder.exists()); |
| testLinkedFile= testFolder.getFile(TEST_LINKEDFILE_NAME); |
| testLinkedFile.createLink(fileLocation, IResource.NONE, getMonitor()); |
| |
| // subfolder |
| testSubFolder= testFolder.getFolder(TEST_SUBFOLDER_NAME); |
| testSubFolder.create(true, true, getMonitor()); |
| |
| history= OperationHistoryFactory.getOperationHistory(); |
| context= RefactoringCorePlugin.getUndoContext(); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| fProject.delete(); |
| final IFileStore[] toDelete= storesToDelete.toArray(new IFileStore[storesToDelete.size()]); |
| storesToDelete.clear(); |
| for (int i= 0; i < toDelete.length; i++) { |
| clear(toDelete[i]); |
| } |
| } |
| |
| |
| public void testFileRenameUndoRedoLTK() throws ExecutionException, CoreException { |
| RefactoringContribution renameContribution= RefactoringCore.getRefactoringContribution(RenameResourceDescriptor.ID); |
| RenameResourceDescriptor desc= (RenameResourceDescriptor) renameContribution.createDescriptor(); |
| desc.setResourcePath(testFile.getFullPath()); |
| desc.setNewName(TEST_NEWFILE_NAME); |
| PerformRefactoringOperation op= new PerformRefactoringOperation(desc.createRefactoringContext(new RefactoringStatus()), CheckConditionsOperation.ALL_CONDITIONS); |
| |
| FileSnapshot snap= new FileSnapshot(testFile); |
| execute(op); |
| |
| IFile renamedFile= testFolder.getFile(TEST_NEWFILE_NAME); |
| assertTrue("File rename failed", renamedFile.exists()); |
| snap.name= TEST_NEWFILE_NAME; |
| assertTrue("File CONTENT was altered on rename", snap.isValid(testFolder)); |
| |
| undo(); |
| snap.name= TEST_FILE_NAME; |
| assertTrue("File CONTENT was altered on undo rename", snap.isValid(testFolder)); |
| assertFalse("Undo rename failed", renamedFile.exists()); |
| |
| redo(); |
| snap.name= TEST_NEWFILE_NAME; |
| assertTrue("File CONTENT was altered on redo rename", snap.isValid(testFolder)); |
| } |
| |
| public void testFolderRenameUndoRedoLTK() throws ExecutionException, CoreException { |
| RefactoringContribution renameContribution= RefactoringCore.getRefactoringContribution(RenameResourceDescriptor.ID); |
| RenameResourceDescriptor desc= (RenameResourceDescriptor) renameContribution.createDescriptor(); |
| desc.setResourcePath(testFolder.getFullPath()); |
| desc.setNewName(TEST_NEWFOLDER_NAME); |
| PerformRefactoringOperation op= new PerformRefactoringOperation(desc.createRefactoringContext(new RefactoringStatus()), CheckConditionsOperation.ALL_CONDITIONS); |
| |
| FolderSnapshot snap= new FolderSnapshot(testFolder); |
| execute(op); |
| IFolder renamedFolder= fProject.getProject().getFolder(TEST_NEWFOLDER_NAME); |
| assertTrue("Project rename failed", renamedFolder.exists()); |
| snap.name= TEST_NEWFOLDER_NAME; |
| assertTrue("Folder CONTENT was altered on rename", snap.isValid(fProject.getProject())); |
| |
| undo(); |
| snap.name= TEST_FOLDER_NAME; |
| assertTrue("Folder CONTENT was altered on undo rename", snap.isValid(fProject.getProject())); |
| assertFalse("Undo rename failed", renamedFolder.exists()); |
| |
| redo(); |
| snap.name= TEST_NEWFOLDER_NAME; |
| assertTrue("Folder CONTENT was altered on redo rename", snap.isValid(fProject.getProject())); |
| } |
| |
| public void testProjectRenameUndoRedoLTK() throws ExecutionException, CoreException { |
| IProject renamedProject= null; |
| try { |
| RefactoringContribution renameContribution= RefactoringCore.getRefactoringContribution(RenameResourceDescriptor.ID); |
| RenameResourceDescriptor desc= (RenameResourceDescriptor) renameContribution.createDescriptor(); |
| desc.setResourcePath(fProject.getProject().getFullPath()); |
| desc.setNewName(TEST_NEWPROJECT_NAME); |
| PerformRefactoringOperation op= new PerformRefactoringOperation(desc.createRefactoringContext(new RefactoringStatus()), CheckConditionsOperation.ALL_CONDITIONS); |
| |
| ProjectSnapshot snap= new ProjectSnapshot(fProject.getProject()); |
| execute(op); |
| renamedProject= getWorkspaceRoot().getProject(TEST_NEWPROJECT_NAME); |
| assertTrue("Project rename failed", renamedProject.exists()); |
| snap.name= TEST_NEWPROJECT_NAME; |
| assertTrue("Project CONTENT was altered on rename", snap.isValid()); |
| undo(); |
| snap.name= SimpleTestProject.TEST_PROJECT_NAME; |
| assertTrue("Project CONTENT was altered on undo rename", snap.isValid()); |
| assertFalse("Undo rename failed", renamedProject.exists()); |
| redo(); |
| snap.name= TEST_NEWPROJECT_NAME; |
| assertTrue("Project CONTENT was altered on redo rename", snap.isValid()); |
| } finally { |
| renamedProject.delete(true, true, null); |
| } |
| } |
| |
| public void testFileDeleteUndoRedoLTK() throws ExecutionException, CoreException { |
| RefactoringContribution renameContribution= RefactoringCore.getRefactoringContribution(DeleteResourcesDescriptor.ID); |
| DeleteResourcesDescriptor desc= (DeleteResourcesDescriptor) renameContribution.createDescriptor(); |
| desc.setResourcePaths(new IPath[] { testFile.getFullPath() }); |
| |
| PerformRefactoringOperation op= new PerformRefactoringOperation(desc.createRefactoringContext(new RefactoringStatus()), CheckConditionsOperation.ALL_CONDITIONS); |
| |
| FileSnapshot snap= new FileSnapshot(testFile); |
| |
| execute(op); |
| |
| assertFalse("File delete failed", testFile.exists()); |
| undo(); |
| assertTrue("File recreation failed", testFile.exists()); |
| assertTrue("File CONTENT was altered on undo", snap.isValid(testFile.getParent())); |
| redo(); |
| assertFalse("Redo delete failed", testFile.exists()); |
| } |
| |
| public void testFileLinkedDeleteUndoRedoLTK() throws ExecutionException, CoreException { |
| RefactoringContribution renameContribution= RefactoringCore.getRefactoringContribution(DeleteResourcesDescriptor.ID); |
| DeleteResourcesDescriptor desc= (DeleteResourcesDescriptor) renameContribution.createDescriptor(); |
| desc.setResourcePaths(new IPath[] { testLinkedFile.getFullPath() }); |
| |
| PerformRefactoringOperation op= new PerformRefactoringOperation(desc.createRefactoringContext(new RefactoringStatus()), CheckConditionsOperation.ALL_CONDITIONS); |
| |
| FileSnapshot snap= new FileSnapshot(testLinkedFile); |
| |
| execute(op); |
| |
| assertFalse("File delete failed", testLinkedFile.exists()); |
| undo(); |
| assertTrue("File recreation failed", testLinkedFile.exists()); |
| assertTrue("File CONTENT was altered on undo", snap.isValid(testLinkedFile.getParent())); |
| redo(); |
| assertFalse("Redo delete failed", testLinkedFile.exists()); |
| } |
| |
| public void testFolderDeleteUndoRedoLTK() throws ExecutionException, CoreException { |
| RefactoringContribution renameContribution= RefactoringCore.getRefactoringContribution(DeleteResourcesDescriptor.ID); |
| DeleteResourcesDescriptor desc= (DeleteResourcesDescriptor) renameContribution.createDescriptor(); |
| desc.setResourcePaths(new IPath[] { testSubFolder.getFullPath() }); |
| |
| PerformRefactoringOperation op= new PerformRefactoringOperation(desc.createRefactoringContext(new RefactoringStatus()), CheckConditionsOperation.ALL_CONDITIONS); |
| |
| FolderSnapshot snap= new FolderSnapshot(testSubFolder); |
| |
| execute(op); |
| |
| assertFalse("Folder delete failed", testSubFolder.exists()); |
| undo(); |
| assertTrue("Folder recreation failed", testSubFolder.exists()); |
| assertTrue("Folder CONTENT was altered on undo", snap.isValid(testSubFolder.getParent())); |
| redo(); |
| assertFalse("Redo delete failed", testSubFolder.exists()); |
| } |
| |
| public void testFolderDeleteLinkedUndoRedoLTK() throws ExecutionException, CoreException { |
| RefactoringContribution renameContribution= RefactoringCore.getRefactoringContribution(DeleteResourcesDescriptor.ID); |
| DeleteResourcesDescriptor desc= (DeleteResourcesDescriptor) renameContribution.createDescriptor(); |
| desc.setResourcePaths(new IPath[] { testLinkedFolder.getFullPath() }); |
| |
| PerformRefactoringOperation op= new PerformRefactoringOperation(desc.createRefactoringContext(new RefactoringStatus()), CheckConditionsOperation.ALL_CONDITIONS); |
| |
| FolderSnapshot snap= new FolderSnapshot(testLinkedFolder); |
| execute(op); |
| assertFalse("Folder delete failed", testLinkedFolder.exists()); |
| undo(); |
| assertTrue("Folder recreation failed", testLinkedFolder.exists()); |
| assertTrue("Folder CONTENT was altered on undo", snap.isValid(testLinkedFolder.getParent())); |
| redo(); |
| assertFalse("Redo delete failed", testLinkedFolder.exists()); |
| } |
| |
| public void testFolderDeleteLinkedDeletedOnFilesystemUndoRedoLTK() throws ExecutionException, CoreException { |
| RefactoringContribution deleteContribution= RefactoringCore.getRefactoringContribution(DeleteResourcesDescriptor.ID); |
| DeleteResourcesDescriptor desc= (DeleteResourcesDescriptor) deleteContribution.createDescriptor(); |
| desc.setResourcePaths(new IPath[] { testLinkedFolder.getFullPath() }); |
| |
| PerformRefactoringOperation op= new PerformRefactoringOperation( |
| desc.createRefactoringContext(new RefactoringStatus()), |
| CheckConditionsOperation.ALL_CONDITIONS); |
| |
| FolderSnapshot snap= new FolderSnapshot(testLinkedFolder); |
| |
| // Create a subfolder containing a file under the linked folder. |
| IFolder subfolder= testLinkedFolder.getFolder("A"); |
| subfolder.create(true, true, getMonitor()); |
| IFile file= subfolder.getFile("test.txt"); |
| file.create(new ByteArrayInputStream("test contents".getBytes(StandardCharsets.UTF_8)), true, getMonitor()); |
| // Delete the target of the linked folder on the file system making the linked folder out of sync |
| // with the file system. |
| IFileStore folderStore= EFS.getStore(testLinkedFolder.getLocationURI()); |
| folderStore.delete(EFS.NONE, getMonitor()); // Delete the target folder on the file system. |
| |
| execute(op); |
| assertFalse("Folder delete failed", testLinkedFolder.exists()); |
| undo(); |
| assertTrue("Folder recreation failed", testLinkedFolder.exists()); |
| assertTrue("Folder CONTENT was altered on undo", snap.isValid(testLinkedFolder.getParent())); |
| redo(); |
| assertFalse("Redo delete failed", testLinkedFolder.exists()); |
| } |
| |
| public void testProjectDeleteUndoRedoLTK() throws ExecutionException, CoreException { |
| RefactoringContribution renameContribution= RefactoringCore.getRefactoringContribution(DeleteResourcesDescriptor.ID); |
| DeleteResourcesDescriptor desc= (DeleteResourcesDescriptor) renameContribution.createDescriptor(); |
| desc.setResourcePaths(new IPath[] { fProject.getProject().getFullPath() }); |
| |
| PerformRefactoringOperation op= new PerformRefactoringOperation(desc.createRefactoringContext(new RefactoringStatus()), CheckConditionsOperation.ALL_CONDITIONS); |
| |
| execute(op); |
| assertFalse("Project delete failed", fProject.getProject().exists()); |
| undo(); |
| assertTrue("Project recreation failed", fProject.getProject().exists()); |
| // Ideally we could run this test everytime, but it fails intermittently |
| // because opening the recreated project occurs in the background, and |
| // the creation of the workspace representation for the disk contents |
| // may not have happened yet. This test always passes under debug where |
| // timing can be controlled. |
| // *********** |
| // assertTrue("Project CONTENT was altered on undo", snap.isValid()); |
| // ************ |
| redo(); |
| assertFalse("Redo delete failed", fProject.getProject().exists()); |
| // We undo again so that the project will exist during teardown and |
| // get cleaned up. Otherwise some CONTENT is left on disk. |
| undo(); |
| } |
| |
| public void testProjectClosedDeleteUndoRedoLTK() throws ExecutionException, CoreException { |
| fProject.getProject().close(getMonitor()); |
| testProjectDeleteUndoRedoLTK(); |
| } |
| |
| public void testProjectDeleteWithContentUndoRedoLTK() throws ExecutionException, CoreException { |
| RefactoringContribution renameContribution= RefactoringCore.getRefactoringContribution(DeleteResourcesDescriptor.ID); |
| DeleteResourcesDescriptor desc= (DeleteResourcesDescriptor) renameContribution.createDescriptor(); |
| desc.setResourcePaths(new IPath[] { fProject.getProject().getFullPath() }); |
| desc.setDeleteContents(true); |
| |
| PerformRefactoringOperation op= new PerformRefactoringOperation(desc.createRefactoringContext(new RefactoringStatus()), CheckConditionsOperation.ALL_CONDITIONS); |
| |
| // we don't snapshot since CONTENT will be deleted |
| execute(op); |
| assertFalse("Project delete failed", fProject.getProject().exists()); |
| undo(); |
| assertTrue("Project was recreated", fProject.getProject().exists()); |
| redo(); |
| assertFalse("Redo delete failed", fProject.getProject().exists()); |
| } |
| |
| public void testProjectClosedDeleteWithContentUndoRedoLTK() throws ExecutionException, CoreException { |
| fProject.getProject().close(getMonitor()); |
| testProjectDeleteWithContentUndoRedoLTK(); |
| } |
| |
| public void testPreChangeUndoRedoLTK() throws ExecutionException, CoreException { |
| Refactoring ref= new ElementRenameRefactoring(ElementRenameRefactoring.WORKING | ElementRenameRefactoring.ALWAYS_ENABLED | ElementRenameRefactoring.PRE_CHANGE); |
| |
| PerformRefactoringOperation op= new PerformRefactoringOperation(ref, CheckConditionsOperation.ALL_CONDITIONS); |
| |
| execute(op); |
| |
| List<String> h= ElementRenameProcessor.fHistory; |
| // Strictly speaking, the execution of these things does not need to be in exactly this |
| // order, but it's an easy way to check. Of course there are some dependencies on the |
| // order (participant-pre-exec, main-exec, participant-exec) |
| int i= 0; |
| assertEquals(ElementRenameProcessor.MAIN_CREATE, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKING_CREATE, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKINGPRE_CREATEPRE, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKINGPRE_CREATE, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKINGPRE_EXECPRE, h.get(i++)); |
| assertEquals(ElementRenameProcessor.MAIN_EXEC, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKING_EXEC, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKINGPRE_EXEC, h.get(i++)); |
| |
| undo(); |
| assertEquals(ElementRenameProcessor.WORKINGPRE_EXEC_UNDO, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKING_EXEC_UNDO, h.get(i++)); |
| assertEquals(ElementRenameProcessor.MAIN_EXEC_UNDO, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKINGPRE_EXECPRE_UNDO, h.get(i++)); |
| |
| redo(); |
| assertEquals(ElementRenameProcessor.WORKINGPRE_EXECPRE, h.get(i++)); |
| assertEquals(ElementRenameProcessor.MAIN_EXEC, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKING_EXEC, h.get(i++)); |
| assertEquals(ElementRenameProcessor.WORKINGPRE_EXEC, h.get(i++)); |
| } |
| |
| private void execute(PerformRefactoringOperation op) throws CoreException { |
| ResourcesPlugin.getWorkspace().run(op, getMonitor()); |
| } |
| |
| private IWorkspaceRoot getWorkspaceRoot() { |
| return ResourcesPlugin.getWorkspace().getRoot(); |
| } |
| |
| private void undo() throws ExecutionException { |
| assertTrue("Operation can be undone", history.canUndo(context)); |
| IStatus status= history.undo(context, getMonitor(), null); |
| assertTrue("Undo should be OK status", status.isOK()); |
| } |
| |
| private void redo() throws ExecutionException { |
| assertTrue("Operation can be redone", history.canRedo(context)); |
| IStatus status= history.redo(context, getMonitor(), null); |
| assertTrue("Redo should be OK status", status.isOK()); |
| } |
| |
| private IProgressMonitor getMonitor() { |
| return null; |
| } |
| |
| private ResourceSnapshot snapshotFromResource(IResource resource) throws CoreException { |
| if (resource instanceof IFile) |
| return new FileSnapshot((IFile) resource); |
| if (resource instanceof IFolder) |
| return new FolderSnapshot((IFolder) resource); |
| if (resource instanceof IProject) |
| return new ProjectSnapshot((IProject) resource); |
| fail("Unknown resource type"); |
| // making compiler happy |
| return new FileSnapshot((IFile) resource); |
| } |
| |
| /* |
| * reads testFile CONTENT and returns string |
| */ |
| private String readContent(IFile file) throws CoreException { |
| InputStream is= file.getContents(); |
| String encoding= file.getCharset(); |
| if (is == null) |
| return null; |
| try (BufferedReader reader= new BufferedReader(new InputStreamReader(is, encoding))) { |
| StringBuffer buffer= new StringBuffer(); |
| char[] part= new char[2048]; |
| int read= 0; |
| |
| while ((read= reader.read(part)) != -1) |
| buffer.append(part, 0, read); |
| |
| return buffer.toString(); |
| |
| } catch (IOException ex) { |
| throw new CoreException(new Status(IStatus.ERROR, RefactoringCoreTestPlugin.getPluginId(), ex.getMessage())); |
| } |
| } |
| |
| /** |
| * Returns a FileStore instance backed by storage in a temporary location. The returned store |
| * will not exist, but will belong to an existing parent. The tearDown method in this class will |
| * ensure the location is deleted after the test is completed. |
| * |
| * @return The temp filestore to use |
| */ |
| private IFileStore getTempStore() { |
| IFileStore store= EFS.getLocalFileSystem().getStore(FileSystemHelper.getRandomLocation(FileSystemHelper.getTempDir())); |
| storesToDelete.add(store); |
| return store; |
| } |
| |
| private void clear(IFileStore store) { |
| try { |
| store.delete(EFS.NONE, null); |
| } catch (CoreException e) { |
| } |
| } |
| |
| class FileSnapshot extends ResourceSnapshot { |
| String content; |
| |
| URI location; |
| |
| MarkerSnapshot[] markerSnapshots; |
| |
| FileSnapshot(IFile file) throws CoreException { |
| content= readContent(file); |
| name= file.getName(); |
| if (file.isLinked()) { |
| location= file.getLocationURI(); |
| } |
| IMarker[] markers= file.findMarkers(null, true, IResource.DEPTH_INFINITE); |
| markerSnapshots= new MarkerSnapshot[markers.length]; |
| for (int i= 0; i < markers.length; i++) { |
| markerSnapshots[i]= new MarkerSnapshot(markers[i]); |
| } |
| } |
| |
| @Override |
| boolean isValid(IResource parent) throws CoreException { |
| IResource resource= getWorkspaceRoot().findMember(parent.getFullPath().append(name)); |
| if (resource == null || !(resource instanceof IFile)) { |
| return false; |
| } |
| IFile file= (IFile) resource; |
| boolean contentMatch= readContent(file).equals(content); |
| if (file.isLinked()) { |
| contentMatch= contentMatch && file.getLocationURI().equals(location); |
| } |
| if (!contentMatch) { |
| return false; |
| } |
| for (int i= 0; i < markerSnapshots.length; i++) { |
| if (!markerSnapshots[i].existsOn(resource)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| } |
| |
| class FolderSnapshot extends ResourceSnapshot { |
| URI location; |
| |
| ResourceSnapshot[] memberSnapshots; |
| |
| FolderSnapshot(IFolder folder) throws CoreException { |
| name= folder.getName(); |
| if (folder.isLinked()) { |
| location= folder.getLocationURI(); |
| } |
| IResource[] members= folder.members(); |
| memberSnapshots= new ResourceSnapshot[members.length]; |
| for (int i= 0; i < members.length; i++) { |
| memberSnapshots[i]= snapshotFromResource(members[i]); |
| } |
| } |
| |
| @Override |
| boolean isValid(IResource parent) throws CoreException { |
| IResource resource= getWorkspaceRoot().findMember(parent.getFullPath().append(name)); |
| if (resource == null || !(resource instanceof IFolder)) { |
| return false; |
| } |
| IFolder folder= (IFolder) resource; |
| if (folder.isLinked()) { |
| if (!folder.getLocationURI().equals(location)) { |
| return false; |
| } |
| } |
| for (int i= 0; i < memberSnapshots.length; i++) { |
| if (!fileNameExcludes.contains(memberSnapshots[i].name)) { |
| if (!memberSnapshots[i].isValid(folder)) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| } |
| |
| class MarkerSnapshot { |
| String type; |
| |
| Map<String, Object> attributes; |
| |
| MarkerSnapshot(IMarker marker) throws CoreException { |
| type= marker.getType(); |
| attributes= marker.getAttributes(); |
| } |
| |
| boolean existsOn(IResource resource) throws CoreException { |
| // comparison is based on equality of attributes, since id will |
| // change on create/delete/recreate sequence |
| IMarker[] markers= resource.findMarkers(type, false, IResource.DEPTH_ZERO); |
| for (int i= 0; i < markers.length; i++) { |
| if (markers[i].getAttributes().equals(attributes)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |
| |
| class ProjectSnapshot extends ResourceSnapshot { |
| ResourceSnapshot[] memberSnapshots; |
| |
| ProjectSnapshot(IProject project) throws CoreException { |
| name= project.getName(); |
| boolean open= project.isOpen(); |
| if (!open) { |
| project.open(null); |
| } |
| IResource[] members= project.members(); |
| memberSnapshots= new ResourceSnapshot[members.length]; |
| for (int i= 0; i < members.length; i++) { |
| memberSnapshots[i]= snapshotFromResource(members[i]); |
| } |
| if (!open) { |
| project.close(null); |
| } |
| |
| } |
| |
| @Override |
| boolean isValid(IResource parent) throws CoreException { |
| IResource resource= getWorkspaceRoot().findMember(parent.getFullPath().append(name)); |
| if (resource == null || !(resource instanceof IProject)) { |
| return false; |
| } |
| IProject project= (IProject) resource; |
| // Must open it to validate the CONTENT |
| boolean open= project.isOpen(); |
| if (!open) { |
| project.open(null); |
| } |
| |
| for (int i= 0; i < memberSnapshots.length; i++) { |
| if (!fileNameExcludes.contains(memberSnapshots[i].name)) { |
| if (!memberSnapshots[i].isValid(resource)) { |
| return false; |
| } |
| } |
| } |
| |
| if (!open) { |
| project.close(null); |
| } |
| |
| return true; |
| } |
| |
| boolean isValid() throws CoreException { |
| return isValid(getWorkspaceRoot()); |
| } |
| } |
| |
| abstract class ResourceSnapshot { |
| String name; |
| |
| abstract boolean isValid(IResource parent) throws CoreException; |
| |
| IWorkspaceRoot getWorkspaceRoot() { |
| return ResourcesPlugin.getWorkspace().getRoot(); |
| } |
| } |
| } |