/*******************************************************************************
* Copyright (c) 2007, 2013 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.internal.core.settings.model;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.cdtvariables.ICdtVariable;
import org.eclipse.cdt.core.cdtvariables.ICdtVariablesContributor;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
import org.eclipse.cdt.core.settings.model.CConfigurationStatus;
import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent;
import org.eclipse.cdt.core.settings.model.ICBuildSetting;
import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICExternalSetting;
import org.eclipse.cdt.core.settings.model.ICFileDescription;
import org.eclipse.cdt.core.settings.model.ICFolderDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSetting;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.core.settings.model.ICSettingBase;
import org.eclipse.cdt.core.settings.model.ICSettingContainer;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingObject;
import org.eclipse.cdt.core.settings.model.ICSourceEntry;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.ICTargetPlatformSetting;
import org.eclipse.cdt.core.settings.model.IModificationContext;
import org.eclipse.cdt.core.settings.model.WriteAccessException;
import org.eclipse.cdt.core.settings.model.extension.CBuildData;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationDataProvider;
import org.eclipse.cdt.core.settings.model.extension.CFileData;
import org.eclipse.cdt.core.settings.model.extension.CFolderData;
import org.eclipse.cdt.core.settings.model.extension.CLanguageData;
import org.eclipse.cdt.core.settings.model.extension.CResourceData;
import org.eclipse.cdt.core.settings.model.extension.CTargetPlatformData;
import org.eclipse.cdt.core.settings.model.extension.impl.CDefaultConfigurationData;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.settings.model.util.PathSettingsContainer;
import org.eclipse.cdt.internal.core.cdtvariables.CdtVariableManager;
import org.eclipse.cdt.internal.core.cdtvariables.StorableCdtVariables;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.QualifiedName;
/**
* CConfigurationDescriptionCache is a proxy class for serialization of configuration description data.
*
* An inspection of the scenario where user changes project properties and saves it yields
* following sequence of events:
* <ol>
* <li> Initialization:
* <ul>
* <li> After eclipse started a project is being opened. A new CConfigurationDescriptionCache is created
* with CConfigurationDescriptionCache(ICStorageElement storage, CProjectDescription parent) constructor.
* <li> Any clients needed ICConfigurationDescription get CConfigurationDescription using constructor
* CConfigurationDescription(CConfigurationData data, String buildSystemId, ICDataProxyContainer cr)
* where the CConfigurationDescriptionCache is passed as data. The reference to cache is kept in field fCfgCache.
* <li> fCfgCache is used to getSpecSettings() CConfigurationSpecSettings, after that fCfgCache is set to null.
* </ul>
* <li> User enters project properties/settings:
* <ul>
* <li> another CConfigurationDescription (settings configuration) created using the same constructor setting fCfgCache
* to the CConfigurationDescriptionCache.
* </ul>
* <li> User changes settings (in the settings configuration CConfigurationDescription) and saves it:
* <ul>
* <li> new CConfigurationDescriptionCache is created from the CConfigurationDescription via constructor
* CConfigurationDescriptionCache(ICConfigurationDescription baseDescription, ...) where
* baseDescription is saved as fBaseDescription.
* <li> CConfigurationDescriptionCache.applyData(...) is used to persist the data. at that point
* reference fBaseDescription gets set to null.
* </ul>
* </ol>
*
* @see ICConfigurationDescription
* @see CConfigurationDescription
* @see CProjectDescriptionEvent
*/
public class CConfigurationDescriptionCache extends CDefaultConfigurationData
implements ICConfigurationDescription, IInternalCCfgInfo, ILanguageSettingsProvidersKeeper, ICachedData {
private CProjectDescription fParent;
private PathSettingsContainer fPathSettingContainer = PathSettingsContainer.createRootContainer();
private ResourceDescriptionHolder fRcHolder = new ResourceDescriptionHolder(fPathSettingContainer, true);
private List<ICSettingObject> fChildList = new ArrayList<ICSettingObject>();
private CConfigurationSpecSettings fSpecSettings;
private CConfigurationData fData;
private CConfigurationDescriptionCache fBaseCache;
private ICSourceEntry fProjSourceEntries[];
private StorableCdtVariables fMacros;
private boolean fDataLoadded;
private boolean fInitializing;
private ICConfigurationDescription fBaseDescription;
private ICSourceEntry[] fResolvedSourceEntries;
CConfigurationDescriptionCache(ICStorageElement storage, CProjectDescription parent) throws CoreException {
super(null);
fInitializing = true;
fParent = parent;
fSpecSettings = new CConfigurationSpecSettings(this, storage);
fId = fSpecSettings.getId();
fName = fSpecSettings.getName();
// loadData();
}
public boolean isInitializing() {
return fInitializing;
}
void loadData() throws CoreException {
if(fDataLoadded)
return;
fDataLoadded = true;
CConfigurationDataProvider dataProvider = CProjectDescriptionManager.getInstance().getProvider(this);
fData = dataProvider.loadConfiguration(this, new NullProgressMonitor());
if (getDefaultLanguageSettingsProvidersIds() == null) {
// default ids would come from toolchain configuration, ensure sensible defaults
String[] defaultIds = ScannerDiscoveryLegacySupport.getDefaultProviderIdsLegacy(this);
setDefaultLanguageSettingsProvidersIds(defaultIds);
}
if (!fSpecSettings.isLanguageSettingProvidersLoaded()) {
// when loading - providers come from xml file, ensure defaults if no xml file present
String[] defaultIds = getDefaultLanguageSettingsProvidersIds();
List<ILanguageSettingsProvider> providers = LanguageSettingsManager.createLanguageSettingsProviders(defaultIds);
setLanguageSettingProviders(providers);
}
copySettingsFrom(fData, true);
fSpecSettings.reconcileExtensionSettings(true);
((CBuildSettingCache)fBuildData).initEnvironmentCache();
ICdtVariable vars[] = CdtVariableManager.getDefault().getVariables(this);
fMacros = new StorableCdtVariables(vars, true);
// fInitializing = false;
}
CConfigurationDescriptionCache(ICConfigurationDescription baseDescription, CConfigurationData base, CConfigurationDescriptionCache baseCache, CConfigurationSpecSettings settingsBase, CProjectDescription parent, ICStorageElement rootEl) throws CoreException {
super(base.getId(), base.getName(), null);
fInitializing = true;
fParent = parent;
fSpecSettings = new CConfigurationSpecSettings(this, settingsBase, rootEl);
fSpecSettings.setModified(settingsBase.isModified());
fBaseDescription = baseDescription;
if(base instanceof CConfigurationDescriptionCache){
fData = ((CConfigurationDescriptionCache)base).getConfigurationData();
// fData = CProjectDescriptionManager.getInstance().applyData(this, baseDescription, fData);
} else {
fData = base;
// base = CProjectDescriptionManager.getInstance().applyData(this, baseDescription, base);
// fData = base;
}
fBaseCache = baseCache;
}
CConfigurationDescriptionCache getBaseCache(){
return fBaseCache;
}
boolean applyData(SettingsContext context) throws CoreException {
boolean modified = true;
if (fBaseDescription != null){
context.init(this);
CConfigurationDataProvider dataProvider = CProjectDescriptionManager.getInstance().getProvider(this);
fData = dataProvider.applyConfiguration(this, fBaseDescription, fData, context, new NullProgressMonitor());
fDataLoadded = true;
fName = fData.getName();
fId = fData.getId();
if((context.getAllConfigurationSettingsFlags() & IModificationContext.CFG_DATA_SETTINGS_UNMODIFIED) == 0 || fBaseCache == null){
copySettingsFrom(fData, true);
} else {
copySettingsFrom(fBaseCache, true);
modified = fSpecSettings.isModified();
if(!modified)
modified = (context.getAllConfigurationSettingsFlags() & IModificationContext.CFG_DATA_STORAGE_UNMODIFIED) == 0;
}
ICdtVariable vars[] = CdtVariableManager.getDefault().getVariables(this);
fMacros = new StorableCdtVariables(vars, true);
fSpecSettings.serialize();
fSpecSettings.setModified(false);
}
fBaseDescription = null;
fBaseCache = null;
return modified;
}
public StorableCdtVariables getCachedVariables(){
return fMacros;
}
protected void setId(String id) throws CoreException {
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public CFileData copyFileData(IPath path, CFileData base, boolean clone) {
return new CFileDescriptionCache(base, this);
}
@Override
protected CFileData copyFileData(IPath path, CFolderData base,
CLanguageData langData) {
//should never be here
throw new UnsupportedOperationException();
}
@Override
public CFolderData copyFolderData(IPath path, CFolderData base, boolean clone) {
return new CFolderDescriptionCache(base, this);
}
@Override
protected CBuildData copyBuildData(CBuildData data, boolean clone) {
return new CBuildSettingCache(data, this);
}
void addResourceDescription(ICResourceDescription des){
fRcHolder.addResourceDescription(des.getPath(), des);
fChildList.add(des);
}
void addTargetPlatformSetting(ICTargetPlatformSetting tpS){
fChildList.add(tpS);
}
void addBuildSetting(ICBuildSetting bs){
fChildList.add(bs);
fBuildData = (CBuildData)bs;
}
@Override
public ICProjectDescription getProjectDescription() {
return fParent;
}
@Override
public ICResourceDescription getResourceDescription(IPath path, boolean exactPath) {
return fRcHolder.getResourceDescription(path, exactPath);
}
public ICResourceDescription[] getResourceDescriptions(int kind) {
return fRcHolder.getResourceDescriptions(kind);
}
@Override
public ICFolderDescription getRootFolderDescription() {
return (ICFolderDescription)fRootFolderData;
}
@Override
public boolean isActive() {
if(isPreferenceConfiguration())
return false;
return fParent.getActiveConfiguration() == this;
}
@Override
public void removeResourceDescription(ICResourceDescription des)
throws CoreException {
throw new CoreException(new DescriptionStatus(SettingsModelMessages.getString("CConfigurationDescriptionCache.0"))); //$NON-NLS-1$
}
@Override
public CFileData createFileData(IPath path, CFileData base) throws CoreException{
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public CFileData createFileData(IPath path, CFolderData base, CLanguageData baseLangData) throws CoreException{
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public CFolderData createFolderData(IPath path, CFolderData base) throws CoreException{
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public void removeResourceData(CResourceData data)throws CoreException {
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public void setDescription(String description) throws WriteAccessException{
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public void setName(String name) throws WriteAccessException {
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public ICSettingObject[] getChildSettings() {
return fChildList.toArray(new ICSettingObject[fChildList.size()]);
}
@Override
public ICConfigurationDescription getConfiguration() {
return this;
}
@Override
public ICSettingContainer getParent() {
return fParent;
}
@Override
public ICResourceDescription[] getResourceDescriptions() {
return fRcHolder.getResourceDescriptions();
}
@Override
public ICStorageElement getStorage(String id, boolean create) throws CoreException {
return getSpecSettings().getStorage(id, create);
}
@Override
public void removeStorage(String id) throws CoreException {
getSpecSettings().removeStorage(id);
}
@Override
public ICStorageElement importStorage(String id, ICStorageElement el) throws UnsupportedOperationException, CoreException {
return getSpecSettings().importStorage(id, el);
}
@Override
public CConfigurationSpecSettings getSpecSettings() /*throws CoreException*/{
return fSpecSettings;
}
@Override
public String getBuildSystemId() {
return fSpecSettings.getBuildSystemId();
}
@Override
public CConfigurationData getConfigurationData() {
return fData;
}
@Override
public void setConfigurationData(String bsId, CConfigurationData data) throws WriteAccessException {
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public boolean isModified() {
return false;
}
@Override
public CConfigurationData getConfigurationData(boolean write) throws WriteAccessException {
if(write)
throw ExceptionFactory.createIsReadOnlyException();
return this;
}
@Override
public void setActive() throws WriteAccessException {
throw ExceptionFactory.createIsReadOnlyException();
}
/* public CConfigurationData getBaseData(){
return fData;
}
*/
@Override
public ICFileDescription createFileDescription(IPath path, ICResourceDescription base) throws CoreException, WriteAccessException {
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public ICFolderDescription createFolderDescription(IPath path, ICFolderDescription base) throws CoreException, WriteAccessException {
throw ExceptionFactory.createIsReadOnlyException();
}
ResourceDescriptionHolder createHolderForRc(IPath path){
return new ResourceDescriptionHolder(fPathSettingContainer.getChildContainer(path, true, true), false);
}
@Override
public boolean isReadOnly() {
return !fInitializing;
}
@Override
public void setReadOnly(boolean readOnly, boolean keepModify) {
if (readOnly)
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public ICTargetPlatformSetting getTargetPlatformSetting() {
return (ICTargetPlatformSetting)getTargetPlatformData();
}
@Override
protected CTargetPlatformData copyTargetPlatformData(CTargetPlatformData base, boolean clone) {
return new CTargetPlatformSettingCache(base, this);
}
@Override
public ICFileDescription[] getFileDescriptions() {
return (ICFileDescription[])fRcHolder.getResourceDescriptions(ICSettingBase.SETTING_FILE);
}
@Override
public ICFolderDescription[] getFolderDescriptions() {
return (ICFolderDescription[])fRcHolder.getResourceDescriptions(ICSettingBase.SETTING_FOLDER);
}
public void setSourcePaths(IPath[] paths) {
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public ICSourceEntry[] getSourceEntries() {
initSourceEntries();
return fProjSourceEntries.clone();
}
private void initSourceEntries(){
if(fProjSourceEntries == null){
IProject project = getProject();
fProjSourceEntries = CDataUtil.adjustEntries(fSourceEntries, true, project);
}
}
private IProject getProject(){
return isPreferenceConfiguration() ? null : getProjectDescription().getProject();
}
@Override
public void setSourceEntries(ICSourceEntry[] entries) {
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public Map<String, String> getReferenceInfo() {
return getSpecSettings().getReferenceInfo();
}
@Override
public void setReferenceInfo(Map<String, String> refs) {
throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public ICExternalSetting createExternalSetting(String[] languageIDs,
String[] contentTypeIds, String[] extensions,
ICSettingEntry[] entries) {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
return fSpecSettings.createExternalSetting(languageIDs, contentTypeIds, extensions, entries);
}
@Override
public ICExternalSetting[] getExternalSettings() {
return fSpecSettings.getExternalSettings();
}
@Override
public void removeExternalSetting(ICExternalSetting setting) {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
fSpecSettings.removeExternalSetting(setting);
}
@Override
public void removeExternalSettings() {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
fSpecSettings.removeExternalSettings();
}
@Override
public ICBuildSetting getBuildSetting() {
return (ICBuildSetting)getBuildData();
}
@Override
public void setSessionProperty(QualifiedName name, Object value) {
fSpecSettings.setSettionProperty(name, value);
//throw ExceptionFactory.createIsReadOnlyException();
}
@Override
public Object getSessionProperty(QualifiedName name) {
return fSpecSettings.getSettionProperty(name);
}
@Override
public ICdtVariablesContributor getBuildVariablesContributor() {
return fData.getBuildVariablesContributor();
}
@Override
public ICConfigExtensionReference create(String extensionPoint,
String extension) throws CoreException {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
return fSpecSettings.create(extensionPoint, extension);
}
@Override
public ICConfigExtensionReference[] get(String extensionPointID) {
return fSpecSettings.get(extensionPointID);
}
@Override
public void remove(ICConfigExtensionReference ext) throws CoreException {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
fSpecSettings.remove(ext);
}
@Override
public void remove(String extensionPoint) throws CoreException {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
fSpecSettings.remove(extensionPoint);
}
@Override
public boolean isPreferenceConfiguration() {
return getProjectDescription() == null;
}
void doneInitialization(){
CProjectDescriptionManager.getInstance().notifyCached(this, fData, null);
fInitializing = false;
fSpecSettings.doneInitialization();
}
@Override
public ICLanguageSetting getLanguageSettingForFile(IPath path, boolean ignoreExcludeStatus) {
return CProjectDescriptionManager.getLanguageSettingForFile(this, path, ignoreExcludeStatus);
}
@Override
protected CResourceData[] filterRcDatasToCopy(CConfigurationData base) {
if(!isPreferenceConfiguration())
CProjectDescriptionManager.removeNonCustomSettings(getProjectDescription().getProject(), base);
return super.filterRcDatasToCopy(base);
}
boolean isExcluded(IPath path){
// if(path.segmentCount() == 0)
// return false;
initSourceEntries();
IProject project = getProject();
if(project != null)
path = project.getFullPath().append(path);
return CDataUtil.isExcluded(path, fProjSourceEntries);
}
@Override
public String[] getExternalSettingsProviderIds() {
return fSpecSettings.getExternalSettingsProviderIds();
}
@Override
public void setExternalSettingsProviderIds(String[] ids) {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
fSpecSettings.setExternalSettingsProviderIds(ids);
}
@Override
public void updateExternalSettingsProviders(String[] ids) {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
fSpecSettings.updateExternalSettingsProviders(ids);
}
@Override
public ICSourceEntry[] getResolvedSourceEntries() {
if(fResolvedSourceEntries == null){
ICSourceEntry[] entries = getSourceEntries();
fResolvedSourceEntries = CDataUtil.resolveEntries(entries, this);
}
return fResolvedSourceEntries;
}
@Override
public CConfigurationStatus getConfigurationStatus() {
CConfigurationStatus status = getStatus();
return status != null ? status : CConfigurationStatus.CFG_STATUS_OK;
}
@Override
public void setLanguageSettingProviders(List<? extends ILanguageSettingsProvider> providers) {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
fSpecSettings.setLanguageSettingProviders(providers);
}
@Override
public List<ILanguageSettingsProvider> getLanguageSettingProviders() {
return fSpecSettings.getLanguageSettingProviders();
}
@Override
public void setDefaultLanguageSettingsProvidersIds(String[] ids) {
if(!fInitializing)
throw ExceptionFactory.createIsReadOnlyException();
fSpecSettings.setDefaultLanguageSettingsProvidersIds(ids);
}
@Override
public String[] getDefaultLanguageSettingsProvidersIds() {
return fSpecSettings.getDefaultLanguageSettingsProvidersIds();
}
}