/*******************************************************************************
* Copyright (c) 2007, 2010 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.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.settings.model.CExternalSetting;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.extension.CExternalSettingProvider;
import org.eclipse.cdt.internal.core.settings.model.CExternalSettingsManager.CContainerRef;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
/**
* Responsible for managing external settings providers contributed through the extension point
*/
public class ExtensionContainerFactory extends CExternalSettingContainerFactoryWithListener {
static final String FACTORY_ID = CCorePlugin.PLUGIN_ID + ".extension.container.factory"; //$NON-NLS-1$
private static final String EXTENSION_ID = CCorePlugin.PLUGIN_ID + ".externalSettingsProvider"; //$NON-NLS-1$
private static ExtensionContainerFactory fInstance;
private Map<String, CExtensionSettingProviderDescriptor> fDescriptorMap;
private static class NullProvider extends CExternalSettingProvider {
private static final NullProvider INSTANCE = new NullProvider();
@Override
public CExternalSetting[] getSettings(IProject project, ICConfigurationDescription cfg) {
return new CExternalSetting[0];
}
}
private static class CESContainer extends CExternalSettingsContainer {
private CExternalSetting[] fSettings;
CESContainer(CExternalSetting[] settings){
fSettings = settings.clone();
}
@Override
public CExternalSetting[] getExternalSettings() {
return fSettings.clone();
}
}
private static class CExtensionSettingProviderDescriptor {
private static final String PROVIDER = "provider"; //$NON-NLS-1$
private static final String CLASS = "class"; //$NON-NLS-1$
private IExtension fExtension;
private IConfigurationElement fProviderElement;
private String fId;
private String fName;
private CExternalSettingProvider fProvider;
CExtensionSettingProviderDescriptor(IExtension extension){
fId = extension.getUniqueIdentifier();
fName = extension.getLabel();
fExtension = extension;
}
public String getId(){
return fId;
}
@SuppressWarnings("unused")
public String getName(){
return fName;
}
private CExternalSettingProvider getProvider(){
if(fProvider == null){
try {
fProvider = createProvider();
} catch (CoreException e) {
CCorePlugin.log(e);
}
if(fProvider == null){
fProvider = NullProvider.INSTANCE;
}
}
return fProvider;
}
CExternalSettingsContainer getContainer(IProject project, ICConfigurationDescription cfg, CExternalSetting[] previousSettings){
return new CESContainer(getProvider().getSettings(project, cfg, previousSettings));
}
CExternalSettingProvider createProvider() throws CoreException{
IConfigurationElement el = getProviderElement();
if(el != null){
Object obj = el.createExecutableExtension(CLASS);
if(obj instanceof CExternalSettingProvider){
return (CExternalSettingProvider)obj;
} else
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("ExtensionContainerFactory.4")); //$NON-NLS-1$
}
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("ExtensionContainerFactory.5")); //$NON-NLS-1$
}
private IConfigurationElement getProviderElement(){
if(fProviderElement == null)
fProviderElement = getProviderElement(fExtension);
return fProviderElement;
}
private static IConfigurationElement getProviderElement(IExtension ext){
IConfigurationElement els[] = ext.getConfigurationElements();
for (IConfigurationElement el : els) {
String name = el.getName();
if(PROVIDER.equals(name))
return el;
}
return null;
}
}
private Map<String, CExtensionSettingProviderDescriptor> getProviderDescriptorMap(){
if(fDescriptorMap == null){
initProviderInfoSynch();
}
return fDescriptorMap;
}
private synchronized void initProviderInfoSynch(){
if(fDescriptorMap != null)
return;
IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_ID);
IExtension exts[] = extensionPoint.getExtensions();
fDescriptorMap = new HashMap<String, CExtensionSettingProviderDescriptor>();
for (IExtension ext : exts) {
CExtensionSettingProviderDescriptor dr = new CExtensionSettingProviderDescriptor(ext);
fDescriptorMap.put(dr.getId(), dr);
}
}
private ExtensionContainerFactory(){
}
public static ExtensionContainerFactory getInstance(){
if(fInstance == null){
fInstance = new ExtensionContainerFactory();
}
return fInstance;
}
public static ExtensionContainerFactory getInstanceInitialized(){
CExternalSettingContainerFactory f = CExternalSettingsManager.getInstance().getFactory(FACTORY_ID);
if(f instanceof ExtensionContainerFactory)
return (ExtensionContainerFactory)f;
return getInstance();
}
@Override
public CExternalSettingsContainer createContainer(String id,
IProject project, ICConfigurationDescription cfgDes, CExternalSetting[] previousSettings) throws CoreException {
CExtensionSettingProviderDescriptor dr = getProviderDescriptorMap().get(id);
if(dr != null)
return dr.getContainer(project, cfgDes, previousSettings);
// Notify the manager that there's no external settings manager matching id.
throw new CoreException(CCorePlugin.createStatus("External settings provider: \"" + id + "\" couldn't be found for " + //$NON-NLS-1$//$NON-NLS-2$
cfgDes.getProjectDescription().getProject() + ":"+cfgDes.getName())); //$NON-NLS-1$
}
public static String[] getReferencedProviderIds(ICConfigurationDescription cfg){
CContainerRef[] refs = CExternalSettingsManager.getInstance().getReferences(cfg, FACTORY_ID);
String[] ids = new String[refs.length];
for(int i = 0; i < refs.length; i++){
ids[i] = refs[i].getContainerId();
}
return ids;
}
public static void setReferencedProviderIds(ICConfigurationDescription cfg, String ids[]){
Set<String> newIdsSet = new HashSet<String>(Arrays.asList(ids));
Set<String> oldIdsSet = new HashSet<String>(Arrays.asList(getReferencedProviderIds(cfg)));
Set<String> newIdsSetCopy = new HashSet<String>(newIdsSet);
newIdsSet.removeAll(oldIdsSet);
oldIdsSet.removeAll(newIdsSetCopy);
if(oldIdsSet.size() != 0){
for (String string : oldIdsSet) {
removeReference(cfg, string);
}
}
if(newIdsSet.size() != 0){
for (String string : newIdsSet) {
createReference(cfg, string);
}
}
}
public static void updateReferencedProviderIds(String ids[], IProgressMonitor monitor){
ExtensionContainerFactory instance = getInstanceInitialized();
CExternalSettingsContainerChangeInfo[] changeInfos =
new CExternalSettingsContainerChangeInfo[ids.length];
for(int i = 0; i < changeInfos.length; i++){
changeInfos[i] = new CExternalSettingsContainerChangeInfo(
CExternalSettingsContainerChangeInfo.CONTAINER_CONTENTS,
new CContainerRef(FACTORY_ID, ids[i]),
null);
}
instance.notifySettingsChange(null, null, changeInfos);
if(monitor != null)
monitor.done();
}
public static void updateReferencedProviderIds(ICConfigurationDescription cfg, String ids[]){
Set<String> newIdsSet = new HashSet<String>(Arrays.asList(ids));
Set<String> oldIdsSet = new HashSet<String>(Arrays.asList(getReferencedProviderIds(cfg)));
Set<String> newIdsSetCopy = new HashSet<String>(newIdsSet);
newIdsSetCopy.removeAll(oldIdsSet);
newIdsSet.removeAll(newIdsSetCopy);
if(newIdsSet.size() != 0){
for (String string : newIdsSet) {
providerChanged(cfg, string);
}
}
}
private static void createReference(ICConfigurationDescription cfg, String id){
CContainerRef cr = createContainerRef(id);
CExternalSettingsManager.getInstance().addContainer(cfg, cr);
}
private static void providerChanged(ICConfigurationDescription cfg, String id){
CContainerRef cr = createContainerRef(id);
CExternalSettingsManager.getInstance().containerContentsChanged(cfg, cr);
}
private static void removeReference(ICConfigurationDescription cfg, String id){
CContainerRef cr = createContainerRef(id);
CExternalSettingsManager.getInstance().removeContainer(cfg, cr);
}
private static CContainerRef createContainerRef(String id){
return new CContainerRef(FACTORY_ID, id);
}
}