From 3c93caf4c92ac214e6023dd4c39aea37b9a9c7cc Mon Sep 17 00:00:00 2001 From: Mikhail Sennikovsky Date: Wed, 6 Jul 2005 17:56:13 +0000 Subject: [PATCH] Checked in the resouece renaming/deletion handling for MBS. When the resouece is either renamed ore deleted, the project ResourceConfiguration data is updated now. Also checked in the test for verification resouece renaming/deletion handling. --- .../core/tests/ResourceBuildCoreTests.java | 215 ++++++++- .../core/ManagedBuildManager.java | 2 +- .../core/ManagedBuilderCorePlugin.java | 26 +- .../internal/core/Configuration.java | 3 +- .../internal/core/PluginResources.properties | 3 +- .../internal/core/ResourceChangeHandler.java | 431 ++++++++++++++++++ 6 files changed, 660 insertions(+), 20 deletions(-) create mode 100644 build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ResourceChangeHandler.java diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ResourceBuildCoreTests.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ResourceBuildCoreTests.java index 651b11a09c5..12d2b8319d4 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ResourceBuildCoreTests.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ResourceBuildCoreTests.java @@ -11,6 +11,7 @@ package org.eclipse.cdt.managedbuilder.core.tests; import java.io.ByteArrayInputStream; +import java.util.HashMap; import junit.framework.Test; import junit.framework.TestCase; @@ -19,19 +20,20 @@ import junit.framework.TestSuite; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.make.core.MakeCorePlugin; import org.eclipse.cdt.managedbuilder.core.BuildException; -import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; -import org.eclipse.cdt.managedbuilder.core.IProjectType; -import org.eclipse.cdt.managedbuilder.core.IManagedProject; import org.eclipse.cdt.managedbuilder.core.IConfiguration; -import org.eclipse.cdt.managedbuilder.core.IResourceConfiguration; -import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.IManagedProject; import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.IOptionCategory; +import org.eclipse.cdt.managedbuilder.core.IProjectType; +import org.eclipse.cdt.managedbuilder.core.IResourceConfiguration; +import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedCProjectNature; import org.eclipse.cdt.managedbuilder.internal.core.Tool; import org.eclipse.cdt.managedbuilder.testplugin.ManagedBuildTestHelper; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; @@ -44,6 +46,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.jobs.ISchedulingRule; public class ResourceBuildCoreTests extends TestCase { @@ -54,8 +57,8 @@ public class ResourceBuildCoreTests extends TestCase { private static final String projectName = "T1"; - - + private static final String renamedProjectName1 = "T1_1"; + private static final String renamedProjectName2 = "T1_2"; public ResourceBuildCoreTests(String name) { super(name); @@ -66,6 +69,7 @@ public class ResourceBuildCoreTests extends TestCase { suite.addTest(new ResourceBuildCoreTests("testResourceConfigurations")); suite.addTest(new ResourceBuildCoreTests("testResourceConfigurationReset")); suite.addTest(new ResourceBuildCoreTests("testResourceConfigurationBuildInfo")); + suite.addTest(new ResourceBuildCoreTests("testResourceRename")); return suite; } @@ -721,4 +725,201 @@ public class ResourceBuildCoreTests extends TestCase { ManagedBuildManager.removeBuildInfo(project); } + public void testResourceRename() throws Exception { + // Create a new project + IProject project = null; + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + + try { + project = createProject(projectName); + + // Now associate the builder with the project + ManagedBuildTestHelper.addManagedBuildNature(project); + IProjectDescription description = project.getDescription(); + // Make sure it has a managed nature + if (description != null) { + assertTrue(description.hasNature(ManagedCProjectNature.MNG_NATURE_ID)); + } + + } catch (CoreException e) { + fail("Test failed on project creation: " + e.getLocalizedMessage()); + } + + // Find the base project type definition + IProjectType[] projTypes = ManagedBuildManager.getDefinedProjectTypes(); + IProjectType projType = ManagedBuildManager.getProjectType("cdt.managedbuild.target.testgnu21.exe"); + assertNotNull(projType); + + // Create the managed-project (.cdtbuild) for our project that builds an executable. + IManagedProject newProject = ManagedBuildManager.createManagedProject(project, projType); + assertEquals(newProject.getName(), projType.getName()); + assertFalse(newProject.equals(projType)); + ManagedBuildManager.setNewProjectVersion(project); + + // Create a couple of resources ( 'main.c' & 'bar.c') + IFile mainFile = project.getProject().getFile( "main.c" ); + if( !mainFile.exists() ){ + mainFile.create( new ByteArrayInputStream( "#include \n extern void bar(); \n int main() { \nprintf(\"Hello, World!!\"); \n bar();\n return 0; }".getBytes() ), false, null ); + } + + IFile aFile = project.getProject().getFile( "a.c" ); + if( !aFile.exists() ){ + aFile.create( new ByteArrayInputStream( "#include \n void bar() { \nprintf(\"Hello, bar()!!\");\n return; }".getBytes() ), false, null ); + } + + IFolder dirFolder = project.getProject().getFolder( "dir" ); + if(!dirFolder.exists()) + dirFolder.create(true,true,null); + IFile bFile = dirFolder.getFile( "b.c" ); + if( !bFile.exists() ){ + bFile.create( new ByteArrayInputStream( "#include \n void bar1() { \nprintf(\"Hello, bar1()!!\");\n return; }".getBytes() ), false, null ); + } + + // Get the configurations and make one of them as default configuration. + IConfiguration defaultConfig = null; + IConfiguration[] configs = projType.getConfigurations(); + for (int i = 0; i < configs.length; ++i) { + // Make the first configuration the default + if (i == 0) { + defaultConfig = newProject.createConfiguration(configs[i], projType.getId() + "." + i); + } else { + newProject.createConfiguration(configs[i], projType.getId() + "." + i); + } + } + ManagedBuildManager.setDefaultConfiguration(project, defaultConfig); + + // Create Resource Configurations for files main.c and bar.c + IResourceConfiguration resMainConfig = defaultConfig.createResourceConfiguration(mainFile); + IResourceConfiguration resAConfig = defaultConfig.createResourceConfiguration(aFile); + IResourceConfiguration resBConfig = defaultConfig.createResourceConfiguration(bFile); + + // Check whether defaultConfig has three resource configurations or not. + IResourceConfiguration resConfigs[] = defaultConfig.getResourceConfigurations(); + assertEquals(resMainConfig,defaultConfig.getResourceConfiguration(mainFile.getFullPath().toString())); + assertEquals(resAConfig,defaultConfig.getResourceConfiguration(aFile.getFullPath().toString())); + assertEquals(resBConfig,defaultConfig.getResourceConfiguration(bFile.getFullPath().toString())); + assertEquals(3,resConfigs.length); + + + mainFile.move(mainFile.getFullPath().removeLastSegments(1).append("main1.c"),true,false,null); + mainFile = (IFile)project.findMember("main1.c"); + assertEquals(resMainConfig,defaultConfig.getResourceConfiguration(mainFile.getFullPath().toString())); + assertEquals(resAConfig,defaultConfig.getResourceConfiguration(aFile.getFullPath().toString())); + assertEquals(resBConfig,defaultConfig.getResourceConfiguration(bFile.getFullPath().toString())); + resConfigs = defaultConfig.getResourceConfigurations(); + assertEquals(3,resConfigs.length); + + dirFolder.move(dirFolder.getFullPath().removeLastSegments(1).append("dir1"),true,false,null); + dirFolder = (IFolder)project.findMember("dir1"); + bFile = (IFile)dirFolder.findMember("b.c"); + assertEquals(resMainConfig,defaultConfig.getResourceConfiguration(mainFile.getFullPath().toString())); + assertEquals(resAConfig,defaultConfig.getResourceConfiguration(aFile.getFullPath().toString())); + assertEquals(resBConfig,defaultConfig.getResourceConfiguration(bFile.getFullPath().toString())); + resConfigs = defaultConfig.getResourceConfigurations(); + assertEquals(3,resConfigs.length); + + bFile.move(bFile.getFullPath().removeLastSegments(1).append("b1.c"),true,false,null); + bFile = (IFile)dirFolder.findMember("b1.c"); + assertEquals(resMainConfig,defaultConfig.getResourceConfiguration(mainFile.getFullPath().toString())); + assertEquals(resAConfig,defaultConfig.getResourceConfiguration(aFile.getFullPath().toString())); + assertEquals(resBConfig,defaultConfig.getResourceConfiguration(bFile.getFullPath().toString())); + resConfigs = defaultConfig.getResourceConfigurations(); + assertEquals(3,resConfigs.length); + + IProjectDescription des = project.getDescription(); + des.setName(renamedProjectName1); + project.move(des,true,null); + project = (IProject)root.findMember(renamedProjectName1); + mainFile = (IFile)project.findMember("main1.c"); + aFile = (IFile)project.findMember("a.c"); + dirFolder = (IFolder)project.findMember("dir1"); + bFile = (IFile)dirFolder.findMember("b1.c"); + assertEquals(resMainConfig,defaultConfig.getResourceConfiguration(mainFile.getFullPath().toString())); + assertEquals(resAConfig,defaultConfig.getResourceConfiguration(aFile.getFullPath().toString())); + assertEquals(resBConfig,defaultConfig.getResourceConfiguration(bFile.getFullPath().toString())); + resConfigs = defaultConfig.getResourceConfigurations(); + assertEquals(3,resConfigs.length); + + final IResource rcBuf[] = new IResource[5]; + rcBuf[0] = project; + rcBuf[1] = mainFile; + rcBuf[2] = aFile; + rcBuf[3] = dirFolder; + rcBuf[4] = bFile; + + ResourcesPlugin.getWorkspace().run( new IWorkspaceRunnable(){ + + public void run(IProgressMonitor monitor) throws CoreException { + IProject project = (IProject)rcBuf[0]; + IFile mainFile = (IFile)rcBuf[1]; + IFile aFile = (IFile)rcBuf[2]; + IFolder dirFolder = (IFolder)rcBuf[3]; + IFile bFile = (IFile)rcBuf[4]; + // TODO Auto-generated method stub + mainFile.move(mainFile.getFullPath().removeLastSegments(1).append("main2.c"),true,false,null); + mainFile = (IFile)project.findMember("main2.c"); + + dirFolder.move(dirFolder.getFullPath().removeLastSegments(1).append("dir2"),true,false,null); + dirFolder = (IFolder)project.findMember("dir2"); + bFile = (IFile)dirFolder.findMember("b1.c"); + + bFile.move(bFile.getFullPath().removeLastSegments(1).append("b2.c"),true,false,null); + bFile = (IFile)dirFolder.findMember("b2.c"); + +// project.move(project.getFullPath().removeLastSegments(1).append(renamedProjectName2),true,null); + IProjectDescription des = project.getDescription(); + des.setName(renamedProjectName2); + project.move(des,true,null); + project = (IProject)ResourcesPlugin.getWorkspace().getRoot().findMember(renamedProjectName2); + + mainFile = (IFile)project.findMember("main2.c"); + aFile = (IFile)project.findMember("a.c"); + dirFolder = (IFolder)project.findMember("dir2"); + bFile = (IFile)dirFolder.findMember("b2.c"); + + rcBuf[0] = project; + rcBuf[1] = mainFile; + rcBuf[2] = aFile; + rcBuf[3] = dirFolder; + rcBuf[4] = bFile; + } + + }, + root, + IWorkspace.AVOID_UPDATE, + null); + + project = (IProject)rcBuf[0]; + mainFile = (IFile)rcBuf[1]; + aFile = (IFile)rcBuf[2]; + dirFolder = (IFolder)rcBuf[3]; + bFile = (IFile)rcBuf[4]; + + assertEquals(resMainConfig,defaultConfig.getResourceConfiguration(mainFile.getFullPath().toString())); + assertEquals(resAConfig,defaultConfig.getResourceConfiguration(aFile.getFullPath().toString())); + assertEquals(resBConfig,defaultConfig.getResourceConfiguration(bFile.getFullPath().toString())); + resConfigs = defaultConfig.getResourceConfigurations(); + assertEquals(3,resConfigs.length); + + aFile.delete(true,null); + // Check whether defaultConfig has two resource configurations or not. + assertEquals(resMainConfig,defaultConfig.getResourceConfiguration(mainFile.getFullPath().toString())); + assertEquals(null,defaultConfig.getResourceConfiguration(aFile.getFullPath().toString())); + assertEquals(resBConfig,defaultConfig.getResourceConfiguration(bFile.getFullPath().toString())); + resConfigs = defaultConfig.getResourceConfigurations(); + assertEquals(2,resConfigs.length); + + dirFolder.delete(true, null); + // Check whether defaultConfig has one resource configuration or not. + assertEquals(resMainConfig,defaultConfig.getResourceConfiguration(mainFile.getFullPath().toString())); + assertEquals(null,defaultConfig.getResourceConfiguration(aFile.getFullPath().toString())); + assertEquals(null,defaultConfig.getResourceConfiguration(bFile.getFullPath().toString())); + resConfigs = defaultConfig.getResourceConfigurations(); + assertEquals(1,resConfigs.length); + + // Close and remove project. + project.close(null); + removeProject(renamedProjectName2); + } + } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java index 3e1877f3b5f..c27d2405b20 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java @@ -2133,7 +2133,7 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI jobManager.endRule(rule); } - if (!buildInfo.isContainerInited()) { + if (buildInfo != null && !buildInfo.isContainerInited()) { // NOTE: If this is called inside the above rule, then an IllegalArgumentException can // occur when the CDT project file is saved - it uses the Workspace Root as the scheduling rule. // diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuilderCorePlugin.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuilderCorePlugin.java index 7654d771d67..4ae7b625384 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuilderCorePlugin.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuilderCorePlugin.java @@ -11,8 +11,12 @@ package org.eclipse.cdt.managedbuilder.core; import org.eclipse.cdt.managedbuilder.internal.core.GeneratedMakefileBuilder; +import org.eclipse.cdt.managedbuilder.internal.core.ResourceChangeHandler; import org.eclipse.cdt.managedbuilder.internal.scannerconfig.ManagedBuildCPathEntryContainer; import org.eclipse.cdt.managedbuilder.internal.scannerconfig.ManagedBuildPathEntryContainerInitializer; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.ISavedState; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; import org.osgi.framework.BundleContext; @@ -35,7 +39,7 @@ public class ManagedBuilderCorePlugin extends Plugin { // NOTE: The code below is for tracking resource renaming and deleting. This is needed to keep // ResourceConfiguration elements up to date. It may also be needed by AdditionalInput // elements - //private static ResourceChangeHandler listener; + private static ResourceChangeHandler listener; /** * @param descriptor @@ -75,14 +79,14 @@ public class ManagedBuilderCorePlugin extends Plugin { // elements // Set up a listener for resource change events - //listener = new ResourceChangeHandler(); - //ResourcesPlugin.getWorkspace().addResourceChangeListener( - // listener, IResourceChangeEvent.POST_CHANGE /*| IResourceChangeEvent.POST_BUILD*/); - //ISavedState lastState = - // ResourcesPlugin.getWorkspace().addSaveParticipant(plugin, listener); - //if (lastState != null) { - // lastState.processResourceChangeEvents(listener); - //} + listener = new ResourceChangeHandler(); + ResourcesPlugin.getWorkspace().addResourceChangeListener( + listener, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_DELETE /*| IResourceChangeEvent.POST_BUILD*/); + ISavedState lastState = + ResourcesPlugin.getWorkspace().addSaveParticipant(this, listener); + if (lastState != null) { + lastState.processResourceChangeEvents(listener); + } } @@ -93,7 +97,9 @@ public class ManagedBuilderCorePlugin extends Plugin { // NOTE: The code below is for tracking resource renaming and deleting. This is needed to keep // ResourceConfiguration elements up to date. It may also be needed by AdditionalInput // elements - //ResourcesPlugin.getWorkspace().removeResourceChangeListener(listener); + ResourcesPlugin.getWorkspace().removeResourceChangeListener(listener); + listener = null; + super.stop(context); } private static final String PATH_ENTRY = ManagedBuilderCorePlugin.getUniqueIdentifier() + "/debug/pathEntry"; //$NON-NLS-1$ diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java index 8f1897838a9..08385ddd043 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java @@ -852,7 +852,8 @@ public class Configuration extends BuildObject implements IConfiguration { } public void removeResourceConfiguration(IResourceConfiguration resConfig) { - getResourceConfigurationList().remove((ResourceConfiguration)resConfig); + getResourceConfigurationList().remove(resConfig); + getResourceConfigurationMap().remove(resConfig.getResourcePath()); } /* * M O D E L A T T R I B U T E A C C E S S O R S diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties index b5a4b7ad0d5..af6b240fcb1 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties @@ -100,4 +100,5 @@ BuildMacroStatus.status.macro.not.stringlist=Macro {0} is not of String-list typ BuildMacroStatus.status.error=Error occured BuildMacroStatus.value.undefined= - +#ResourceChangeHandler messages +ResourceChangeHandler.buildInfoSerializationJob=Build Info Serialization diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ResourceChangeHandler.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ResourceChangeHandler.java new file mode 100644 index 00000000000..1be5cc97fbf --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ResourceChangeHandler.java @@ -0,0 +1,431 @@ +/******************************************************************************* + * Copyright (c) 2005 Intel 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: + * Intel Corporation - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.managedbuilder.internal.core; + +import java.util.HashMap; +import java.util.HashSet; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.IManagedProject; +import org.eclipse.cdt.managedbuilder.core.IResourceConfiguration; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; +import org.eclipse.cdt.managedbuilder.core.ManagedCProjectNature; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IResourceRuleFactory; +import org.eclipse.core.resources.ISaveContext; +import org.eclipse.core.resources.ISaveParticipant; +import org.eclipse.core.resources.IWorkspace; +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.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.MultiRule; + +public class ResourceChangeHandler implements IResourceChangeListener, ISaveParticipant { + + private class ResourceConfigurationChecker implements IResourceDeltaVisitor{ + private IResourceDelta fRootDelta; + private HashMap fBuildFileGeneratorMap = new HashMap(); + private HashSet fValidatedFilesSet = new HashSet(); + private HashSet fModifiedProjects = new HashSet(); + + public ResourceConfigurationChecker(IResourceDelta rootDelta){ + fRootDelta = rootDelta; + } + + public IProject[] getModifiedProjects(){ + return (IProject[])fModifiedProjects.toArray(new IProject[fModifiedProjects.size()]); + } + + public boolean visit(IResourceDelta delta) throws CoreException { + IResource dResource = delta.getResource(); + int rcType = dResource.getType(); + + if(rcType == IResource.PROJECT || rcType == IResource.FOLDER){ + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IProject project = null; + IResource rcToCheck = null; + switch (delta.getKind()) { + case IResourceDelta.REMOVED : + if ((delta.getFlags() & IResourceDelta.MOVED_TO) == 0 && rcType == IResource.PROJECT) { + break; + } + case IResourceDelta.CHANGED : + if ((delta.getFlags() & IResourceDelta.MOVED_TO) != 0) { + IPath path = delta.getMovedToPath(); + if(path != null){ + project = root.findMember(path.segment(0)).getProject(); + if(project != null && rcType == IResource.FOLDER) + rcToCheck = root.getFolder(substituteProject(dResource.getFullPath(),project.getName())); + } + break; + } + default: + project = dResource.getProject(); + if(rcType == IResource.FOLDER) + rcToCheck = dResource; + break; + } + + if(project != null) { + IManagedBuilderMakefileGenerator makeGen = getInitializedGenerator(project); + if(makeGen != null){ + if(rcToCheck == null || !makeGen.isGeneratedResource(rcToCheck)) + return true; + } + } + return false; + } else if (rcType == IResource.FILE && !dResource.isDerived()) { + int flags = delta.getFlags(); + switch (delta.getKind()) { + case IResourceDelta.REMOVED : + if ((flags & IResourceDelta.MOVED_TO) == 0) { + handleDeleteFile(dResource.getFullPath()); + break; + } + case IResourceDelta.ADDED : + case IResourceDelta.CHANGED : + if ((flags & IResourceDelta.MOVED_TO) != 0) { + IPath path = delta.getMovedToPath(); + if (path != null) { + handleRenamedFile( + dResource.getFullPath(), + path); + } + } else if ((flags & IResourceDelta.MOVED_FROM) != 0) { + IPath path = delta.getMovedFromPath(); + if (path != null) { + handleRenamedFile( + path, + dResource.getFullPath()); + } + } + break; + + default: + break; + } + return false; + } + return true; // visit the children + } + + private IPath substituteProject(IPath path, String projectName){ + return new Path(projectName).makeAbsolute().append(path.removeFirstSegments(1)); + } + + private void handleRenamedFile(IPath fromPath, IPath toPath){ + if(!fValidatedFilesSet.add(fromPath)) + return; + + IProject fromProject = findModifiedProject(fromPath.segment(0)); + if(fromProject == null) + return; + IManagedBuilderMakefileGenerator fromMakeGen = getInitializedGenerator(fromProject); + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + if(fromMakeGen == null || fromMakeGen.isGeneratedResource(root.getFile(substituteProject(fromPath,fromProject.getName())))) + return; + + IManagedBuildInfo fromInfo = fromProject != null ? + ManagedBuildManager.getBuildInfo(fromProject) : + null; + + IProject toProject = root.findMember(toPath.uptoSegment(1)).getProject(); + IManagedBuildInfo toInfo = toProject != null ? + ManagedBuildManager.getBuildInfo(toProject) : + null; + IManagedBuilderMakefileGenerator toMakeGen = toProject != null ? + getInitializedGenerator(toProject) : + null; + if(toMakeGen != null && toMakeGen.isGeneratedResource(root.getFile(toPath))) + toInfo = null; + + if(fromInfo == toInfo){ + //the resource was moved whithing the project scope + if(updateResourceConfigurations(fromInfo,fromPath,toPath) && toProject != null) + fModifiedProjects.add(toProject); + } else { + if(fromInfo != null && toInfo != null){ + //TODO: this is the case when the resource + //is moved from one managed project to another + //should we handle this? + //e.g. add resource configurations to the destination project? + } + if(fromInfo != null && removeResourceConfigurations(fromInfo,fromPath) && fromProject != null) + fModifiedProjects.add(fromProject); + } + } + + private void handleDeleteFile(IPath path){ + IProject project = findModifiedProject(path.segment(0)); + if(project != null){ + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + if(info != null + && removeResourceConfigurations(info,path)) + fModifiedProjects.add(project); + } + } + + //finds the project geven the initial project name + //That is: + // if the project of a given name was renamed returns the renamed project + // if the project of a given name was removed returns null + // if the project of a given name was neither renamed or removed + // returns the project of that name or null if the project does not exist + // + private IProject findModifiedProject(final String oldProjectName){ + IResourceDelta projectDelta = fRootDelta.findMember(new Path(oldProjectName)); + boolean replaced = false; + if(projectDelta != null) { + switch(projectDelta.getKind()){ + case IResourceDelta.REMOVED : + if ((projectDelta.getFlags() & IResourceDelta.MOVED_TO) == 0) { + return null; + } + case IResourceDelta.CHANGED : + if ((projectDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) { + IPath path = projectDelta.getMovedToPath(); + if(path != null) + return ResourcesPlugin.getWorkspace().getRoot().findMember(path).getProject(); + } + break; + } + } + + final IProject project[] = new IProject[1]; + try { + fRootDelta.accept(new IResourceDeltaVisitor() { + public boolean visit(IResourceDelta delta) throws CoreException { + IResource dResource = delta.getResource(); + int rcType = dResource.getType(); + if(rcType == IResource.ROOT) { + return true; + } else if(rcType == IResource.PROJECT){ + switch(delta.getKind()){ + case IResourceDelta.ADDED : + case IResourceDelta.CHANGED : + if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) { + IPath path = delta.getMovedFromPath(); + if (path != null && path.segment(0).equals(oldProjectName)) { + project[0] = dResource.getProject(); + } + } + break; + default: + break; + } + } + return false; + } + }); + } catch (CoreException e) { + } + + if(project[0] == null && !replaced) + project[0] = ResourcesPlugin.getWorkspace().getRoot().findMember(oldProjectName).getProject(); + return project[0]; + } + + private IManagedBuilderMakefileGenerator getInitializedGenerator(IProject project){ + IManagedBuilderMakefileGenerator makeGen = (IManagedBuilderMakefileGenerator)fBuildFileGeneratorMap.get(project); + if(makeGen == null){ + try{ + if(project.hasNature(ManagedCProjectNature.MNG_NATURE_ID)){ + IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project); + if(buildInfo != null){ + IConfiguration defaultCfg = buildInfo.getDefaultConfiguration(); + if(defaultCfg != null){ + makeGen = ManagedBuildManager.getBuildfileGenerator(defaultCfg); + makeGen.initialize(project,buildInfo,new NullProgressMonitor()); + fBuildFileGeneratorMap.put(project,makeGen); + } + } + } + } catch (CoreException e){ + } + } + return makeGen; + } + } + + /* + * I R e s o u r c e C h a n g e L i s t e n e r + */ + + /* (non-Javadoc) + * + * Handle the renaming and deletion of project resources + * This is necessary in order to update ResourceConfigurations and AdditionalInputs + * + * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) + */ + public void resourceChanged(IResourceChangeEvent event) { + if (event.getSource() instanceof IWorkspace) { + + switch (event.getType()) { + case IResourceChangeEvent.POST_CHANGE : + case IResourceChangeEvent.POST_BUILD : + case IResourceChangeEvent.PRE_DELETE : + IResourceDelta resDelta = event.getDelta(); + if (resDelta == null) { + break; + } + try { + ResourceConfigurationChecker rcChecker = new ResourceConfigurationChecker(resDelta); + resDelta.accept(rcChecker); + + //saving info for the modified projects + initInfoSerialization(rcChecker.getModifiedProjects()); + + } catch (CoreException e) { + CCorePlugin.log(e); + } + break; + default : + break; + } + } + } + + private void initInfoSerialization(final IProject projects[]){ + if(projects.length == 0) + return; + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IResourceRuleFactory ruleFactory = workspace.getRuleFactory(); + ISchedulingRule buildInfoSaveRule; + if(projects.length == 1){ + buildInfoSaveRule = ruleFactory.modifyRule(projects[0]); + } else { + ISchedulingRule rules[] = new ISchedulingRule[projects.length]; + for(int i = 0; i < rules.length; i++) + rules[i] = ruleFactory.modifyRule(projects[i]); + buildInfoSaveRule = MultiRule.combine(rules); + } + + Job savingJob = new Job(ManagedMakeMessages.getResourceString("ResourceChangeHandler.buildInfoSerializationJob")){ //$NON-NLS-1$ + protected IStatus run(IProgressMonitor monitor) { + for(int i = 0; i < projects.length; i++){ + ManagedBuildManager.saveBuildInfo(projects[i],true); + } + return new Status( + IStatus.OK, + ManagedBuilderCorePlugin.getUniqueIdentifier(), + IStatus.OK, + new String(), + null); + } + }; + savingJob.setRule(buildInfoSaveRule); + + savingJob.schedule(); + } + + private boolean updateResourceConfigurations(IManagedBuildInfo info, IPath oldPath, IPath newPath){ + boolean changed = false; + if(!oldPath.equals(newPath)){ + IManagedProject mngProj = info.getManagedProject(); + if(mngProj != null){ + IConfiguration configs[] = mngProj.getConfigurations(); + if(configs != null && configs.length > 0){ + for(int i = 0; i < configs.length; i++){ + if(updateResourceConfiguration(configs[i],oldPath,newPath)) + changed = true; + } + } + } + } + return changed; + } + + private boolean removeResourceConfigurations(IManagedBuildInfo info, IPath path){ + boolean changed = false; + IManagedProject mngProj = info.getManagedProject(); + if(mngProj != null){ + IConfiguration configs[] = mngProj.getConfigurations(); + if(configs != null && configs.length > 0){ + for(int i = 0; i < configs.length; i++){ + if(removeResourceConfiguration(configs[i],path)) + changed = true; + } + } + } + return changed; + } + + private boolean updateResourceConfiguration(IConfiguration config, IPath oldPath, IPath newPath){ + IResourceConfiguration rcCfg = config.getResourceConfiguration(oldPath.toString()); + if(rcCfg != null && !oldPath.equals(newPath)){ + config.removeResourceConfiguration(rcCfg); + rcCfg.setResourcePath(newPath.toString()); + ((Configuration)config).addResourceConfiguration((ResourceConfiguration)rcCfg); + return true; + } + return false; + } + + private boolean removeResourceConfiguration(IConfiguration config, IPath path){ + IResourceConfiguration rcCfg = config.getResourceConfiguration(path.toString()); + if(rcCfg != null){ + config.removeResourceConfiguration(rcCfg); + return true; + } + return false; + } + + /* + * I S a v e P a r t i c i p a n t + */ + + /* (non-Javadoc) + * @see org.eclipse.core.resources.ISaveParticipant#saving(org.eclipse.core.resources.ISaveContext) + */ + public void saving(ISaveContext context) throws CoreException { + // No state to be saved by the plug-in, but request a + // resource delta to be used on next activation. + context.needDelta(); + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.ISaveParticipant#doneSaving(org.eclipse.core.resources.ISaveContext) + */ + public void doneSaving(ISaveContext context) { + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.ISaveParticipant#prepareToSave(org.eclipse.core.resources.ISaveContext) + */ + public void prepareToSave(ISaveContext context) throws CoreException { + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.ISaveParticipant#rollback(org.eclipse.core.resources.ISaveContext) + */ + public void rollback(ISaveContext context) { + } + +}