1
/*******************************************************************************
2
* Copyright (c) 2007 Intel Corporation and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* Intel Corporation - Initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.internal.core.settings.model;
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.Iterator;
17
import java.util.List;
21
import org.eclipse.cdt.core.CCorePlugin;
22
import org.eclipse.cdt.core.settings.model.CExternalSetting;
23
import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent;
24
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
25
import org.eclipse.cdt.core.settings.model.ICLanguageSetting;
26
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
27
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener;
28
import org.eclipse.cdt.core.settings.model.ICStorageElement;
29
import org.eclipse.cdt.internal.core.settings.model.CExternalSettinsDeltaCalculator.ExtSettingsDelta;
30
import org.eclipse.core.resources.IProject;
31
import org.eclipse.core.resources.IWorkspaceRunnable;
32
import org.eclipse.core.resources.ResourcesPlugin;
33
import org.eclipse.core.runtime.CoreException;
34
import org.eclipse.core.runtime.IProgressMonitor;
35
import org.eclipse.core.runtime.NullProgressMonitor;
36
import org.eclipse.core.runtime.QualifiedName;
38
public class CExternalSettingsManager implements ICExternalSettingsListener, ICProjectDescriptionListener{
39
private static final int OP_CHANGED = 1;
40
private static final int OP_ADDED = 2;
41
private static final int OP_REMOVED = 3;
43
private static final QualifiedName EXTERNAL_SETTING_PROPERTY = new QualifiedName(CCorePlugin.PLUGIN_ID, "externalSettings"); //$NON-NLS-1$
44
private static final String EXTERNAL_SETTING_STORAGE_ID = CCorePlugin.PLUGIN_ID + ".externalSettings"; //$NON-NLS-1$
46
private Map fFactoryMap = new HashMap();
47
private static CExternalSettingsManager fInstance;
49
public static class SettingsUpdateStatus {
50
ICProjectDescription fDes;
53
SettingsUpdateStatus(ICProjectDescription des, boolean isChanged){
55
fIsChanged = isChanged;
58
public ICProjectDescription getCProjectDescription(){
62
public boolean isChanged(){
66
private CExternalSettingsManager(){
69
public void startup(){
70
CProjectDescriptionManager.getInstance().addCProjectDescriptionListener(this, CProjectDescriptionEvent.DATA_APPLIED
71
| CProjectDescriptionEvent.LOADED);
74
public void shutdown(){
75
for(Iterator iter = fFactoryMap.values().iterator(); iter.hasNext();){
76
FactoryDescriptor dr = (FactoryDescriptor)iter.next();
81
CProjectDescriptionManager.getInstance().removeCProjectDescriptionListener(this);
85
public static CExternalSettingsManager getInstance(){
86
if(fInstance == null){
87
fInstance = new CExternalSettingsManager();
92
public final static class CContainerRef {
93
private String fFactoryId;
94
private String fContainerId;
96
public CContainerRef(String factoryId, String containerId){
97
fFactoryId = factoryId;
98
fContainerId = containerId;
101
public String getFactoryId() {
105
public String getContainerId() {
110
public boolean equals(Object obj) {
117
if(!(obj instanceof CContainerRef))
120
CContainerRef other = (CContainerRef)obj;
122
if(!fContainerId.equals(other.fContainerId))
125
return fFactoryId.equals(other.fFactoryId);
129
public int hashCode() {
130
return fFactoryId.hashCode() + fContainerId.hashCode();
134
public String toString() {
135
return fFactoryId.toString() + " : " + fContainerId.toString(); //$NON-NLS-1$
138
private static class ContainerDescriptor {
139
private FactoryDescriptor fFactoryDr;
140
// private String fContainerId;
141
// private String fProjectName;
142
// private String fCfgId;
143
private CExternalSettingsHolder fHolder;
145
private CExternalSettingsContainer fContainer;
147
private ContainerDescriptor(FactoryDescriptor factoryDr,
150
ICConfigurationDescription cfgDes){
151
fFactoryDr = factoryDr;
152
// fContainerId = containerId;
153
// fProjectName = project.getName();
154
// fCfgId = cfgDes.getId();
156
fContainer = fFactoryDr.getFactory().createContainer(containerId, project, cfgDes);
157
} catch (CoreException e) {
159
if(fContainer == null)
160
fContainer = NullContainer.INSTANCE;
163
public CExternalSetting[] getExternalSettings(){
165
fHolder = new CExternalSettingsHolder();
166
fHolder.setExternallSettings(fContainer.getExternalSettings());
168
return fHolder.getExternalSettings();
171
// public CExternalSettingsContainer getContainer(){
172
// if(fContainer == null){
173
// IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(fProjectName);
175
// fContainer = fFactoryDr.getFactory().createContainer(fContainerId, project, fCfgId);
176
// } catch (CoreException e) {
177
// CCorePlugin.log(e);
179
// if(fContainer == null)
180
// fContainer = NullContainer.INSTANCE;
182
// return fContainer;
186
static class NullContainer extends CExternalSettingsContainer {
187
static final NullContainer INSTANCE = new NullContainer();
190
public CExternalSetting[] getExternalSettings() {
191
return new CExternalSetting[0];
195
private static class NullFactory extends CExternalSettingContainerFactory {
196
static NullFactory INSTANCE = new NullFactory();
199
public void addListener(ICExternalSettingsListener listener) {
203
public CExternalSettingsContainer createContainer(String id,
204
IProject project, ICConfigurationDescription cfgDes) throws CoreException {
205
return NullContainer.INSTANCE;
208
public String[] getSupplierIds() {
213
public void removeListener(ICExternalSettingsListener listener) {
217
public void shutdown() {
221
public void startup() {
225
private class FactoryDescriptor {
226
private CExternalSettingContainerFactory fFactory;
228
// private Map fContainerMap;
230
private FactoryDescriptor(String id){
234
private CExternalSettingContainerFactory getFactory(){
235
if(fFactory == null){
236
fFactory = createFactory(fId);
238
fFactory.addListener(CExternalSettingsManager.this);
243
private CExternalSettingContainerFactory createFactory(String id) {
244
if(id.equals(CfgExportSettingContainerFactory.FACTORY_ID))
245
return CfgExportSettingContainerFactory.getInstance();
246
else if(id.equals(ExtensionContainerFactory.FACTORY_ID))
247
return ExtensionContainerFactory.getInstance();
248
return NullFactory.INSTANCE;
251
public String getId(){
255
public void shutdown(){
256
if(fFactory != null){
257
fFactory.removeListener(CExternalSettingsManager.this);
264
private interface ICfgContainer {
265
ICConfigurationDescription getConfguration(boolean write);
267
// boolean isWritable();
270
private class CfgContainer implements ICfgContainer {
271
private ICConfigurationDescription fCfgDes;
273
CfgContainer(ICConfigurationDescription cfgDes){
277
public ICConfigurationDescription getConfguration(boolean write) {
283
private interface ICRefInfoContainer {
284
CSettingsRefInfo getRefInfo(boolean write);
287
private class CfgContainerRefInfoContainer implements ICRefInfoContainer{
288
private ICfgContainer fCfgContainer;
289
private CSettingsRefInfo fRefInfo;
290
private boolean fWriteWasRequested;
292
CfgContainerRefInfoContainer(ICfgContainer container){
293
fCfgContainer = container;
296
public CSettingsRefInfo getRefInfo(boolean write) {
298
|| (write && !fWriteWasRequested)){
299
ICConfigurationDescription cfg = fCfgContainer.getConfguration(write);
300
fRefInfo = CExternalSettingsManager.this.getRefInfo(cfg, write);
301
fWriteWasRequested |= write;
307
// private class CfgRefInfoContainer implements ICRefInfoContainer{
308
// private CSettingsRefInfo fRefInfo;
309
// private ICConfigurationDescription fCfgDes;
310
// private boolean fWriteWasRequested;
312
// CfgRefInfoContainer(ICConfigurationDescription cfg){
316
// public CSettingsRefInfo getRefInfo(boolean write) {
317
// if(fRefInfo == null
318
// || (write && !fWriteWasRequested)){
319
// ICConfigurationDescription cfg = fCfgDes;
320
// fRefInfo = CExternalSettingsManager.this.getRefInfo(cfg, write);
321
// fWriteWasRequested |= write;
327
private class HolderContainer {
328
private ICRefInfoContainer fRIContainer;
329
private CRefSettingsHolder fHolder;
330
private boolean fWriteWasRequested;
331
private CContainerRef fCRef;
333
HolderContainer(ICRefInfoContainer cr, CContainerRef cref){
338
CRefSettingsHolder getHolder(boolean write){
340
|| (write && !fWriteWasRequested)){
341
CSettingsRefInfo ri = fRIContainer.getRefInfo(write);
342
fHolder = ri.get(fCRef);
343
fWriteWasRequested |= write;
348
void setHolder(CRefSettingsHolder holder){
349
fRIContainer.getRefInfo(true).put(holder);
350
fWriteWasRequested = true;
355
fWriteWasRequested = true;
357
fRIContainer.getRefInfo(true).remove(fCRef);
361
private static class CfgListCfgContainer implements ICfgContainer{
362
private ICfgList fList;
365
CfgListCfgContainer(ICfgList list, int num){
370
public ICConfigurationDescription getConfguration(boolean write) {
371
return fList.get(fNum, write);
374
// public boolean isWritable() {
375
// return !getConfguration(false).isReadOnly();
379
private interface ICfgList {
380
ICConfigurationDescription get(int num, boolean write);
385
private static class ProjDesCfgList implements ICfgList{
386
private ICProjectDescription fProjDes;
387
private List fCfgList = new ArrayList();
389
public ProjDesCfgList(ICProjectDescription des, Set idSet){
391
ICConfigurationDescription[] cfgs = des.getConfigurations();
392
for(int i = 0; i < cfgs.length; i++){
393
if(idSet == null || idSet.contains(cfgs[i].getId()))
394
fCfgList.add(cfgs[i]);
398
public boolean isWritable(){
399
return !fProjDes.isReadOnly();
402
public ICConfigurationDescription get(int num, boolean write) {
403
if(write && fProjDes.isReadOnly()){
406
return (ICConfigurationDescription)fCfgList.get(num);
409
private void makeWritable(){
410
ICProjectDescription writeDes = CProjectDescriptionManager.getInstance().getProjectDescription(fProjDes.getProject());
412
for(int i = 0; i < fCfgList.size(); i++){
413
ICConfigurationDescription cfg = (ICConfigurationDescription)fCfgList.get(i);
414
cfg = writeDes.getConfigurationById(cfg.getId());
416
fCfgList.set(i, cfg);
422
public int getNumForId(String id){
423
for(int i = 0; i < fCfgList.size(); i++){
424
ICConfigurationDescription cfg = (ICConfigurationDescription)fCfgList.get(i);
425
if(id.equals(cfg.getId()))
431
public ICConfigurationDescription getConfigurationById(String id, boolean write){
432
ICConfigurationDescription cfg = fProjDes.getConfigurationById(id);
435
if(write && fProjDes.isReadOnly()){
437
cfg = fProjDes.getConfigurationById(id);
443
return fCfgList.size();
447
private static class DeltaInfo{
448
private boolean fCalculated;
449
private ExtSettingsDelta[] fDeltas;
451
void setDelta(ExtSettingsDelta[] deltas){
457
private FactoryDescriptor getFactoryDescriptor(String id){
458
FactoryDescriptor dr = (FactoryDescriptor)fFactoryMap.get(id);
460
dr = new FactoryDescriptor(id);
461
fFactoryMap.put(id, dr);
466
CExternalSettingContainerFactory getFactory(String id){
467
FactoryDescriptor dr = getFactoryDescriptor(id);
468
return dr.getFactory();
471
private ContainerDescriptor createDescriptor(String factoryId,
474
ICConfigurationDescription cfgDes
476
FactoryDescriptor dr = getFactoryDescriptor(factoryId);
477
return new ContainerDescriptor(dr, containerId, project, cfgDes);
480
public void settingsChanged(IProject project, String cfgId,
481
CExternalSettingChangeEvent event) {
482
ProjDesCfgList[] lists = null;
483
CExternalSettingsContainerChangeInfo[] infos = event.getChangeInfos();
484
for(int i = 0; i < infos.length; i++){
485
CExternalSettingsContainerChangeInfo info = infos[i];
486
switch(info.getEventType()){
487
case CExternalSettingsContainerChangeInfo.CHANGED:
488
int flags = info.getChangeFlags();
489
if((flags & CExternalSettingsContainerChangeInfo.CONTAINER_CONTENTS) != 0){
491
lists = createCfgListsForEvent(project, cfgId);
492
containerContentsChanged(lists, info.getContainerInfo(), null);
503
private void applyLists(ProjDesCfgList[] lists){
504
final List list = getModifiedProjDesList(lists);
505
if(list.size() != 0){
506
IWorkspaceRunnable r = new IWorkspaceRunnable(){
508
public void run(IProgressMonitor monitor) throws CoreException {
509
for(int i = 0; i < list.size(); i++){
510
ICProjectDescription des = (ICProjectDescription)list.get(i);
511
CProjectDescriptionManager.getInstance().setProjectDescription(des.getProject(), des, false, monitor);
517
CProjectDescriptionManager.getInstance().runWspModification(r, new NullProgressMonitor());
521
private List getModifiedProjDesList(ProjDesCfgList[] lists){
522
List list = new ArrayList();
523
for(int i = 0; i < lists.length; i++){
524
if(lists[i].isWritable())
525
list.add(lists[i].fProjDes);
530
private void containerContentsChanged(ProjDesCfgList[] lists, CContainerRef ref, DeltaInfo deltaInfo){
531
for(int i = 0; i < lists.length; i++){
532
containerContentsChanged(lists[i], null, ref, deltaInfo);
536
private ProjDesCfgList[] createCfgListsForEvent(IProject project, String cfgId){
537
ProjDesCfgList lists[];
539
ProjDesCfgList l = createCfgList(project, cfgId);
541
lists = new ProjDesCfgList[1];
544
lists = new ProjDesCfgList[0];
547
lists = createCfgLists();
552
private ProjDesCfgList[] createCfgLists(){
553
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
554
List list = new ArrayList();
555
for(int i = 0; i < projects.length; i++){
556
ProjDesCfgList l = createCfgList(projects[i], (Set)null);
560
return (ProjDesCfgList[])list.toArray(new ProjDesCfgList[list.size()]);
563
private ProjDesCfgList createCfgList(IProject project, String cfgId){
570
return createCfgList(project, set);
573
private ProjDesCfgList createCfgList(IProject project, Set cfgIdSet){
574
ICProjectDescription des = CProjectDescriptionManager.getInstance().getProjectDescription(project, false);
578
return new ProjDesCfgList(des, cfgIdSet);
581
private void containerContentsChanged(ProjDesCfgList list, String[]cfgIds, CContainerRef ref, DeltaInfo deltaInfo){
582
if(cfgIds != null && cfgIds.length != 0){
583
for(int i = 0; i < cfgIds.length; i++){
584
int num = list.getNumForId(cfgIds[i]);
586
CfgListCfgContainer cr = new CfgListCfgContainer(list, num);
587
containerContentsChanged(cr, ref, deltaInfo);
591
for(int i = 0; i < list.size(); i++){
592
CfgListCfgContainer cr = new CfgListCfgContainer(list, i);
593
containerContentsChanged(cr, ref, deltaInfo);
599
private boolean containerContentsChanged(ICfgContainer cr, CContainerRef ref, DeltaInfo deltaInfo){
600
return processContainerChange(OP_CHANGED, cr, ref, deltaInfo);
603
private boolean processContainerChange(int op,
605
CContainerRef crInfo,
606
DeltaInfo deltaInfo){
607
return processContainerChange(op, cr, new CfgContainerRefInfoContainer(cr), crInfo, deltaInfo);
610
private boolean processContainerChange(int op,
612
ICRefInfoContainer riContainer,
613
CContainerRef crInfo,
614
DeltaInfo deltaInfo){
616
ICConfigurationDescription cfg = cr.getConfguration(false);
618
ExtSettingsDelta[] deltas = checkExternalSettingsChange(op,
619
cfg.getProjectDescription().getProject(), cfg, riContainer, crInfo);
622
return applyDeltas(cr, deltas);
627
private boolean applyDeltas(ICfgContainer cr, ExtSettingsDelta[] deltas){
628
return CExternalSettingsDeltaProcessor.applyDelta(cr.getConfguration(true), deltas);
631
private static class RefInfoContainer{
632
CSettingsRefInfo fRefInfo;
635
RefInfoContainer(CSettingsRefInfo ri, int id){
641
private CSettingsRefInfo getRefInfo(ICConfigurationDescription cfg, boolean write){
642
if(write && cfg.isReadOnly())
643
throw new IllegalArgumentException(SettingsModelMessages.getString("CExternalSettingsManager.3")); //$NON-NLS-1$
645
RefInfoContainer cr = (RefInfoContainer)cfg.getSessionProperty(EXTERNAL_SETTING_PROPERTY);
647
boolean setCr = false;
651
ri = new CSettingsRefInfo();
653
} else if (write && cr.fInstanceId != cfg.hashCode()){
654
ri = new CSettingsRefInfo(cr.fRefInfo);
662
cr = new RefInfoContainer(ri, cfg.hashCode());
663
cfg.setSessionProperty(EXTERNAL_SETTING_PROPERTY, cr);
669
private CSettingsRefInfo load(ICConfigurationDescription cfg){
671
ICStorageElement el = cfg.getStorage(EXTERNAL_SETTING_STORAGE_ID, false);
673
CSettingsRefInfo ri = new CSettingsRefInfo(el);
676
} catch (CoreException e) {
682
public void handleEvent(CProjectDescriptionEvent event) {
683
switch(event.getEventType()){
684
case CProjectDescriptionEvent.DATA_APPLIED:
685
checkStore(event.getNewCProjectDescription());
687
case CProjectDescriptionEvent.LOADED:
688
final SettingsUpdateStatus status = update(event.getNewCProjectDescription());
689
if(status.isChanged()){
690
IWorkspaceRunnable r = new IWorkspaceRunnable(){
692
public void run(IProgressMonitor monitor) throws CoreException {
693
ICProjectDescription des = status.getCProjectDescription();
694
CProjectDescriptionManager.getInstance().setProjectDescription(des.getProject(), des);
698
CProjectDescriptionManager.getInstance().runWspModification(r, null);
704
private void checkStore(ICProjectDescription des){
708
ICConfigurationDescription[] cfgs = des.getConfigurations();
709
for(int i = 0; i < cfgs.length; i++){
714
private void checkStore(ICConfigurationDescription cfg){
715
RefInfoContainer cr = (RefInfoContainer)cfg.getSessionProperty(EXTERNAL_SETTING_PROPERTY);
716
if(cr != null/* && cr.fInstanceId != cfg.hashCode()*/){
717
store(cfg, cr.fRefInfo);
721
private void store(ICConfigurationDescription cfg, CSettingsRefInfo ri){
723
ICStorageElement el = cfg.getStorage(EXTERNAL_SETTING_STORAGE_ID, true);
726
} catch (CoreException e) {
731
public void containerContentsChanged(ICConfigurationDescription cfg, CContainerRef cr){
732
CfgContainer ccr = new CfgContainer(cfg);
733
containerContentsChanged(ccr, cr, null);
736
public void addContainer(ICConfigurationDescription cfg, CContainerRef cr){
737
CfgContainer ccr = new CfgContainer(cfg);
738
processContainerChange(OP_ADDED, ccr, cr, null);
741
public void removeContainer(ICConfigurationDescription cfg, CContainerRef cr){
742
CfgContainer ccr = new CfgContainer(cfg);
743
processContainerChange(OP_REMOVED, ccr, cr, null);
746
public CContainerRef[] getReferences(ICConfigurationDescription cfg, String factoryId){
747
CSettingsRefInfo info = getRefInfo(cfg, false);
748
return info.getReferences(factoryId);
751
public SettingsUpdateStatus update(ICProjectDescription des){
752
ProjDesCfgList list = new ProjDesCfgList(des, null);
753
boolean changed = false;
754
for(int i = 0; i < list.size(); i++){
755
CfgListCfgContainer cfgCr = new CfgListCfgContainer(list, i);
756
CfgContainerRefInfoContainer ric = new CfgContainerRefInfoContainer(cfgCr);
757
CContainerRef[] refs = ric.getRefInfo(false).getReferences();
758
for(int k = 0; k < refs.length; k++){
759
if(containerContentsChanged(cfgCr, refs[k], null))
763
return new SettingsUpdateStatus(list.fProjDes, changed);
766
private ExtSettingsDelta[] checkExternalSettingsChange(int op,
768
ICConfigurationDescription cfgDes,
769
ICRefInfoContainer riContainer,
771
HolderContainer hCr = new HolderContainer(riContainer, cr);
772
CRefSettingsHolder holder = hCr.getHolder(false);
773
if(holder == null && op == OP_ADDED){
774
holder = new CRefSettingsHolder(cr);
775
hCr.setHolder(holder);
781
ExtSettingsDelta[] deltas = reconsile(proj, cfgDes, op != OP_REMOVED, hCr, cr);
788
private ExtSettingsDelta[] reconsile(IProject proj, ICConfigurationDescription cfgDes, boolean add, HolderContainer hCr, CContainerRef cr){
789
// if(holder.isReconsiled())
791
CExternalSetting[] newSettings = null;
792
CExternalSetting[] oldSettings = hCr.getHolder(false).getExternalSettings();
794
ContainerDescriptor cdr = createDescriptor(cr.getFactoryId(), cr.getContainerId(), proj, cfgDes);
795
newSettings = cdr.getExternalSettings();
798
ExtSettingsDelta[] deltas = getDeltaCalculator().getSettingChange(newSettings, oldSettings);
800
CRefSettingsHolder holder = hCr.getHolder(true);
801
holder.setExternallSettings(newSettings);
802
holder.setReconsiled(true);
807
private CExternalSettinsDeltaCalculator getDeltaCalculator(){
808
return CExternalSettinsDeltaCalculator.getInstance();
811
public void restoreSourceEntryDefaults(ICConfigurationDescription cfg){
812
CfgContainer cr = new CfgContainer(cfg);
813
CfgContainerRefInfoContainer ric = new CfgContainerRefInfoContainer(cr);
814
CExternalSetting[] settings = ric.getRefInfo(false).createExternalSettings();
815
ExtSettingsDelta[] deltas = getDeltaCalculator().getSettingChange(settings, null);
817
CExternalSettingsDeltaProcessor.applySourceEntriesChange(cfg, deltas);
821
public void restoreOutputEntryDefaults(ICConfigurationDescription cfg){
822
CfgContainer cr = new CfgContainer(cfg);
823
CfgContainerRefInfoContainer ric = new CfgContainerRefInfoContainer(cr);
824
CExternalSetting[] settings = ric.getRefInfo(false).createExternalSettings();
825
ExtSettingsDelta[] deltas = getDeltaCalculator().getSettingChange(settings, null);
827
CExternalSettingsDeltaProcessor.applyOutputEntriesChange(cfg, deltas);
831
public void restoreDefaults(ICLanguageSetting ls, int entryKinds){
832
ICConfigurationDescription cfg = ls.getConfiguration();
833
CfgContainer cr = new CfgContainer(cfg);
834
CfgContainerRefInfoContainer ric = new CfgContainerRefInfoContainer(cr);
835
CExternalSetting[] settings = ric.getRefInfo(false).createExternalSettings();
836
ExtSettingsDelta[] deltas = getDeltaCalculator().getSettingChange(settings, null);
838
CExternalSettingsDeltaProcessor.applyDelta(ls, deltas, entryKinds);