/*******************************************************************************
* Copyright (c) 2007, 2011 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.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ICExtensionReference;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IPathEntry;
import org.eclipse.cdt.core.resources.IPathEntryStore;
import org.eclipse.cdt.core.resources.IPathEntryStoreListener;
import org.eclipse.cdt.core.resources.PathEntryStoreChangedEvent;
import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent;
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.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.core.settings.model.util.PathEntryTranslator;
import org.eclipse.cdt.core.settings.model.util.PathEntryTranslator.PathEntryCollector;
import org.eclipse.cdt.core.settings.model.util.PathEntryTranslator.ReferenceSettingsInfo;
import org.eclipse.cdt.internal.core.model.CModelManager;
import org.eclipse.cdt.internal.core.model.PathEntryManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.QualifiedName;
public class ConfigBasedPathEntryStore implements IPathEntryStore, ICProjectDescriptionListener {
private List<IPathEntryStoreListener> fListeners;
private IProject fProject;
static final QualifiedName PATH_ENTRY_COLLECTOR_PROPERTY_NAME = new QualifiedName(CCorePlugin.PLUGIN_ID, "PathEntryStoreCollector"); //$NON-NLS-1$
/**
*
*/
public ConfigBasedPathEntryStore(IProject project) {
fProject = project;
fListeners = Collections.synchronizedList(new ArrayList<IPathEntryStoreListener>());
CProjectDescriptionManager.getInstance().addCProjectDescriptionListener(this, CProjectDescriptionEvent.APPLIED | CProjectDescriptionEvent.LOADED);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.resources.IPathEntryStore#addPathEntryStoreListener(org.eclipse.cdt.core.resources.IPathEntryStoreListener)
*/
@Override
public void addPathEntryStoreListener(IPathEntryStoreListener listener) {
fListeners.add(listener);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.resources.IPathEntryStore#removePathEntryStoreListener(org.eclipse.cdt.core.resources.IPathEntryStoreListener)
*/
@Override
public void removePathEntryStoreListener(IPathEntryStoreListener listener) {
fListeners.remove(listener);
}
private void fireContentChangedEvent(IProject project) {
PathEntryStoreChangedEvent evt = new PathEntryStoreChangedEvent(this, project, PathEntryStoreChangedEvent.CONTENT_CHANGED);
IPathEntryStoreListener[] observers = new IPathEntryStoreListener[fListeners.size()];
fListeners.toArray(observers);
for (IPathEntryStoreListener observer : observers) {
observer.pathEntryStoreChanged(evt);
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.resources.IPathEntryStore#fireClosedChangedEvent(IProject)
*/
@Override
public void close() {
PathEntryStoreChangedEvent evt = new PathEntryStoreChangedEvent(this, fProject, PathEntryStoreChangedEvent.STORE_CLOSED);
IPathEntryStoreListener[] observers = new IPathEntryStoreListener[fListeners.size()];
fListeners.toArray(observers);
for (IPathEntryStoreListener observer : observers) {
observer.pathEntryStoreChanged(evt);
}
CProjectDescriptionManager.getInstance().removeCProjectDescriptionListener(this);
}
@Override
public IProject getProject() {
return fProject;
}
@Override
@Deprecated
public ICExtensionReference getExtensionReference() {
return null;
}
@Override
public ICConfigExtensionReference getConfigExtensionReference() {
return null;
}
@Override
public IPathEntry[] getRawPathEntries() throws CoreException {
ICConfigurationDescription cfg = getIndexCfg(fProject);
List<IPathEntry>[] es = getEntries(fProject, cfg);
if(es != null){
List<IPathEntry> list = new ArrayList<IPathEntry>(es[0].size() + 1);
list.addAll(es[0]);
list.add(CoreModel.newContainerEntry(ConfigBasedPathEntryContainer.CONTAINER_PATH));
return list.toArray(new IPathEntry[list.size()]);
}
return new IPathEntry[0];
}
@Override
public void setRawPathEntries(IPathEntry[] entries) throws CoreException {
ICConfigurationDescription cfg = getIndexCfg(fProject);
List<IPathEntry> es[] = getEntries(fProject, cfg);
if(es != null){
List<IPathEntry> sysList = es[1];
List<IPathEntry> usrList = es[0];
List<IPathEntry> newUsrList = new ArrayList<IPathEntry>(entries.length);
for (IPathEntry entry : entries) {
if(entry.getEntryKind() != IPathEntry.CDT_CONTAINER)
newUsrList.add(entry);
}
if(!newUsrList.equals(usrList)){
usrList = newUsrList;
ICProjectDescription des = CoreModel.getDefault().getProjectDescription(fProject, true);
ICConfigurationDescription cfgDes = des.getDefaultSettingConfiguration();
CConfigurationData data = cfgDes.getConfigurationData();
PathEntryTranslator tr = new PathEntryTranslator(fProject, data);
IPathEntry[] usrEntries = usrList.toArray(new IPathEntry[usrList.size()]);
IPathEntry[] sysEntries = sysList.toArray(new IPathEntry[sysList.size()]);
ReferenceSettingsInfo rInfo = tr.applyPathEntries(usrEntries, sysEntries, PathEntryTranslator.OP_REPLACE);
cfgDes.removeExternalSettings();
ICExternalSetting extSettings[] = rInfo.getExternalSettings();
for (ICExternalSetting setting : extSettings) {
cfgDes.createExternalSetting(setting.getCompatibleLanguageIds(),
setting.getCompatibleContentTypeIds(),
setting.getCompatibleExtensions(),
setting.getEntries());
}
Map<String, String> refMap = rInfo.getRefProjectsMap();
cfgDes.setReferenceInfo(refMap);
CoreModel.getDefault().setProjectDescription(fProject, des);
}
}
}
private static void clearCachedEntries(ICProjectDescription des){
ICConfigurationDescription[] cfgDess = des.getConfigurations();
for (ICConfigurationDescription cfgDes : cfgDess) {
setCachedEntries(cfgDes, null);
}
}
@Override
public void handleEvent(CProjectDescriptionEvent event) {
IProject project = event.getProject();
if(!fProject.equals(project))
return;
switch(event.getEventType()){
case CProjectDescriptionEvent.APPLIED:{
ICProjectDescription des = event.getNewCProjectDescription();
ICProjectDescription oldDes = event.getOldCProjectDescription();
List<IPathEntry> oldCrEntries = null;
if(oldDes != null){
ICConfigurationDescription oldIndexCfg = oldDes.getDefaultSettingConfiguration();
List<IPathEntry>[] oldEs = getCachedEntries(oldIndexCfg);
if(oldEs != null)
oldCrEntries = oldEs[1];
clearCachedEntries(oldDes);
}
if(des != null){
//TODO: smart delta handling
clearCachedEntries(des);
if(oldCrEntries != null){
ICConfigurationDescription newIndexCfg = des.getDefaultSettingConfiguration();
List<IPathEntry>[] newEs = getEntries(fProject, newIndexCfg);
List<IPathEntry> newCrEntries = newEs[1];
if(!Arrays.equals(oldCrEntries.toArray(), newCrEntries.toArray())){
CModelManager manager = CModelManager.getDefault();
ICProject cproject = manager.create(project);
// ConfigBasedPathEntryContainer newContainer = createContainer(des);
try {
PathEntryManager.getDefault().clearPathEntryContainer(new ICProject[]{cproject}, ConfigBasedPathEntryContainer.CONTAINER_PATH, new NullProgressMonitor());
} catch (CModelException e) {
CCorePlugin.log(e);
}
}
}
}
fireContentChangedEvent(fProject);
break;
}
}
}
// private static PathEntryCollector getCollector(ICProjectDescription des){
// ICConfigurationDescription cfgDes = ((CProjectDescription)des).getIndexConfiguration();
// if(cfgDes != null){
// PathEntryCollector cr = getCachedCollector(cfgDes);
// if(cr == null){
// cr = PathEntryTranslator.collectEntries(des.getProject(), cfgDes);
// setCachedCollector(cfgDes, cr);
// }
// return cr;
// }
// return null;
// }
private static List<IPathEntry>[] getEntries(IProject project, ICConfigurationDescription cfgDes){
if(cfgDes != null){
List<IPathEntry>[] es = getCachedEntries(cfgDes);
if(es == null){
PathEntryCollector cr = PathEntryTranslator.collectEntries(project, cfgDes);
es = createEntriesList(cfgDes, cr);
setCachedEntries(cfgDes, es);
}
return es;
}
return null;
}
private static List<IPathEntry>[] createEntriesList(ICConfigurationDescription cfgDes, PathEntryCollector cr){
@SuppressWarnings("unchecked")
ArrayList<IPathEntry>[] es = new ArrayList[2];
es[0] = new ArrayList<IPathEntry>();
cr.getEntries(es[0], PathEntryTranslator.INCLUDE_USER, cfgDes);
es[0].trimToSize();
es[1] = new ArrayList<IPathEntry>();
cr.getEntries(es[1], PathEntryTranslator.INCLUDE_BUILT_INS, cfgDes);
es[1].trimToSize();
return es;
}
@SuppressWarnings("unchecked")
private static List<IPathEntry>[] getCachedEntries(ICConfigurationDescription cfgDes){
return (List<IPathEntry>[])cfgDes.getSessionProperty(PATH_ENTRY_COLLECTOR_PROPERTY_NAME);
}
private static void setCachedEntries(ICConfigurationDescription cfgDes, List<IPathEntry>[] es){
cfgDes.setSessionProperty(PATH_ENTRY_COLLECTOR_PROPERTY_NAME, es);
}
// public static PathEntryCollector getCollector(IProject project){
// ICProjectDescription des = CCorePlugin.getDefault().getProjectDescription(project, false);
// if(des != null)
// return getCollector(des);
// return null;
// }
private static ICConfigurationDescription getIndexCfg(IProject project){
ICProjectDescription des = CCorePlugin.getDefault().getProjectDescription(project, false);
return des != null ? des.getDefaultSettingConfiguration() : null;
}
private static List<IPathEntry> getContainerEntries(IProject project){
ICProjectDescription des = CCorePlugin.getDefault().getProjectDescription(project, false);
if(des != null)
return getContainerEntries(des);
return new ArrayList<IPathEntry>(0);
}
private static List<IPathEntry> getContainerEntries(ICProjectDescription des){
ICConfigurationDescription cfg = des.getDefaultSettingConfiguration();
List<IPathEntry> es[] = getEntries(des.getProject(), cfg);
if(es != null)
return es[1];
return new ArrayList<IPathEntry>(0);
}
public static ConfigBasedPathEntryContainer createContainer(IProject project){
List<IPathEntry> list = getContainerEntries(project);
return new ConfigBasedPathEntryContainer(list);
}
public static ConfigBasedPathEntryContainer createContainer(ICProjectDescription des){
List<IPathEntry> list = getContainerEntries(des);
return new ConfigBasedPathEntryContainer(list);
}
}