diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/ICProjectDescription.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/ICProjectDescription.java index d188552a950..0225f878c10 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/ICProjectDescription.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/ICProjectDescription.java @@ -194,5 +194,4 @@ public interface ICProjectDescription extends ICSettingContainer, * @see ICProjectDescriptionManager#createProjectDescription(IProject, boolean, boolean) */ void setCdtProjectCreated(); - } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CExternalSettingsManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CExternalSettingsManager.java index 8e353564751..91839442045 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CExternalSettingsManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CExternalSettingsManager.java @@ -693,6 +693,9 @@ public class CExternalSettingsManager implements ICExternalSettingsListener, ICP } private void checkStore(ICProjectDescription des){ + if(des == null) + return; + ICConfigurationDescription[] cfgs = des.getConfigurations(); for(int i = 0; i < cfgs.length; i++){ checkStore(cfgs[i]); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescription.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescription.java index 65dd1a4b716..6972da66ae6 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescription.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescription.java @@ -613,6 +613,13 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon fIsCreating = false; fIsModified = true; } + + public void touch() throws WriteAccessException { + if(fIsReadOnly) + throw ExceptionFactory.createIsReadOnlyException(); + + fIsModified = true; + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java index 9dbf94aa95a..84195f2a77d 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java @@ -135,7 +135,7 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { private static final String CONVERTED_CFG_NAME = "convertedConfig"; //$NON-NLS-1$ private static final String CONVERTED_CFG_ID_PREFIX = "converted.config"; //$NON-NLS-1$ - private static final String STORAGE_FILE_NAME = ".cproject"; //$NON-NLS-1$ + static final String STORAGE_FILE_NAME = ".cproject"; //$NON-NLS-1$ // private static final QualifiedName PROJECT_DESCRCIPTION_PROPERTY = new QualifiedName(CCorePlugin.PLUGIN_ID, "projectDescription"); //$NON-NLS-1$ private static final String ROOT_ELEMENT_NAME = "cproject"; //$NON-NLS-1$ private static final String VERSION_ELEMENT_NAME = "fileVersion"; //$NON-NLS-1$ @@ -239,6 +239,7 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { private static class ThreadInfo { Map fDescriptionLoaddingMap; Map fDescriptionApplyingMap; + Map fProjectFileSerializationMap; public Map getDescriptionLoaddingMap(boolean create){ if(fDescriptionLoaddingMap == null && create){ @@ -253,6 +254,14 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { } return fDescriptionApplyingMap; } + + public Map getProjectFileSerializationMap(boolean create){ + if(fProjectFileSerializationMap == null && create){ + fProjectFileSerializationMap = new HashMap(); + } + return fProjectFileSerializationMap; + } + } private Map fProviderMap; @@ -413,6 +422,46 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { return null; } + private Map getProjectFileSerializationMap(boolean create){ + ThreadInfo info = getThreadInfo(create); + if(info != null) + return info.getProjectFileSerializationMap(create); + return null; + } + + private void aboutToSaveProjectFile(IProject project){ + getProjectFileSerializationMap(true).put(project, Boolean.TRUE); + } + + private void doneSaveProjectFile(IProject project){ +// Map map = getProjectFileSerializationMap(false); +// if(map != null){ +// if(map.remove(project) != null){ +// CCorePlugin.log("incorrect .cproject file save state, ingnoring"); +// } +// } + } + + CProjectDescription checkExternalProjectFileModification(IResource rc) throws CoreException{ + Map map = getProjectFileSerializationMap(false); + IProject project = rc.getProject(); + if(map != null){ + if(map.remove(project) != null) + return null; + } + + CProjectDescription des = (CProjectDescription)getProjectDescription(project, GET_IF_LOADDED); + if(des == null || des.isLoadding()) + return null; + + //TODO: .cproject file is modified externally + des = (CProjectDescription)loadProjectDescription(project); + des = createWritableDescription(des); + des.touch(); + + return des; + } + private ThreadInfo getThreadInfo(boolean create){ ThreadInfo info = (ThreadInfo)fThreadInfo.get(); if(info == null && create){ @@ -443,12 +492,15 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { SettingsContext context = null; des = getDescriptionApplying(project); - - if(des == null && (ignoreClose || project.isOpen())) - des = getLoaddedDescription(project); if(des == null) des = getDescriptionLoadding(project); + + if(des == null && (ignoreClose || project.isOpen())) + des = getLoaddedDescription(project); + +// if(des == null) +// des = getDescriptionLoadding(project); if(des == null && load && project.isOpen()){ try { @@ -489,22 +541,26 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { } if(des != null && write){ - CProjectDescription cache = (CProjectDescription)des; - ICStorageElement el = null; - try { - el = cache.getRootStorageElement(); - el = copyElement((InternalXmlStorageElement)el, false); - } catch (CoreException e) { - CCorePlugin.log(e); - } - - des = new CProjectDescription((CProjectDescription)des, false, el, des.isCdtProjectCreating()); - CProjectDescriptionEvent event = createCopyCreatedEvent(des, cache); - notifyListeners(event); + des = createWritableDescription((CProjectDescription)des); } return des; } + private CProjectDescription createWritableDescription(CProjectDescription cache){ + ICStorageElement el = null; + try { + el = cache.getRootStorageElement(); + el = copyElement((InternalXmlStorageElement)el, false); + } catch (CoreException e) { + CCorePlugin.log(e); + } + + CProjectDescription des = new CProjectDescription(cache, false, el, cache.isCdtProjectCreating()); + CProjectDescriptionEvent event = createCopyCreatedEvent(des, cache); + notifyListeners(event); + return des; + } + private synchronized boolean setLoaddedDescriptionOnLoad(IProject project, ICProjectDescription des){ des.setSessionProperty(LOAD_FLAG, Boolean.TRUE); ICProjectDescription oldDes = getLoaddedDescription(project); @@ -1173,22 +1229,24 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { public void setProjectDescription(IProject project, ICProjectDescription des, int flags, IProgressMonitor monitor) throws CoreException { - if(!des.isValid() && (!fAllowEmptyCreatingDescription || !des.isCdtProjectCreating())) - throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.17") + project.getName()); //$NON-NLS-1$ - - if(!checkFlags(flags, SET_FORCE) && !des.isModified()) - return; - - if(((CProjectDescription)des).isLoadding()){ - //do nothing -// throw ExceptionFactory.createCoreException("description is being loadded"); - return; - } - - if(((CProjectDescription)des).isApplying()){ - //do nothing -// throw ExceptionFactory.createCoreException("description is being applied"); - return; + if(des != null){ + if(!des.isValid() && (!fAllowEmptyCreatingDescription || !des.isCdtProjectCreating())) + throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.17") + project.getName()); //$NON-NLS-1$ + + if(!checkFlags(flags, SET_FORCE) && !des.isModified()) + return; + + if(((CProjectDescription)des).isLoadding()){ + //do nothing + // throw ExceptionFactory.createCoreException("description is being loadded"); + return; + } + + if(((CProjectDescription)des).isApplying()){ + //do nothing + // throw ExceptionFactory.createCoreException("description is being applied"); + return; + } } if(monitor == null) @@ -1386,6 +1444,8 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { IFile projectFile = project.getFile(file); String utfString = stream.toString("UTF-8"); //$NON-NLS-1$ + aboutToSaveProjectFile(project); + if (projectFile.exists()) { if (projectFile.isReadOnly()) { // Inform Eclipse that we are intending to modify this file @@ -1425,6 +1485,7 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { } else { projectFile.create(new ByteArrayInputStream(utfString.getBytes("UTF-8")), IResource.FORCE, new NullProgressMonitor()); //$NON-NLS-1$ } + doneSaveProjectFile(project); // Close the streams stream.close(); } catch (TransformerConfigurationException e){ @@ -2895,6 +2956,7 @@ public class CProjectDescriptionManager implements ICProjectDescriptionManager { } } + void checkRemovedConfigurations(ICDescriptionDelta delta){ if(delta == null) return; diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/ConfigBasedPathEntryStore.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/ConfigBasedPathEntryStore.java index 454b895c63f..1f66c7e5301 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/ConfigBasedPathEntryStore.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/ConfigBasedPathEntryStore.java @@ -258,7 +258,7 @@ public class ConfigBasedPathEntryStore implements IPathEntryStore, ICProjectDesc private static ICConfigurationDescription getIndexCfg(IProject project){ ICProjectDescription des = CCorePlugin.getDefault().getProjectDescription(project, false); - return des.getDefaultSettingConfiguration(); + return des != null ? des.getDefaultSettingConfiguration() : null; } private static List getContainerEntries(IProject project){ diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/ResourceChangeHandler.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/ResourceChangeHandler.java index 3fbb236f28a..9414c5ae52e 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/ResourceChangeHandler.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/ResourceChangeHandler.java @@ -20,10 +20,8 @@ import java.util.Map; import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.settings.model.ICBuildSetting; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICExclusionPatternPathEntry; -import org.eclipse.cdt.core.settings.model.ICOutputEntry; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICResourceDescription; import org.eclipse.cdt.core.settings.model.ICSourceEntry; @@ -33,6 +31,7 @@ import org.eclipse.cdt.core.settings.model.util.ResourceChangeHandlerBase; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.ISaveContext; import org.eclipse.core.resources.ISaveParticipant; import org.eclipse.core.resources.IWorkspaceRunnable; @@ -44,7 +43,7 @@ import org.eclipse.core.runtime.NullProgressMonitor; public class ResourceChangeHandler extends ResourceChangeHandlerBase implements ISaveParticipant { CProjectDescriptionManager fMngr = CProjectDescriptionManager.getInstance(); - private class RcMoveHandler implements IResourceMoveHandler { + class RcMoveHandler implements IResourceMoveHandler { Map fProjDesMap = new HashMap(); Set fRemovedProjSet = new HashSet(); @@ -157,7 +156,7 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements private ICProjectDescription getProjectDescription(IResource rc, boolean load){ IProject project = rc.getProject(); ICProjectDescription des = (ICProjectDescription)fProjDesMap.get(project); - if(des == null){ + if(des == null && !fProjDesMap.containsKey(project)){ int flags = load ? 0 : CProjectDescriptionManager.GET_IF_LOADDED; flags |= CProjectDescriptionManager.INTERNAL_GET_IGNORE_CLOSE; flags |= CProjectDescriptionManager.GET_WRITABLE; @@ -167,6 +166,10 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements return des; } + private void setProjectDescription(IProject project, ICProjectDescription des){ + fProjDesMap.put(project, des); + } + private List checkRemove(IPath rcFullPath, ICExclusionPatternPathEntry[] entries){ List updatedList = null; int num = 0; @@ -256,7 +259,7 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements iter.remove(); } else { ICProjectDescription des = (ICProjectDescription)entry.getValue(); - if(des == null || !des.isModified()) + if(des != null && !des.isModified()) iter.remove(); } } @@ -322,4 +325,43 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements public void rollback(ISaveContext context) { } + protected void doHahdleResourceMove(IResourceChangeEvent event, + IResourceMoveHandler handler) { + switch(event.getType()){ + case IResourceChangeEvent.POST_CHANGE: + IResourceDelta delta = event.getDelta(); + if(delta != null){ + IResourceDelta projs[] = delta.getAffectedChildren(); + for(int i = 0; i < projs.length; i++){ + IResourceDelta children[] = projs[i].getAffectedChildren(); + for(int k = 0; k < children.length; k++){ + IResourceDelta child = children[k]; + IResource rc = child.getResource(); + if(rc.getType() != IResource.FILE) + continue; + + if(!CProjectDescriptionManager.STORAGE_FILE_NAME.equals(rc.getName())) + continue; + + //the .cproject file is changed + try { + CProjectDescription des = CProjectDescriptionManager.getInstance().checkExternalProjectFileModification(rc); + if(des != null){ + ((RcMoveHandler)handler).setProjectDescription(rc.getProject(), des); + } + } catch (CoreException e) { + CCorePlugin.log(e); + //project file does not exist or corrupted, remove + ((RcMoveHandler)handler).setProjectDescription(rc.getProject(), null); + } + } + } + } + break; + } + super.doHahdleResourceMove(event, handler); + } + + + } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/SetCProjectDescriptionOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/SetCProjectDescriptionOperation.java index 68a56d6687b..c2d80592a90 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/SetCProjectDescriptionOperation.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/SetCProjectDescriptionOperation.java @@ -43,29 +43,31 @@ public class SetCProjectDescriptionOperation extends CModelOperation { CProjectDescriptionEvent event = mngr.createAboutToApplyEvent(fSetDescription, fOldDescriptionCache); mngr.notifyListeners(event); - - InternalXmlStorageElement el = null; - try { - el = mngr.copyElement((InternalXmlStorageElement)fSetDescription.getRootStorageElement(), false); - } catch (CoreException e2) { - } - - boolean creating = fOldDescriptionCache != null ? fOldDescriptionCache.isCdtProjectCreating() : true; - if(creating) - creating = fSetDescription.isCdtProjectCreating(); - - if(!fSetDescription.isValid() && (!mngr.isEmptyCreatingDescriptionAllowed() || !creating)) - throw new CModelException(ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.17") + project.getName())); //$NON-NLS-1$ - - CProjectDescription fNewDescriptionCache = new CProjectDescription(fSetDescription, true, el, creating); + CProjectDescription fNewDescriptionCache = null; SettingsContext context = new SettingsContext(project); - try { - mngr.setDescriptionApplying(project, fNewDescriptionCache); - fNewDescriptionCache.applyDatas(context); - } finally { - mngr.clearDescriptionApplying(project); - } + if(fSetDescription != null){ + InternalXmlStorageElement el = null; + try { + el = mngr.copyElement((InternalXmlStorageElement)fSetDescription.getRootStorageElement(), false); + } catch (CoreException e2) { + } + + boolean creating = fOldDescriptionCache != null ? fOldDescriptionCache.isCdtProjectCreating() : true; + if(creating) + creating = fSetDescription.isCdtProjectCreating(); + + if(!fSetDescription.isValid() && (!mngr.isEmptyCreatingDescriptionAllowed() || !creating)) + throw new CModelException(ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.17") + project.getName())); //$NON-NLS-1$ + + fNewDescriptionCache = new CProjectDescription(fSetDescription, true, el, creating); + try { + mngr.setDescriptionApplying(project, fNewDescriptionCache); + fNewDescriptionCache.applyDatas(context); + } finally { + mngr.clearDescriptionApplying(project); + } + } ICDescriptionDelta delta = mngr.createDelta(fNewDescriptionCache, fOldDescriptionCache); mngr.checkRemovedConfigurations(delta); @@ -81,7 +83,8 @@ public class SetCProjectDescriptionOperation extends CModelOperation { mngr.setLoaddedDescription(project, fNewDescriptionCache, true); - fSetDescription.switchToCachedAppliedData(fNewDescriptionCache); + if(fSetDescription != null) + fSetDescription.switchToCachedAppliedData(fNewDescriptionCache); try { final IProjectDescription eDes = context.getEclipseProjectDescription(); @@ -99,18 +102,20 @@ public class SetCProjectDescriptionOperation extends CModelOperation { // ExternalSettingsManager.getInstance().updateDepentents(delta); - try { - ((InternalXmlStorageElement)fNewDescriptionCache.getRootStorageElement()).setReadOnly(true); - } catch (CoreException e1) { + if(fNewDescriptionCache != null){ + try { + ((InternalXmlStorageElement)fNewDescriptionCache.getRootStorageElement()).setReadOnly(true); + } catch (CoreException e1) { + } + + fNewDescriptionCache.doneApplying(); } - - fNewDescriptionCache.doneApplying(); event = mngr.createAppliedEvent(fNewDescriptionCache, fOldDescriptionCache, fSetDescription, delta); mngr.notifyListeners(event); try { - if(!CProjectDescriptionManager.checkFlags(fFlags, ICProjectDescriptionManager.SET_NO_SERIALIZE)) + if(fNewDescriptionCache != null && !CProjectDescriptionManager.checkFlags(fFlags, ICProjectDescriptionManager.SET_NO_SERIALIZE)) context.addWorkspaceRunnable(mngr.createDesSerializationRunnable(fNewDescriptionCache)); IWorkspaceRunnable toRun = context.createOperationRunnable();