From c931ca6163773c99c67f79a041bf2d5751da31e9 Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Fri, 20 Aug 2004 20:29:57 +0000 Subject: [PATCH] 2004-08-18 Alain Magloire Work on the ResolverModel, we make the Core Model aware of the changes. Noticeable changes ICFileTypeResolver is tied to a container, this change things considerably when extending the implementations. Sam orignal works did not with some pros && cons .. this also has pros and cons. * model/org/eclipse/cdt/internal/core/model/CModelManager.java * model/org/eclipse/cdt/internal/core/model/ResolverProcessor.java * src/org/eclipse/cdt/core/filetype/ICFielTypeResolver.java * src/org/eclipse/cdt/core/filetype/IResolverChangeListener.java * src/org/eclipse/cdt/core/filetype/IResolverModel.java * src/org/eclipse/cdt/core/filetype/ResolverChangeEvent.java * src/org/eclipse/cdt/core/filetype/ResolverDelta.java * src/org/eclipse/cdt/core/internal/filetype/CFileTypeResolver.java * src/org/eclipse/cdt/core/internal/filetype/CustomResolver.java * src/org/eclipse/cdt/core/internal/filetype/ResolverModel.java * src/org/eclipse/cdt/core/internal/filetype/WorkspaceResolver.java --- core/org.eclipse.cdt.core/ChangeLog | 21 + .../internal/core/model/CModelManager.java | 4 +- .../core/model/ResolverProcessor.java | 123 ++- .../cdt/core/filetype/ICFileTypeResolver.java | 30 +- .../filetype/IResolverChangeListener.java | 2 +- .../cdt/core/filetype/IResolverModel.java | 45 +- .../core/filetype/ResolverChangeEvent.java | 158 ++-- .../cdt/core/filetype/ResolverDelta.java | 110 +++ .../internal/filetype/CFileTypeResolver.java | 171 ++-- .../internal/filetype/CustomResolver.java | 311 +++++++ .../core/internal/filetype/ResolverModel.java | 766 +++++++----------- .../internal/filetype/WorkspaceResolver.java | 303 +++++++ 12 files changed, 1292 insertions(+), 752 deletions(-) create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ResolverDelta.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/CustomResolver.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/WorkspaceResolver.java diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 6f0c2e87061..bc582b7e526 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,24 @@ +2004-08-18 Alain Magloire + + Work on the ResolverModel, we make the Core Model aware of the changes. + Noticeable changes ICFileTypeResolver is tied to a container, this change + things considerably when extending the implementations. Sam orignal works + did not with some pros && cons .. this also has pros and cons. + + * model/org/eclipse/cdt/internal/core/model/CModelManager.java + * model/org/eclipse/cdt/internal/core/model/ResolverProcessor.java + + * src/org/eclipse/cdt/core/filetype/ICFielTypeResolver.java + * src/org/eclipse/cdt/core/filetype/IResolverChangeListener.java + * src/org/eclipse/cdt/core/filetype/IResolverModel.java + * src/org/eclipse/cdt/core/filetype/ResolverChangeEvent.java + * src/org/eclipse/cdt/core/filetype/ResolverDelta.java + + * src/org/eclipse/cdt/core/internal/filetype/CFileTypeResolver.java + * src/org/eclipse/cdt/core/internal/filetype/CustomResolver.java + * src/org/eclipse/cdt/core/internal/filetype/ResolverModel.java + * src/org/eclipse/cdt/core/internal/filetype/WorkspaceResolver.java + 2004-08-18 Alain Magloire When running the CDescriptorOperation make sure we have an ICDescriptor. diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java index afbe4bf12cd..8ad9155ccdc 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java @@ -739,8 +739,8 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe /* (non-Javadoc) * @see org.eclipse.cdt.core.filetype.IResolverChangeListener#resolverChanged(org.eclipse.cdt.core.filetype.ResolverChangeEvent) */ - public void resolverChanged(ResolverChangeEvent[] events) { - fResolverProcessor.processResolverChanges(events); + public void resolverChanged(ResolverChangeEvent event) { + fResolverProcessor.processResolverChanges(event); } public void fire(int eventType) { diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ResolverProcessor.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ResolverProcessor.java index 1f8ec449f8e..2a7474007c2 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ResolverProcessor.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ResolverProcessor.java @@ -11,21 +11,20 @@ package org.eclipse.cdt.internal.core.model; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - import org.eclipse.cdt.core.filetype.ICFileTypeAssociation; import org.eclipse.cdt.core.filetype.ResolverChangeEvent; +import org.eclipse.cdt.core.filetype.ResolverDelta; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ElementChangedEvent; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IOpenable; +import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; /** * ResolverProcessor @@ -35,43 +34,29 @@ public class ResolverProcessor { CModelManager fManager; CElementDelta fCurrentDelta; - public void processResolverChanges(ResolverChangeEvent[] events) { + public void processResolverChanges(ResolverChangeEvent event) { ICElement root = CModelManager.getDefault().getCModel(); fCurrentDelta = new CElementDelta(root); fManager = CModelManager.getDefault(); - - // Regroup the events per container. - Map map = new HashMap(); - for (int i = 0; i < events.length; ++i) { - IContainer container = events[i].getContainer(); - List list = (List)map.get(container); - if (list == null) { - list = new ArrayList(); - map.put(container, list); - } - list.add(events[i]); - } // Go through the events and generate deltas CModelManager manager = CModelManager.getDefault(); - Iterator entries = map.entrySet().iterator(); - while (entries.hasNext()) { - Map.Entry entry = (Map.Entry)entries.next(); - List list = (List)entry.getValue(); - for (int i = 0; i < list.size(); ++i) { - ResolverChangeEvent event = (ResolverChangeEvent)list.get(i); - if (event.getElementType() ==ResolverChangeEvent.ELEMENT_ASSOCIATION) { - IContainer container = (IContainer)entry.getKey(); - ICElement celement = CoreModel.getDefault().create(container); - ICFileTypeAssociation association = (ICFileTypeAssociation)event.getElement(); + ResolverDelta[] deltas = event.getDeltas(); + IContainer container = event.getResolver().getContainer(); + ICElement celement = CoreModel.getDefault().create(container); + for (int i = 0; i < deltas.length; ++i) { + ResolverDelta delta = deltas[i]; + if (delta.getElementType() == ResolverDelta.ELEMENT_ASSOCIATION) { + ICFileTypeAssociation association = (ICFileTypeAssociation)delta.getElement(); + if (association.getType().isTranslationUnit()) { try { - switch (event.getEventType()) { - case ResolverChangeEvent.EVENT_ADD: - add(celement, association); - break; - case ResolverChangeEvent.EVENT_REMOVE: - remove(celement, association); - break; + switch (delta.getEventType()) { + case ResolverDelta.EVENT_ADD: + add(celement, association); + break; + case ResolverDelta.EVENT_REMOVE: + remove(celement, association); + break; } } catch (CModelException e) { // @@ -79,43 +64,42 @@ public class ResolverProcessor { } } } - fManager.fire(fCurrentDelta, ElementChangedEvent.POST_CHANGE); + if (fCurrentDelta.getAffectedChildren().length > 0) { + fManager.fire(fCurrentDelta, ElementChangedEvent.POST_CHANGE); + } } void add(ICElement celement, ICFileTypeAssociation association) throws CModelException { if (celement instanceof IOpenable) { int type = celement.getElementType(); if (type < ICElement.C_UNIT) { - Object[] elements = null; CElementInfo info = (CElementInfo)fManager.peekAtInfo(celement); if (info != null) { - switch (celement.getElementType()) { - case ICElement.C_MODEL: - elements = ((CModelInfo)info).getNonCResources(); - break; - case ICElement.C_PROJECT: - elements = ((CProjectInfo)info).getNonCResources(celement.getResource()); - break; - case ICElement.C_CCONTAINER: - elements = ((CContainerInfo)info).getNonCResources(celement.getResource()); - break; - } - } - if (elements != null) { - for (int i = 0; i < elements.length; ++i) { - if (elements[i] instanceof IFile) { - IFile file = (IFile) elements[i]; - if (association.matches(file.getName())) { - ICElement newElement = CoreModel.getDefault().create(file); - if (newElement != null) { - elementAdded(newElement, celement); + try { + IResource resource = celement.getResource(); + IResource[] members = null; + if (resource instanceof IContainer) { + members = ((IContainer)resource).members(); + } + if (members != null) { + for (int i = 0; i < members.length; ++i) { + if (members[i] instanceof IFile) { + IFile file = (IFile) members[i]; + if (association.matches(file.getName())) { + ICElement newElement = CoreModel.getDefault().create(file); + if (newElement != null) { + elementAdded(newElement, celement); + } + } } } + ICElement[] celements = info.getChildren(); + for (int i = 0; i < celements.length; ++i) { + add(celements[i], association); + } } - } - ICElement[] celements = info.getChildren(); - for (int i = 0; i < celements.length; ++i) { - add(celements[i], association); + } catch (CoreException e) { + // } } } @@ -126,9 +110,8 @@ public class ResolverProcessor { if (celement instanceof IOpenable) { int type = celement.getElementType(); if (type < ICElement.C_UNIT) { - CElementInfo info = (CElementInfo)fManager.peekAtInfo(celement); - if (info instanceof CElementInfo) { - CElementInfo cinfo = (CElementInfo)info; + CElementInfo cinfo = (CElementInfo)fManager.peekAtInfo(celement); + if (cinfo != null) { ICElement[] celements = cinfo.getChildren(); for (int i = 0; i < celements.length; ++i) { if (celements[i].getElementType() == ICElement.C_UNIT) { @@ -162,6 +145,16 @@ public class ResolverProcessor { break; case ICElement.C_CCONTAINER: ((CContainerInfo)info).setNonCResources(null); + if (parent instanceof ISourceRoot) { + // if sourceRoot == Project we nee to update the nonCResource of the project also. + if (parent.getResource() instanceof IProject) { + ICElement cproject = parent.getCProject(); + CProjectInfo pinfo = (CProjectInfo)fManager.peekAtInfo(cproject); + if (pinfo != null) { + pinfo.setNonCResources(null); + } + } + } break; } } catch (CModelException e) { diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ICFileTypeResolver.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ICFileTypeResolver.java index 06448dc109d..bac59689794 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ICFileTypeResolver.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ICFileTypeResolver.java @@ -10,6 +10,8 @@ ***********************************************************************/ package org.eclipse.cdt.core.filetype; +import org.eclipse.core.resources.IContainer; + /** * Class responsible for resolving a file name into the * associated file type. @@ -32,16 +34,9 @@ public interface ICFileTypeResolver { */ public ICFileType getFileType(String fileName); - /** - * Add a new file type association to the resolver's list. - * @param assoc file name pattern to add. - * - * @return true if the file type association was added. - */ - public boolean addAssociation(ICFileTypeAssociation assoc); - /** * Add multiple file type associations to the resolver's list. + * This method does not fire delta changes use adjustAssociations. * * @param assocs array of file type associations to add; may be null. * @@ -49,17 +44,9 @@ public interface ICFileTypeResolver { */ public boolean addAssociations(ICFileTypeAssociation[] assocs); - /** - * Remove a file type association from the resolver's list. - * - * @param assoc file type association to remove. - * - * @return true if the file type association was removed. - */ - public boolean removeAssociation(ICFileTypeAssociation assoc); - /** * Remove multiple file type associations from the resolver's list. + * This method does not fire delta changes use adjustAssociations. * * @param assoc array of file type association to remove; may be null * @@ -70,7 +57,7 @@ public interface ICFileTypeResolver { /** * Add and/or remove associations from the resolver in a * batch operation. Either (or both) of the parameters - * may be null. + * may be null. This method fires delta change events. * * @param add associations to add to the resolver; may be null * @param rem associations to remove from the resolver; may be null @@ -88,4 +75,11 @@ public interface ICFileTypeResolver { * @return working copy of this file type resolver */ public ICFileTypeResolver createWorkingCopy(); + + /** + * The container of the resolver can be IWorkspaceRoot or IProject. + * + * @return + */ + public IContainer getContainer(); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/IResolverChangeListener.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/IResolverChangeListener.java index a00f5b21a7f..2a8b7ca0cf4 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/IResolverChangeListener.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/IResolverChangeListener.java @@ -15,5 +15,5 @@ package org.eclipse.cdt.core.filetype; * individual resolver. */ public interface IResolverChangeListener { - public void resolverChanged(ResolverChangeEvent[] events); + public void resolverChanged(ResolverChangeEvent event); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/IResolverModel.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/IResolverModel.java index 8c317bb0bd1..0b5fecf4f1b 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/IResolverModel.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/IResolverModel.java @@ -46,39 +46,42 @@ public interface IResolverModel { */ public ICFileType getFileTypeById(String typeId); - /** - * Set the resolver for the current workspace. - * - * The workspace resolver is set to the specified - * resolver, and the resolver data is persisted - * in the workspace. - * - * @param resolver new workspace resolver. - */ - public void setResolver(ICFileTypeResolver resolver); - /** * Get the resolver for the current workspace. * - * If the workspace resolver is unavailable (or - * identical to the default resolver), then the - * default resolver is returned. - * * @return workspace resolver */ public ICFileTypeResolver getResolver(); /** - * Set the resolver for the specified project. + * Create a custom resolver for the specified project. * - * The project resolver is set to the specified + * The project resolver is set to a custom * resolver, and the resolver data is persisted * in the project (in the .cdtproject file). - * - * @param project project this resolver applied to - * @param resolver new project resolver + * + * This method fires changed event + * + * @param project - project this resolver applied to + * @param copyResolver - retrieve associations for the copy to populate the custom resolver. */ - public void setResolver(IProject project, ICFileTypeResolver resolver); + public ICFileTypeResolver createCustomResolver(IProject project, ICFileTypeResolver copyResolver); + + /** + * Remove the custom resolver on the project. + * This method fires changed event + * + * @param project + */ + public void removeCustomResolver(IProject project); + + /** + * Return true if the project has a custom resolver. + * + * @param project + * @return true if a custom resolver + */ + public boolean hasCustomResolver(IProject project); /** * Get the resolver for the specified project. diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ResolverChangeEvent.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ResolverChangeEvent.java index 4dbe1075f8d..39829faf4d6 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ResolverChangeEvent.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ResolverChangeEvent.java @@ -10,127 +10,91 @@ ***********************************************************************/ package org.eclipse.cdt.core.filetype; +import java.util.ArrayList; import java.util.EventObject; +import java.util.Iterator; +import java.util.List; -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IProject; public class ResolverChangeEvent extends EventObject { - - public static final int EVENT_ADD = 0x10; - public static final int EVENT_REMOVE = 0x20; - public static final int EVENT_SET = 0x40; - public static final int EVENT_MASK = 0xF0; - public static final int ELEMENT_LANGUAGE = 0x01; - public static final int ELEMENT_FILETYPE = 0x02; - public static final int ELEMENT_ASSOCIATION = 0x04; - public static final int ELEMENT_RESOLVER = 0x08; - public static final int ELEMENT_MASK = 0x0F; - - private Object fElement; - private int fEventType; + private List fDeltas = new ArrayList(); + private ICFileTypeResolver fNewResolver; + private ICFileTypeResolver fOldResolver; /** - * Create a new change event. + * Create a new resolver change event. The event is empty + * of any change deltas, and references the provided file + * type resolver. * * @param resolver file type resolver this event applies to */ - public ResolverChangeEvent(IContainer container, int eventType, Object element) { - super(container); - fEventType = eventType; - fElement = element; + public ResolverChangeEvent(IResolverModel model, ICFileTypeResolver resolver) { + this(model, resolver, null); } - public IContainer getContainer() { - return (IContainer)getSource(); + /** + * Create a new resolver change event. The event is empty + * of any change deltas, and references the provided file + * type resolver. + * + * @param resolver file type resolver this event applies to + */ + public ResolverChangeEvent(IResolverModel model, ICFileTypeResolver newResolver, ICFileTypeResolver oldResolver) { + super(model); + fNewResolver = newResolver; + fOldResolver = oldResolver; } - public int getEventType() { - return fEventType & EVENT_MASK; + public boolean resolverHasChanged() { + return fOldResolver != null; } - public Object getElement() { - return fElement; + /** + * @return resolver affected by this change + */ + public ICFileTypeResolver getResolver() { + return fNewResolver; } - public int getElementType() { - if (fElement instanceof ICLanguage) { - return ELEMENT_LANGUAGE; - } else if (fElement instanceof ICFileType) { - return ELEMENT_FILETYPE; - } else if (fElement instanceof ICFileTypeAssociation) { - return ELEMENT_ASSOCIATION; - } else if (fElement instanceof ICFileTypeResolver) { - return ELEMENT_RESOLVER; - } - return 0; + /** + * @return number of resolver deltas involved in this change + */ + public int getDeltaCount() { + return fDeltas.size(); + } + + /** + * @return ResolverDelta[] for this change + */ + public ResolverDelta[] getDeltas() { + return (ResolverDelta[]) fDeltas.toArray(new ResolverDelta[fDeltas.size()]); } + /** + * Add a new delta to the list of deltas. + * + * @param delta instance of ResolverDelta to add to the list. + */ + public void addDelta(ResolverDelta delta) { + fDeltas.add(delta); + } public String toString() { StringBuffer buf = new StringBuffer(); - buf.append("ResolverChangeEvent ["); //$NON-NLS-1$ - - IContainer container = getContainer(); - if (container instanceof IProject) { - buf.append("For project "); //$NON-NLS-1$ - buf.append(container.getName()); - } else { - buf.append("For workspace"); //$NON-NLS-1$ + + buf.append("ResolverChangeEvent ["); + buf.append(fDeltas.size()); + buf.append(" delta(s)]"); + + for (Iterator iter = fDeltas.iterator(); iter.hasNext();) { + ResolverDelta element = (ResolverDelta) iter.next(); + buf.append("\n "); + buf.append(element.toString()); } - - buf.append(' '); - - switch (getEventType()) { - case EVENT_ADD: - buf.append("add"); //$NON-NLS-1$ - break; - case EVENT_REMOVE: - buf.append("remove"); //$NON-NLS-1$ - break; - case EVENT_SET: - buf.append("set"); //$NON-NLS-1$ - break; - default: - buf.append("?unknown event?"); //$NON-NLS-1$ - break; - } - buf.append(' '); - switch (getElementType()) { - case ELEMENT_LANGUAGE: - { - ICLanguage lang = (ICLanguage)getElement(); - buf.append("language "); //$NON-NLS-1$ - buf.append(lang.getName()); - break; - } - case ELEMENT_FILETYPE: - { - ICFileType fileType = (ICFileType)getElement(); - buf.append("filetype "); //$NON-NLS-1$ - buf.append(fileType.getName()); - break; - } - case ELEMENT_ASSOCIATION: - { - ICFileTypeAssociation association = (ICFileTypeAssociation)getElement(); - buf.append("assoc "); //$NON-NLS-1$ - buf.append(association.getPattern()); - break; - } - case ELEMENT_RESOLVER: - { - ICFileTypeResolver resolver = (ICFileTypeResolver)getElement(); - buf.append("resolver "); //$NON-NLS-1$ - break; - } - default: - buf.append("?unknown source?"); //$NON-NLS-1$ - break; - } - - buf.append(']'); + return buf.toString(); } + + } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ResolverDelta.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ResolverDelta.java new file mode 100644 index 00000000000..9dacca95ceb --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/filetype/ResolverDelta.java @@ -0,0 +1,110 @@ +/********************************************************************** + * Copyright (c) 2004 TimeSys Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * TimeSys Corporation - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.core.filetype; + + +public class ResolverDelta { + public static final int EVENT_ADD = 0x10; + public static final int EVENT_REMOVE = 0x20; + public static final int EVENT_SET = 0x40; + public static final int EVENT_MASK = 0xF0; + + public static final int ELEMENT_LANGUAGE = 0x01; + public static final int ELEMENT_FILETYPE = 0x02; + public static final int ELEMENT_ASSOCIATION = 0x04; + public static final int ELEMENT_MASK = 0x0F; + + private Object fElement; + private int fEvent; + + public ResolverDelta(int eventType, int elementType, Object element) { + fElement = element; + fEvent = eventType | elementType; + } + + public ResolverDelta(ICLanguage lang, int event) { + this(event, ELEMENT_LANGUAGE, lang); + } + + public ResolverDelta(ICFileType type, int event) { + this(event, ELEMENT_FILETYPE, type); + } + + public ResolverDelta(ICFileTypeAssociation assoc, int event) { + this(event, ELEMENT_ASSOCIATION, assoc); + } + + public Object getElement() { + return fElement; + } + + public int getElementType() { + return fEvent & ELEMENT_MASK; + } + + public int getEventType() { + return fEvent & EVENT_MASK; + } + + public ICLanguage getLanguage() { + return ((fElement instanceof ICLanguage) ? ((ICLanguage) fElement) : null); + } + + public ICFileType getFileType() { + return ((fElement instanceof ICFileType) ? ((ICFileType) fElement) : null); + } + + public ICFileTypeAssociation getAssociation() { + return ((fElement instanceof ICFileTypeAssociation) ? ((ICFileTypeAssociation) fElement) : null); + } + + public int getEvent() { + return fEvent; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + switch (getEventType()) { + case EVENT_ADD: + buf.append("add"); + break; + case EVENT_REMOVE: + buf.append("remove"); + break; + case EVENT_SET: + buf.append("set"); + break; + default: + buf.append("?unknown event?"); + break; + } + buf.append(" "); + switch (getElementType()) { + case ELEMENT_LANGUAGE: + buf.append("language "); + buf.append(null != getLanguage() ? getLanguage().getName() : "?"); + break; + case ELEMENT_FILETYPE: + buf.append("filetype "); + buf.append(null != getFileType() ? getFileType().getName() : "?"); + break; + case ELEMENT_ASSOCIATION: + buf.append("assoc "); + buf.append(null != getAssociation() ? getAssociation().getPattern() : "?"); + break; + default: + buf.append("?unknown source?"); + break; + } + + return buf.toString(); + } +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/CFileTypeResolver.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/CFileTypeResolver.java index 7e78449b815..26db7e3b7b4 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/CFileTypeResolver.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/CFileTypeResolver.java @@ -11,113 +11,142 @@ package org.eclipse.cdt.core.internal.filetype; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; -import java.util.Iterator; import java.util.List; import org.eclipse.cdt.core.filetype.ICFileType; import org.eclipse.cdt.core.filetype.ICFileTypeAssociation; import org.eclipse.cdt.core.filetype.ICFileTypeResolver; import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.ResourcesPlugin; -public class CFileTypeResolver implements ICFileTypeResolver { +public abstract class CFileTypeResolver implements ICFileTypeResolver { + // the container of the resolver protected IContainer fContainer; // The association list holds a list of known file associations. - protected List fAssocList = new ArrayList(); + protected List fAssocList; - public CFileTypeResolver() { - this(ResourcesPlugin.getWorkspace().getRoot()); - } public CFileTypeResolver(IContainer container) { fContainer = container; } - public ICFileTypeAssociation[] getFileTypeAssociations() { - return (ICFileTypeAssociation[]) fAssocList.toArray(new ICFileTypeAssociation[fAssocList.size()]); + /* (non-Javadoc) + * @see org.eclipse.cdt.core.filetype.ICFileTypeResolver#getContainer() + */ + public IContainer getContainer() { + return fContainer; } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.filetype.ICFileTypeResolver#addAssociations(org.eclipse.cdt.core.filetype.ICFileTypeAssociation[]) + */ + public boolean addAssociations(ICFileTypeAssociation[] assocs) { + return adjustAssociations(assocs, null, false); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.filetype.ICFileTypeResolver#getFileType(java.lang.String) + */ public ICFileType getFileType(String fileName) { - for (Iterator iter = fAssocList.iterator(); iter.hasNext();) { - ICFileTypeAssociation element = (ICFileTypeAssociation) iter.next(); + ICFileTypeAssociation[] assocs = getFileTypeAssociations(); + for (int i = 0; i < assocs.length; ++i) { + ICFileTypeAssociation element = assocs[i]; if (element.matches(fileName)) { return element.getType(); } } return ResolverModel.DEFAULT_FILE_TYPE; } - - //TODO: the add/remove methods do not generate change notifications... - // They really should be part of an IFileTypeResolverWorkingCopy interface - // For now, just be careful with them... - - public boolean addAssociation(ICFileTypeAssociation assoc) { - return addAssociations(new ICFileTypeAssociation[] { assoc } ); - } - - public boolean addAssociations(ICFileTypeAssociation[] assocs) { - return doAddAssociations(assocs); - } - - public boolean removeAssociation(ICFileTypeAssociation assoc) { - return removeAssociations(new ICFileTypeAssociation[] { assoc } ); - } - + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.filetype.ICFileTypeResolver#removeAssociations(org.eclipse.cdt.core.filetype.ICFileTypeAssociation[]) + */ public boolean removeAssociations(ICFileTypeAssociation[] assocs) { - return doRemoveAssociations(assocs); + return adjustAssociations(null, assocs, false); } - public boolean adjustAssociations(ICFileTypeAssociation[] add, ICFileTypeAssociation[] remove) { - boolean added = doAddAssociations(add); - boolean removed = doRemoveAssociations(remove); - return (added || removed); + + public synchronized ICFileTypeAssociation[] getFileTypeAssociations() { + if (fAssocList == null) { + loadAssociationList(); + } + return (ICFileTypeAssociation[]) fAssocList.toArray(new ICFileTypeAssociation[fAssocList.size()]); + } + + public boolean adjustAssociations(ICFileTypeAssociation[] addAssocs, ICFileTypeAssociation[] delAssocs) { + return adjustAssociations(addAssocs, delAssocs, true); + } + + protected synchronized boolean adjustAssociations(ICFileTypeAssociation[] addAssocs, + ICFileTypeAssociation[] delAssocs, boolean triggerEvent) { + List addList = new ArrayList(); + List delList = new ArrayList(); + + loadAssociationList(); + + // check the adds + if (null != addAssocs) { + for (int i = 0; i < addAssocs.length; i++) { + if (!fAssocList.contains(addAssocs[i])) { + fAssocList.add(addAssocs[i]); + addList.add(addAssocs[i]); + } + } + } + + // check the removes + if (null != delAssocs) { + for (int i = 0; i < delAssocs.length; i++) { + if (fAssocList.remove(delAssocs[i])) { + delList.add(delAssocs[i]); + } + } + } + + // Anything change ? + boolean changed = !addList.isEmpty() || !delList.isEmpty(); + + if (changed) { + Collections.sort(fAssocList, ICFileTypeAssociation.Comparator); + addAssocs = (ICFileTypeAssociation[]) addList.toArray(new ICFileTypeAssociation[addList.size()]); + delAssocs = (ICFileTypeAssociation[]) delList.toArray(new ICFileTypeAssociation[delList.size()]); + doAdjustAssociations(addAssocs, delAssocs, true); + } + + return changed; } public ICFileTypeResolver createWorkingCopy() { - CFileTypeResolver copy = new CFileTypeResolver(fContainer); - copy.fAssocList.addAll(fAssocList); + final ICFileTypeAssociation[] associations = getFileTypeAssociations(); + CFileTypeResolver copy = new CFileTypeResolver(fContainer) { + public void doAdjustAssociations(ICFileTypeAssociation[] add, ICFileTypeAssociation[] del, + boolean triggerEvent) { + // + } + protected ICFileTypeAssociation[] loadAssociations() { + return associations; + } + }; return copy; } - - protected boolean doAddAssociations(ICFileTypeAssociation[] assocs) { - boolean added = false; - if (null != assocs) { - for (int i = 0; i < assocs.length; i++) { - if (!fAssocList.contains(assocs[i])) { - if (fAssocList.add(assocs[i])) { - added = true; - } - } + + protected abstract void doAdjustAssociations(ICFileTypeAssociation[] addAssocs, ICFileTypeAssociation[] delAssocs, + boolean triggerEvent); + protected abstract ICFileTypeAssociation[] loadAssociations(); + + + private synchronized List loadAssociationList() { + if (fAssocList == null) { + fAssocList = new ArrayList(); + ICFileTypeAssociation[] assocs = loadAssociations(); + if (assocs != null) { + fAssocList.addAll(Arrays.asList(assocs)); + Collections.sort(fAssocList, ICFileTypeAssociation.Comparator); } } - if (added) { - Collections.sort(fAssocList, ICFileTypeAssociation.Comparator); - } - return added; - } - - public boolean doRemoveAssociations(ICFileTypeAssociation[] assocs) { - boolean removed = false; - if (null != assocs) { - for (int i = 0; i < assocs.length; i++) { - if (fAssocList.remove(assocs[i])) { - removed = true; - } - } - } - if (removed) { - Collections.sort(fAssocList, ICFileTypeAssociation.Comparator); - } - return removed; + return fAssocList; } - private static boolean isDebugging() { - return ResolverModel.VERBOSE; - } - - private static void debugLog(String message) { - System.out.println("CDT Resolver: " + message); //$NON-NLS-1$ - } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/CustomResolver.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/CustomResolver.java new file mode 100644 index 00000000000..2d89a0f9ebc --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/CustomResolver.java @@ -0,0 +1,311 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.core.internal.filetype; + + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.ICDescriptor; +import org.eclipse.cdt.core.filetype.ICFileTypeAssociation; +import org.eclipse.cdt.core.filetype.IResolverModel; +import org.eclipse.cdt.core.filetype.ResolverChangeEvent; +import org.eclipse.cdt.core.filetype.ResolverDelta; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + */ +public class CustomResolver extends CFileTypeResolver { + + // XML tag names, etc. + private static final String OLD_RESOLVER = "cdt_resolver"; //$NON-NLS-1$ + private static final String CDT_RESOLVER = CCorePlugin.PLUGIN_ID + ".resolver"; //$NON-NLS-1$ + private static final String TAG_CUSTOM = "custom"; //$NON-NLS-1$ + private static final String TAG_ASSOC = "associations"; //$NON-NLS-1$ + private static final String TAG_ENTRY = "entry"; //$NON-NLS-1$ + private static final String ATTR_TYPE = "type"; //$NON-NLS-1$ + private static final String ATTR_PATTERN = "pattern"; //$NON-NLS-1$ + private static final String ATTR_VALUE = "value"; //$NON-NLS-1$ + + private ResolverModel fModel; + + public CustomResolver(ResolverModel model, IProject p) { + super(p); + fModel = model; + } + + public static boolean hasCustomResolver(IProject project) { + Boolean custom = new Boolean(false); + // Check for old custom resolver but do not convert + + Element data = getProjectOldResolverData(project, false); + custom = hasCustomTag(data); + + if (!custom.booleanValue()) { + data = getProjectResolverData(project, false); + custom = hasCustomTag(data); + } + + return custom.booleanValue(); + } + + /** + * @param project + */ + public static void removeCustomResover(IProject project) { + Element root = getProjectResolverData(project, false); + if (root != null) { + Node child = root.getFirstChild(); + Element element = null; + + // Clear the old stuff. + while (child != null) { + root.removeChild(child); + child = root.getFirstChild(); + } + try { + getProjectDescriptor(project, true).saveProjectData(); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + } + + protected void doAdjustAssociations(ICFileTypeAssociation[] addAssocs, ICFileTypeAssociation[] delAssocs, + boolean triggerEvent) { + IProject project = (IProject)getContainer(); + List deltas = new ArrayList(); + + // add + if (triggerEvent && null != addAssocs && addAssocs.length > 0) { + for (int i = 0; i < addAssocs.length; i++) { + deltas.add(new ResolverDelta(addAssocs[i], ResolverDelta.EVENT_ADD)); + } + } + + // remove + if (triggerEvent && null != delAssocs && delAssocs.length > 0) { + for (int i = 0; i < delAssocs.length; i++) { + deltas.add(new ResolverDelta(delAssocs[i], ResolverDelta.EVENT_REMOVE)); + } + } + + // fire the deltas. + if (triggerEvent && !deltas.isEmpty()) { + ResolverChangeEvent event = new ResolverChangeEvent(fModel, this); + for (int i = 0; i < deltas.size(); ++i) { + ResolverDelta delta = (ResolverDelta)deltas.get(i); + event.addDelta(delta); + } + fModel.fireEvent(event); + } + + // Save to the file. + + Element root = getProjectResolverData(project, true); + Document doc = root.getOwnerDocument(); + Node child = root.getFirstChild(); + Element element = null; + + // Clear the old stuff. + while (child != null) { + root.removeChild(child); + child = root.getFirstChild(); + } + + element = doc.createElement(TAG_CUSTOM); + element.setAttribute(ATTR_VALUE, Boolean.TRUE.toString()); + root.appendChild(element); + + element = doc.createElement(TAG_ASSOC); + root.appendChild(element); + + root = element; // Note that root changes... + + ICFileTypeAssociation[] assoc = getFileTypeAssociations(); + + for (int i = 0; i < assoc.length; i++) { + element = doc.createElement(TAG_ENTRY); + element.setAttribute(ATTR_PATTERN, assoc[i].getPattern()); + element.setAttribute(ATTR_TYPE, assoc[i].getType().getId()); + root.appendChild(element); + } + + try { + getProjectDescriptor(project, true).saveProjectData(); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.internal.filetype.CFileTypeResolver#loadAssociations() + */ + protected ICFileTypeAssociation[] loadAssociations() { + + IProject project = (IProject)getContainer(); + + convert20(project); + + List assocs = new ArrayList(); + Element data = getProjectResolverData(project, false); + Node child = ((null != data) ? data.getFirstChild() : null); + while (child != null) { + if (child.getNodeName().equals(TAG_ASSOC)) { + Node assoc = child.getFirstChild(); + while (assoc != null) { + if (assoc.getNodeName().equals(TAG_ENTRY)) { + Element element = (Element) assoc; + String pattern = element.getAttribute(ATTR_PATTERN); + String typeId = element.getAttribute(ATTR_TYPE); + try { + assocs.add(fModel.createAssocation(pattern, fModel.getFileTypeById(typeId))); + } catch (IllegalArgumentException e) { + CCorePlugin.log(e); + } + } + assoc = assoc.getNextSibling(); + } + } + child = child.getNextSibling(); + } + return (ICFileTypeAssociation[]) assocs.toArray(new ICFileTypeAssociation[assocs.size()]); + } + + private static Element getProjectResolverData(IProject project, boolean create) { + Element data = null; + try { + ICDescriptor desc = getProjectDescriptor(project, create); + if (desc != null) { + data = desc.getProjectData(CDT_RESOLVER); + } + } catch (CoreException e) { + // ignore + } + return data; + } + + private static ICDescriptor getProjectDescriptor(IProject project, boolean create) throws CoreException { + ICDescriptor descriptor = null; + descriptor = CCorePlugin.getDefault().getCProjectDescription(project, create); + return descriptor; + } + + private static Element getProjectOldResolverData(IProject project, boolean create) { + Element data = null; + try { + ICDescriptor desc = getProjectDescriptor(project, create); + if (desc != null) { + data = desc.getProjectData(OLD_RESOLVER); + } + } catch (CoreException e) { + // ignore + } + return data; + } + + private static void convert20(IProject project) { + Element root = getProjectOldResolverData(project, false); + if (root != null) { + IResolverModel model = ResolverModel.getDefault(); + List assocList = new ArrayList(); + + // 1 - get the old stuff + Node child = root.getFirstChild(); + while (child != null) { + if (child.getNodeName().equals(TAG_ASSOC)) { + Node assoc = child.getFirstChild(); + while (assoc != null) { + if (assoc.getNodeName().equals(TAG_ENTRY)) { + Element element = (Element) assoc; + String pattern = element.getAttribute(ATTR_PATTERN); + String typeId = element.getAttribute(ATTR_TYPE); + try { + assocList.add(model.createAssocation(pattern, model.getFileTypeById(typeId))); + } catch (IllegalArgumentException e) { + CCorePlugin.log(e); + } + } + assoc = assoc.getNextSibling(); + } + } + child = child.getNextSibling(); + } + + // 2 - Clear the old stuff. + child = root.getFirstChild(); + while (child != null) { + root.removeChild(child); + child = root.getFirstChild(); + } + + ICFileTypeAssociation[] assocs = (ICFileTypeAssociation[]) assocList.toArray(new ICFileTypeAssociation[assocList.size()]); + + if (assocs.length > 0) { + // 3 - save the old stuff on the new id + root = getProjectResolverData(project, true); + if (root != null) { + Document doc = root.getOwnerDocument(); + child = root.getFirstChild(); + Element element = null; + + // Clear the old stuff. + while (child != null) { + root.removeChild(child); + child = root.getFirstChild(); + } + + element = doc.createElement(TAG_CUSTOM); + element.setAttribute(ATTR_VALUE, Boolean.TRUE.toString()); + root.appendChild(element); + + element = doc.createElement(TAG_ASSOC); + root.appendChild(element); + + root = element; // Note that root changes... + + for (int i = 0; i < assocs.length; i++) { + element = doc.createElement(TAG_ENTRY); + element.setAttribute(ATTR_PATTERN, assocs[i].getPattern()); + element.setAttribute(ATTR_TYPE, assocs[i].getType().getId()); + root.appendChild(element); + } + + } + } + try { + getProjectDescriptor(project, true).saveProjectData(); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + } + + private static Boolean hasCustomTag(Element data) { + Node child = ((null != data) ? data.getFirstChild() : null); + Boolean custom = new Boolean(false); + + while (child != null) { + if (child.getNodeName().equals(TAG_CUSTOM)) { + return Boolean.valueOf(((Element)child).getAttribute(ATTR_VALUE)); + } + child = child.getNextSibling(); + } + return Boolean.FALSE; + } + +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/ResolverModel.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/ResolverModel.java index 58aa684b961..0a33b91940e 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/ResolverModel.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/ResolverModel.java @@ -10,14 +10,9 @@ ***********************************************************************/ package org.eclipse.cdt.core.internal.filetype; -import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; -import java.io.FileWriter; import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -29,7 +24,6 @@ import java.util.Properties; import java.util.Vector; import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.ICDescriptor; import org.eclipse.cdt.core.filetype.ICFileType; import org.eclipse.cdt.core.filetype.ICFileTypeAssociation; import org.eclipse.cdt.core.filetype.ICFileTypeConstants; @@ -38,9 +32,8 @@ import org.eclipse.cdt.core.filetype.ICLanguage; import org.eclipse.cdt.core.filetype.IResolverChangeListener; import org.eclipse.cdt.core.filetype.IResolverModel; import org.eclipse.cdt.core.filetype.ResolverChangeEvent; -import org.eclipse.core.resources.IContainer; +import org.eclipse.cdt.core.filetype.ResolverDelta; import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; @@ -52,11 +45,10 @@ import org.eclipse.core.runtime.IRegistryChangeListener; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.Status; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; +import org.eclipse.core.runtime.Preferences.PropertyChangeEvent; /** * Implementation of the file type resolver interface. @@ -89,27 +81,16 @@ public class ResolverModel implements IResolverModel { // Default resolver private ICFileTypeResolver fDefaultResolver = null; - // Workspace resolver - private ICFileTypeResolver fWkspResolver = null; - // XML tag names, etc. private static final String EXTENSION_LANG = "CLanguage"; //$NON-NLS-1$ private static final String EXTENSION_TYPE = "CFileType"; //$NON-NLS-1$ private static final String EXTENSION_ASSOC = "CFileTypeAssociation"; //$NON-NLS-1$ - private static final String TAG_CUSTOM = "custom"; //$NON-NLS-1$ - private static final String TAG_ASSOC = "associations"; //$NON-NLS-1$ - private static final String TAG_ENTRY = "entry"; //$NON-NLS-1$ private static final String ATTR_TYPE = "type"; //$NON-NLS-1$ - private static final String ATTR_PATTERN = "pattern"; //$NON-NLS-1$ - private static final String ATTR_FILE = "file"; //$NON-NLS-1$ private static final String ATTR_ID = "id"; //$NON-NLS-1$ private static final String ATTR_LANGUAGE = "language"; //$NON-NLS-1$ private static final String ATTR_NAME = "name"; //$NON-NLS-1$ private static final String ATTR_VAL_SOURCE = "source"; //$NON-NLS-1$ private static final String ATTR_VAL_HEADER = "header"; //$NON-NLS-1$ - private static final String ATTR_VALUE = "value"; //$NON-NLS-1$ - private static final String WKSP_STATE_FILE = "resolver.properties"; //$NON-NLS-1$ - private static final String CDT_RESOLVER = "cdt_resolver"; //$NON-NLS-1$ // Trace flag public static boolean VERBOSE = false; @@ -118,8 +99,8 @@ public class ResolverModel implements IResolverModel { private static ResolverModel fInstance = null; // Qualified names used to identify project session properties - private static final String RESOLVER_MODEL_ID = CCorePlugin.PLUGIN_ID + ".resolver"; //$NON-NLS-1$ - private static final QualifiedName QN_CUSTOM_RESOLVER = new QualifiedName(RESOLVER_MODEL_ID, TAG_CUSTOM); + private static final String QN_RESOLVER_MODEL_ID = CCorePlugin.PLUGIN_ID + ".resolver"; //$NON-NLS-1$ + private static final QualifiedName QN_CUSTOM_RESOLVER = new QualifiedName(QN_RESOLVER_MODEL_ID, "custom"); //$NON-NLS-1$ // List of listeners on the model private List fListeners = new Vector(); @@ -131,9 +112,10 @@ public class ResolverModel implements IResolverModel { loadDeclaredTypes(); fDefaultResolver = loadDefaultResolver(); - fWkspResolver = loadWorkspaceResolver(); + convertFrom20(); initRegistryChangeListener(); + initPreferenceChangeListener(); } catch (Exception e) { CCorePlugin.log(e); } @@ -169,56 +151,6 @@ public class ResolverModel implements IResolverModel { return ((null != type) ? type : DEFAULT_FILE_TYPE); } - public void setResolver(ICFileTypeResolver newResolver) { - ICFileTypeResolver oldResolver = getResolver(); - fWkspResolver = newResolver; - saveWorkspaceResolver(newResolver); - fireResolverChangeEvent(null, oldResolver); - } - - public ICFileTypeResolver getResolver() { - return ((null != fWkspResolver) ? fWkspResolver : fDefaultResolver) ; - } - - public void setResolver(IProject project, ICFileTypeResolver newResolver) { - ICFileTypeResolver oldResolver = getResolver(project); - try { - project.setSessionProperty(QN_CUSTOM_RESOLVER, newResolver); - } catch (CoreException e) { - } - saveProjectResolver(project, newResolver); - fireResolverChangeEvent(project, oldResolver); - } - - public ICFileTypeResolver getResolver(IProject project) { - ICFileTypeResolver resolver = null; - - if (null != project) { - try { - Object obj = project.getSessionProperty(QN_CUSTOM_RESOLVER); - if (obj instanceof ICFileTypeResolver) { - resolver = (ICFileTypeResolver) obj; - } - } catch (CoreException e) { - } - if (null == resolver) { - if (customProjectResolverExists(project)) { - resolver = loadProjectResolver(project); - } - } - } - - if (null == resolver) { - resolver = getResolver(); - } - - return resolver; - } - - public ICFileTypeAssociation createAssocation(String pattern, ICFileType type) { - return new CFileTypeAssociation(pattern, type); - } - /** * Add an instance of a language to the languages known to the * resolver. @@ -230,14 +162,11 @@ public class ResolverModel implements IResolverModel { * * @return true if the language is added, false otherwise */ - public boolean addLanguage(ICLanguage lang) { - IContainer root = ResourcesPlugin.getWorkspace().getRoot(); - List list = new ArrayList(1); - boolean result = addLanguage(root, list, lang); + public boolean addLanguages(ICLanguage[] langs) { + ResolverChangeEvent event = new ResolverChangeEvent(this, getResolver()); + boolean result = addLanguages(langs, event); if (true == result) { - ResolverChangeEvent[] events = new ResolverChangeEvent[list.size()]; - list.toArray(events); - fireEvent(events); + fireEvent(event); } return result; } @@ -253,14 +182,11 @@ public class ResolverModel implements IResolverModel { * * @return true if the file type is added, false otherwise */ - public boolean addFileType(ICFileType type) { - IContainer root = ResourcesPlugin.getWorkspace().getRoot(); - List list = new ArrayList(1); - boolean result = addFileType(root, list, type); + public boolean addFileTypes(ICFileType[] types) { + ResolverChangeEvent event = new ResolverChangeEvent(this, getResolver()); + boolean result = addFileTypes(types, event); if (true == result) { - ResolverChangeEvent[] events = new ResolverChangeEvent[list.size()]; - list.toArray(events); - fireEvent(events); + fireEvent(event); } return result; } @@ -272,14 +198,11 @@ public class ResolverModel implements IResolverModel { * * @return true if the language is removed, false otherwise */ - public boolean removeLanguage(ICLanguage lang) { - IContainer root = ResourcesPlugin.getWorkspace().getRoot(); - List list = new ArrayList(1); - boolean result = removeLanguage(root, list, lang); + public boolean removeLanguages(ICLanguage[] langs) { + ResolverChangeEvent event = new ResolverChangeEvent(this, getResolver()); + boolean result = removeLanguages(langs, event); if (true == result) { - ResolverChangeEvent[] events = new ResolverChangeEvent[list.size()]; - list.toArray(events); - fireEvent(events); + fireEvent(event); } return result; } @@ -291,18 +214,113 @@ public class ResolverModel implements IResolverModel { * * @return true if the file type is removed, false otherwise */ - public boolean removeFileType(ICFileType type) { - IContainer root = ResourcesPlugin.getWorkspace().getRoot(); - List list = new ArrayList(1); - boolean result = removeFileType(root, list, type); + public boolean removeFileTypes(ICFileType[] types) { + ResolverChangeEvent event = new ResolverChangeEvent(this, getResolver()); + boolean result = removeFileTypes(types, event); if (true == result) { - ResolverChangeEvent[] events = new ResolverChangeEvent[list.size()]; - list.toArray(events); - fireEvent(events); + fireEvent(event); } return result; } + public ICFileTypeResolver getResolver() { + return fDefaultResolver; + } + + public boolean hasCustomResolver(IProject project) { + return CustomResolver.hasCustomResolver(project); + } + + public ICFileTypeResolver createCustomResolver(IProject project, ICFileTypeResolver copy) { + ICFileTypeAssociation[] oldAssocs = null; + ICFileTypeAssociation[] newAssocs = null; + + // get the old resolver first, creating the new will erase stuff in the cdescriptor. + ICFileTypeResolver oldResolver = getResolver(project); + if (oldResolver != null) { + oldAssocs = oldResolver.getFileTypeAssociations(); + } + + ICFileTypeResolver newResolver = new CustomResolver(this, project); + + if (copy != null) { + newAssocs = copy.getFileTypeAssociations(); + newResolver.addAssociations(newAssocs); + } + + // cache the result in project session property. + try { + project.setSessionProperty(QN_CUSTOM_RESOLVER, newResolver); + } catch (CoreException e) { + } + + ResolverChangeEvent event = new ResolverChangeEvent(this, newResolver, oldResolver); + + fireResolverChangeEvent(event, newAssocs, oldAssocs); + return newResolver; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.filetype.IResolverModel#removeCustomResolver(org.eclipse.core.resources.IProject) + */ + public void removeCustomResolver(IProject project) { + ICFileTypeAssociation[] oldAssocs = null; + ICFileTypeAssociation[] newAssocs = null; + + // get the old resolver first, creating the new will erase stuff in the cdescriptor. + ICFileTypeResolver oldResolver = getResolver(project); + if (oldResolver != null) { + oldAssocs = oldResolver.getFileTypeAssociations(); + } + + ICFileTypeResolver newResolver = getResolver(); + + // cache the result in project session property. + try { + project.setSessionProperty(QN_CUSTOM_RESOLVER, null); + } catch (CoreException e) { + } + + CustomResolver.removeCustomResover(project); + ResolverChangeEvent event = new ResolverChangeEvent(this, newResolver, oldResolver); + fireResolverChangeEvent(event, newAssocs, oldAssocs); + } + + + public ICFileTypeResolver getResolver(IProject project) { + ICFileTypeResolver resolver = null; + + if (null != project) { + try { + Object obj = project.getSessionProperty(QN_CUSTOM_RESOLVER); + if (obj instanceof ICFileTypeResolver) { + resolver = (ICFileTypeResolver) obj; + } + } catch (CoreException e) { + } + if (null == resolver) { + if (hasCustomResolver(project)) { + resolver = new CustomResolver(this, project); + // cache the result in the session property. + try { + project.setSessionProperty(QN_CUSTOM_RESOLVER, resolver); + } catch (CoreException e) { + } + } + } + } + + if (null == resolver) { + resolver = getResolver(); + } + + return resolver; + } + + public ICFileTypeAssociation createAssocation(String pattern, ICFileType type) { + return new CFileTypeAssociation(pattern, type); + } + public void addResolverChangeListener(IResolverChangeListener listener) { fListeners.add(listener); } @@ -327,82 +345,14 @@ public class ResolverModel implements IResolverModel { System.out.println("CDT Resolver: " + message); //$NON-NLS-1$ } - //---------------------------------------------------------------------- - // Registry change event handling - //---------------------------------------------------------------------- - - private boolean addLanguage(IContainer container, List list, ICLanguage lang) { - boolean added = false; - if (!fLangMap.containsValue(lang)) { - fLangMap.put(lang.getId(), lang); - if (null != list) { - ResolverChangeEvent event = new ResolverChangeEvent(container, ResolverChangeEvent.EVENT_ADD, lang); - list.add(event); - } - added = true; - } - return added; - } - - private boolean addFileType(IContainer container, List list, ICFileType type) { - boolean added = false; - if (!fTypeMap.containsValue(type)) { - fTypeMap.put(type.getId(), type); - if (null != list) { - ResolverChangeEvent event = new ResolverChangeEvent(container, ResolverChangeEvent.EVENT_ADD, type); - list.add(event); - } - added = true; - } - return added; - } - - private boolean removeLanguage(IContainer container, List list, ICLanguage lang) { - boolean removed = (null != fLangMap.remove(lang.getId())); + public void fireEvent(final ResolverChangeEvent event) { - if (removed) { - if (null != list) { - ResolverChangeEvent event = new ResolverChangeEvent(container, ResolverChangeEvent.EVENT_REMOVE, lang); - list.add(event); - } - ArrayList removeList = new ArrayList(); - for (Iterator iter = fTypeMap.values().iterator(); iter.hasNext();) { - ICFileType type = (ICFileType) iter.next(); - if (lang.equals(type.getLanguage())) { - removeList.add(type); - } - } - for (Iterator iter = removeList.iterator(); iter.hasNext();) { - removeFileType(container, list, (ICFileType) iter.next()); - } - } - return removed; - } - - private boolean removeFileType(IContainer container, List list, ICFileType type) { - boolean removed = (null != fTypeMap.remove(type.getId())); - if (removed) { - if (null != list) { - ResolverChangeEvent event = new ResolverChangeEvent(container, ResolverChangeEvent.EVENT_REMOVE, type); - list.add(event); - } - // TODO: must remove any associations based on this file type as well - // Unforuntately, at this point, that means iterating over the contents - // of the default, workspace, and project resolvers. Ugh. - } - return removed; - } - - private void fireEvent(final ResolverChangeEvent[] events) { - - if (events == null || events.length == 0) { + if (event == null) { return; } if (isDebugging()) { - for (int i = 0; i < events.length; i++) { - debugLog(events[i].toString()); - } + debugLog(event.toString()); } if (fListeners.isEmpty()) { @@ -421,49 +371,30 @@ public class ResolverModel implements IResolverModel { CCorePlugin.log(status); } public void run() throws Exception { - listeners[index].resolverChanged(events); + listeners[index].resolverChanged(event); } }); } } - private void fireResolverChangeEvent(IProject project, ICFileTypeResolver oldResolver) { - IContainer container = project; - ICFileTypeResolver newResolver = getResolver(project); - //ResolverChangeEvent event = new ResolverChangeEvent(newResolver); - //int element = ResolverDelta.ELEMENT_WORKSPACE; - //if (null != project) { - // element = ResolverDelta.ELEMENT_PROJECT; - //} - //event.addDelta(new ResolverDelta(ResolverDelta.EVENT_SET, element, project)); - - List list = new ArrayList(); - if (container == null) { - container = ResourcesPlugin.getWorkspace().getRoot(); - } - list.add(new ResolverChangeEvent(container, ResolverChangeEvent.EVENT_SET, newResolver)); + private void fireResolverChangeEvent(ResolverChangeEvent event, ICFileTypeAssociation[] newAssocs, + ICFileTypeAssociation[] oldAssocs) { - if ((null != oldResolver) && (null != newResolver)) { - ICFileTypeAssociation[] oldAssoc = oldResolver.getFileTypeAssociations(); - ICFileTypeAssociation[] newAssoc = newResolver.getFileTypeAssociations(); + if ((null != oldAssocs) && (null != newAssocs)) { - for (int i = 0; i < oldAssoc.length; i++) { - if (Arrays.binarySearch(newAssoc, oldAssoc[i], ICFileTypeAssociation.Comparator) < 0) { - //event.addDelta(new ResolverDelta(oldAssoc[i], ResolverDelta.EVENT_REMOVE)); - list.add(new ResolverChangeEvent(container, ResolverChangeEvent.EVENT_REMOVE, oldAssoc[i])); + for (int i = 0; i < oldAssocs.length; i++) { + if (Arrays.binarySearch(newAssocs, oldAssocs[i], ICFileTypeAssociation.Comparator) < 0) { + event.addDelta(new ResolverDelta(oldAssocs[i], ResolverDelta.EVENT_REMOVE)); } } - for (int i = 0; i < newAssoc.length; i++) { - if (Arrays.binarySearch(oldAssoc, newAssoc[i], ICFileTypeAssociation.Comparator) < 0) { - //event.addDelta(new ResolverDelta(newAssoc[i], ResolverDelta.EVENT_ADD)); - list.add(new ResolverChangeEvent(container, ResolverChangeEvent.EVENT_ADD, newAssoc[i])); + for (int i = 0; i < newAssocs.length; i++) { + if (Arrays.binarySearch(oldAssocs, newAssocs[i], ICFileTypeAssociation.Comparator) < 0) { + event.addDelta(new ResolverDelta(newAssocs[i], ResolverDelta.EVENT_ADD)); } } } - ResolverChangeEvent[] events = new ResolverChangeEvent[list.size()]; - list.toArray(events); - fireEvent(events); + fireEvent(event); } private void initRegistryChangeListener() { @@ -474,34 +405,123 @@ public class ResolverModel implements IResolverModel { }, CCorePlugin.PLUGIN_ID); } + private void initPreferenceChangeListener() { + Preferences prefs = CCorePlugin.getDefault().getPluginPreferences(); + prefs.addPropertyChangeListener(new Preferences.IPropertyChangeListener() { + /* (non-Javadoc) + * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + handlePropertyChanged(event); + } + }); + } + + protected void handlePropertyChanged(Preferences.PropertyChangeEvent event) { + String property = event.getProperty(); + if (property != null) { + if (WorkspaceResolver.PREFS_ASSOCIATIONS_EXCLUSION.equals(property) || + WorkspaceResolver.PREFS_ASSOCIATIONS_INCLUSION.equals(property)) { + fDefaultResolver = loadDefaultResolver(); + } + } + } + protected void handleRegistryChanged(IRegistryChangeEvent event) { IExtensionDelta[] deltas = null; - //ResolverChangeEvent modelEvent = new ResolverChangeEvent(null); - List list = new ArrayList(); - IContainer container = ResourcesPlugin.getWorkspace().getRoot(); + ResolverChangeEvent modelEvent = new ResolverChangeEvent(this, getResolver()); deltas = event.getExtensionDeltas(CCorePlugin.PLUGIN_ID, EXTENSION_LANG); for (int i = 0; i < deltas.length; i++) { - processLanguageExtension(container, list, deltas[i].getExtension(), IExtensionDelta.ADDED == deltas[i].getKind()); + processLanguageExtension(modelEvent, deltas[i].getExtension(), IExtensionDelta.ADDED == deltas[i].getKind()); } deltas = event.getExtensionDeltas(CCorePlugin.PLUGIN_ID, EXTENSION_TYPE); for (int i = 0; i < deltas.length; i++) { - processTypeExtension(container, list, deltas[i].getExtension(), IExtensionDelta.ADDED == deltas[i].getKind()); + processTypeExtension(modelEvent, deltas[i].getExtension(), IExtensionDelta.ADDED == deltas[i].getKind()); } deltas = event.getExtensionDeltas(CCorePlugin.PLUGIN_ID, EXTENSION_ASSOC); if (deltas.length != 0) { fDefaultResolver = loadDefaultResolver(); - fWkspResolver = loadWorkspaceResolver(); - } - if (!list.isEmpty()) { - ResolverChangeEvent[] events = new ResolverChangeEvent[list.size()]; - list.toArray(events); - fireEvent(events); + //fWkspResolver = loadWorkspaceResolver(); } + + fireEvent(modelEvent); } + private boolean addLanguages(ICLanguage[] langs, ResolverChangeEvent event) { + boolean added = false; + for (int i = 0; i < langs.length; ++i) { + ICLanguage lang = langs[i]; + if (!fLangMap.containsValue(lang)) { + fLangMap.put(lang.getId(), lang); + if (null != event) { + event.addDelta(new ResolverDelta(lang, ResolverDelta.EVENT_ADD)); + } + added = true; + } + } + return added; + } + + private boolean addFileTypes(ICFileType[] types, ResolverChangeEvent event) { + boolean added = false; + for (int i = 0; i < types.length; ++i) { + ICFileType type = types[i]; + if (!fTypeMap.containsValue(type)) { + fTypeMap.put(type.getId(), type); + event.addDelta(new ResolverDelta(type, ResolverDelta.EVENT_ADD)); + added = true; + } + } + return added; + } + + private boolean removeLanguages(ICLanguage[] langs, ResolverChangeEvent event) { + boolean del = false; + ArrayList removeTypeList = new ArrayList(langs.length); + for (int i = 0; i < langs.length; ++i) { + ICLanguage lang = langs[i]; + boolean removed = (null != fLangMap.remove(lang.getId())); + + if (removed) { + event.addDelta(new ResolverDelta(lang, ResolverDelta.EVENT_REMOVE)); + del = true; + for (Iterator iter = fTypeMap.values().iterator(); iter.hasNext();) { + ICFileType type = (ICFileType) iter.next(); + if (lang.equals(type.getLanguage())) { + removeTypeList.add(type); + } + } + } + } + if (!removeTypeList.isEmpty()) { + ICFileType[] types = (ICFileType[]) removeTypeList.toArray(new ICFileType[removeTypeList.size()]); + removeFileTypes(types, event); + } + return del; + } + + private boolean removeFileTypes(ICFileType[] types, ResolverChangeEvent event) { + boolean changed = false; + for (int i = 0; i < types.length; ++i) { + ICFileType type = types[i]; + boolean removed = (null != fTypeMap.remove(type.getId())); + if (removed) { + changed = true; + if (null != event) { + event.addDelta(new ResolverDelta(type, ResolverDelta.EVENT_REMOVE)); + } + // TODO: must remove any associations based on this file type as well + // Unforuntately, at this point, that means iterating over the contents + // of the default, workspace, and project resolvers. Ugh. + } + } + return changed; + } + + //---------------------------------------------------------------------- // Extension point handling //---------------------------------------------------------------------- @@ -512,22 +532,16 @@ public class ResolverModel implements IResolverModel { private void loadDeclaredLanguages() { IExtensionPoint point = getExtensionPoint(EXTENSION_LANG); IExtension[] extensions = point.getExtensions(); - //ResolverChangeEvent event = new ResolverChangeEvent(null); - IContainer root = ResourcesPlugin.getWorkspace().getRoot(); - List list = new ArrayList(); + ResolverChangeEvent event = new ResolverChangeEvent(this, getResolver()); for (int i = 0; i < extensions.length; i++) { - processLanguageExtension(root, list, extensions[i], true); + processLanguageExtension(event, extensions[i], true); } // Shouldn't have anything listening here, but generating // the events helps maintain internal consistency w/logging - - if (!list.isEmpty()) { - ResolverChangeEvent[] events = new ResolverChangeEvent[list.size()]; - list.toArray(events); - fireEvent(events); - } + + fireEvent(event); } /** @@ -536,44 +550,42 @@ public class ResolverModel implements IResolverModel { private void loadDeclaredTypes() { IExtensionPoint point = getExtensionPoint(EXTENSION_TYPE); IExtension[] extensions = point.getExtensions(); - //ResolverChangeEvent event = new ResolverChangeEvent(null); - IContainer root = ResourcesPlugin.getWorkspace().getRoot(); - List list = new ArrayList(); + ResolverChangeEvent event = new ResolverChangeEvent(this, getResolver()); for (int i = 0; i < extensions.length; i++) { - processTypeExtension(root, list, extensions[i], true); + processTypeExtension(event, extensions[i], true); } // Shouldn't have anything listening here, but generating // the events helps maintain internal consistency w/logging - if (!list.isEmpty()) { - ResolverChangeEvent[] events = new ResolverChangeEvent[list.size()]; - list.toArray(events); - fireEvent(events); - } + + fireEvent(event); } - private void processLanguageExtension(IContainer container, List list, IExtension extension, boolean add) { + private void processLanguageExtension(ResolverChangeEvent event, IExtension extension, boolean add) { IConfigurationElement[] elements = extension.getConfigurationElements(); + List list = new ArrayList(elements.length); for (int i = 0; i < elements.length; i++) { String id = elements[i].getAttribute(ATTR_ID); String name = elements[i].getAttribute(ATTR_NAME); - try { ICLanguage element = new CLanguage(id, name); - if (add) { - addLanguage(container, list, element); - } else { - removeLanguage(container, list, element); - } + list.add (element); } catch (IllegalArgumentException e) { CCorePlugin.log(e); } } + ICLanguage[] langs = (ICLanguage[]) list.toArray(new ICLanguage[list.size()]); + if (add) { + addLanguages(langs, event); + } else { + removeLanguages(langs, event); + } } - private void processTypeExtension(IContainer container, List list, IExtension extension, boolean add) { + private void processTypeExtension(ResolverChangeEvent event, IExtension extension, boolean add) { IConfigurationElement[] elements = extension.getConfigurationElements(); + List list = new ArrayList(elements.length); for (int i = 0; i < elements.length; i++) { String id = elements[i].getAttribute(ATTR_ID); String lang = elements[i].getAttribute(ATTR_LANGUAGE); @@ -582,15 +594,17 @@ public class ResolverModel implements IResolverModel { try { ICFileType element = new CFileType(id, getLanguageById(lang), name, parseType(type)); - if (add) { - addFileType(container, list, element); - } else { - removeFileType(container, list, element); - } + list.add(element); } catch (IllegalArgumentException e) { CCorePlugin.log(e); } } + ICFileType[] types = (ICFileType[]) list.toArray(new ICFileType[list.size()]); + if (add) { + addFileTypes(types, event); + } else { + removeFileTypes(types, event); + } } /** @@ -622,97 +636,29 @@ public class ResolverModel implements IResolverModel { * declared extension points. */ private ICFileTypeResolver loadDefaultResolver() { - List assoc = new ArrayList(); - ICFileTypeResolver resolver = new CFileTypeResolver(ResourcesPlugin.getWorkspace().getRoot()); - IExtensionPoint point = getExtensionPoint(EXTENSION_ASSOC); - IExtension[] extensions = point.getExtensions(); - IConfigurationElement[] elements = null; - - for (int i = 0; i < extensions.length; i++) { - elements = extensions[i].getConfigurationElements(); - for (int j = 0; j < elements.length; j++) { - ICFileType typeRef = getFileTypeById(elements[j].getAttribute(ATTR_TYPE)); - if (null != typeRef) { - assoc.addAll(getAssocFromPattern(typeRef, elements[j])); - assoc.addAll(getAssocFromFile(typeRef, elements[j])); - } - } - } - - resolver.addAssociations((ICFileTypeAssociation[]) assoc.toArray(new ICFileTypeAssociation[assoc.size()])); - - return resolver; - } - - /** - * Associate one or more file extensions with an ICFileType instance. - * - * @param typeRef reference to the ICFileType instance - * - * @param element configuration element to get file extensions from - */ - private List getAssocFromPattern(ICFileType typeRef, IConfigurationElement element) { - List assocs = new ArrayList(); - String attr = element.getAttribute(ATTR_PATTERN); - if (null != attr) { - String[] item = attr.split(","); //$NON-NLS-1$ - for (int i = 0; i < item.length; i++) { - try { - assocs.add(createAssocation(item[i].trim(), typeRef)); - } catch (IllegalArgumentException e) { - CCorePlugin.log(e); - } - } - } - return assocs; + return new WorkspaceResolver(this); } - /** - * Associate the contents of a file with an ICFileType instance. - * - * The file is read, one entry per line; each line is taken as - * a pattern that should be associated with the specified ICFileType - * instance. - * - * @param typeRef reference to the ICFileType instance - * - * @param element configuration element to get file extensions from - */ - private List getAssocFromFile(ICFileType typeRef, IConfigurationElement element) { - List assocs = new ArrayList(); - String attr = element.getAttribute(ATTR_FILE); - - if (null != attr) { - URL baseURL = null; - URL fileURL = null; - BufferedReader in = null; - String line = null; - - try { - baseURL = Platform.getBundle(element.getDeclaringExtension().getNamespace()).getEntry("/"); //$NON-NLS-1$ - fileURL = new URL(baseURL, attr); - in = new BufferedReader(new InputStreamReader(fileURL.openStream())); - line = in.readLine(); - while (null != line) { - try { - assocs.add(createAssocation(line.trim(), typeRef)); - } catch (IllegalArgumentException e) { - CCorePlugin.log(e); - } - line = in.readLine(); - } - in.close(); - } catch (IOException e) { - CCorePlugin.log(e); - } - } - return assocs; - } - //---------------------------------------------------------------------- // Workspace resolver //---------------------------------------------------------------------- - + + private static final String WKSP_STATE_FILE = "resolver.properties"; //$NON-NLS-1$ + + private void convertFrom20() { + if (customWorkspaceResolverExists()) { + ICFileTypeAssociation[] assocs = loadWorkspaceResolver(); + if (assocs != null && assocs.length > 0) { + getResolver().addAssociations(assocs); + } + try { + getWorkspaceResolverStateFilePath().toFile().delete(); + } catch (Exception e) { + // + } + } + } + private boolean customWorkspaceResolverExists() { return getWorkspaceResolverStateFilePath().toFile().exists(); } @@ -721,16 +667,13 @@ public class ResolverModel implements IResolverModel { return CCorePlugin.getDefault().getStateLocation().append(WKSP_STATE_FILE); } - private ICFileTypeResolver loadWorkspaceResolver() { + private ICFileTypeAssociation[] loadWorkspaceResolver() { List assocs = new ArrayList(); - ICFileTypeResolver resolver = null; File file = getWorkspaceResolverStateFilePath().toFile(); if (file.exists()) { Properties props = new Properties(); FileInputStream in = null; - - resolver = new CFileTypeResolver(ResourcesPlugin.getWorkspace().getRoot()); try { in = new FileInputStream(file); @@ -747,151 +690,20 @@ public class ResolverModel implements IResolverModel { } } - in.close(); } catch (IOException e) { CCorePlugin.log(e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // + } + } } - - if (null != in) { - in = null; - } - - resolver.addAssociations((ICFileTypeAssociation[]) assocs.toArray(new ICFileTypeAssociation[assocs.size()])); } - return resolver; + return ((ICFileTypeAssociation[]) assocs.toArray(new ICFileTypeAssociation[assocs.size()])); } - private void saveWorkspaceResolver(ICFileTypeResolver resolver) { - File file = getWorkspaceResolverStateFilePath().toFile(); - BufferedWriter out = null; - - try { - if (null == resolver) { - file.delete(); - } else { - out = new BufferedWriter(new FileWriter(file)); - - ICFileTypeAssociation[] assoc = resolver.getFileTypeAssociations(); - - for (int i = 0; i < assoc.length; i++) { - out.write(assoc[i].getPattern() + '=' + assoc[i].getType().getId() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - out.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - - if (null != out) { - out = null; - } - } - - //---------------------------------------------------------------------- - // Project resolver - //---------------------------------------------------------------------- - - private boolean customProjectResolverExists(IProject project) { - Element data = getProjectData(project, false); - Node child = ((null != data) ? data.getFirstChild() : null); - Boolean custom = new Boolean(false); - - while (child != null) { - if (child.getNodeName().equals(TAG_CUSTOM)) { - custom = Boolean.valueOf(((Element)child).getAttribute(ATTR_VALUE)); - } - child = child.getNextSibling(); - } - - return custom.booleanValue(); - } - - private ICDescriptor getProjectDescriptor(IProject project, boolean create) throws CoreException { - ICDescriptor descriptor = null; - descriptor = CCorePlugin.getDefault().getCProjectDescription(project, create); - return descriptor; - } - - private Element getProjectData(IProject project, boolean create) { - Element data = null; - try { - ICDescriptor desc = getProjectDescriptor(project, create); - if (desc != null) { - data = desc.getProjectData(CDT_RESOLVER); - } - } catch (CoreException e) { - } - return data; - } - - private ICFileTypeResolver loadProjectResolver(IProject project) { - List assocs = new ArrayList(); - ICFileTypeResolver resolver = new CFileTypeResolver(project); - Element data = getProjectData(project, false); - Node child = ((null != data) ? data.getFirstChild() : null); - - while (child != null) { - if (child.getNodeName().equals(TAG_ASSOC)) { - Node assoc = child.getFirstChild(); - while (assoc != null) { - if (assoc.getNodeName().equals(TAG_ENTRY)) { - Element element = (Element) assoc; - String pattern = element.getAttribute(ATTR_PATTERN); - String typeId = element.getAttribute(ATTR_TYPE); - try { - assocs.add(createAssocation(pattern, getFileTypeById(typeId))); - } catch (IllegalArgumentException e) { - CCorePlugin.log(e); - } - } - assoc = assoc.getNextSibling(); - } - } - child = child.getNextSibling(); - } - - resolver.addAssociations((ICFileTypeAssociation[]) assocs.toArray(new ICFileTypeAssociation[assocs.size()])); - - return resolver; - } - - private void saveProjectResolver(IProject project, ICFileTypeResolver resolver) { - Element root = getProjectData(project, true); - Document doc = root.getOwnerDocument(); - Node child = root.getFirstChild(); - Element element = null; - - while (child != null) { - root.removeChild(child); - child = root.getFirstChild(); - } - - element = doc.createElement(TAG_CUSTOM); - element.setAttribute(ATTR_VALUE, new Boolean(null != resolver).toString()); - root.appendChild(element); - - if (null != resolver) { - element = doc.createElement(TAG_ASSOC); - root.appendChild(element); - - root = element; // Note that root changes... - - ICFileTypeAssociation[] assoc = resolver.getFileTypeAssociations(); - - for (int i = 0; i < assoc.length; i++) { - element = doc.createElement(TAG_ENTRY); - element.setAttribute(ATTR_PATTERN, assoc[i].getPattern()); - element.setAttribute(ATTR_TYPE, assoc[i].getType().getId()); - root.appendChild(element); - } - } - - try { - getProjectDescriptor(project, true).saveProjectData(); - } catch (CoreException e) { - CCorePlugin.log(e); - } - } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/WorkspaceResolver.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/WorkspaceResolver.java new file mode 100644 index 00000000000..02613805b87 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/internal/filetype/WorkspaceResolver.java @@ -0,0 +1,303 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.core.internal.filetype; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.filetype.ICFileType; +import org.eclipse.cdt.core.filetype.ICFileTypeAssociation; +import org.eclipse.cdt.core.filetype.ResolverChangeEvent; +import org.eclipse.cdt.core.filetype.ResolverDelta; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Preferences; + +/** + */ +public class WorkspaceResolver extends CFileTypeResolver { + + public static final String PREFS_ASSOCIATIONS_INCLUSION = CCorePlugin.PLUGIN_ID + ".associationInclusion"; + public static final String PREFS_ASSOCIATIONS_EXCLUSION = CCorePlugin.PLUGIN_ID + ".associationExclusion"; + + ResolverModel fModel; + + private static final String EXTENSION_ASSOC = "CFileTypeAssociation"; //$NON-NLS-1$ + private static final String ATTR_TYPE = "type"; //$NON-NLS-1$ + private static final String ATTR_PATTERN = "pattern"; //$NON-NLS-1$ + private static final String ATTR_FILE = "file"; //$NON-NLS-1$ + + public WorkspaceResolver() { + this(ResolverModel.getDefault()); + } + + public WorkspaceResolver(ResolverModel model) { + super(ResourcesPlugin.getWorkspace().getRoot()); + fModel = model; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.internal.filetype.CFileTypeResolver#doAdjustAssociations(org.eclipse.cdt.core.filetype.ICFileTypeAssociation[], org.eclipse.cdt.core.filetype.ICFileTypeAssociation[], boolean, org.eclipse.core.runtime.IProgressMonitor) + */ + protected void doAdjustAssociations(ICFileTypeAssociation[] addAssocs, + ICFileTypeAssociation[] delAssocs, boolean triggerEvent) { + List deltas = new ArrayList(); + + // add + if (triggerEvent && null != addAssocs && addAssocs.length > 0) { + for (int i = 0; i < addAssocs.length; i++) { + deltas.add(new ResolverDelta(addAssocs[i], ResolverDelta.EVENT_ADD)); + } + } + + // remove + if (triggerEvent && null != delAssocs && delAssocs.length > 0) { + for (int i = 0; i < delAssocs.length; i++) { + deltas.add(new ResolverDelta(delAssocs[i], ResolverDelta.EVENT_REMOVE)); + } + } + + // fire the deltas. + if (triggerEvent && !deltas.isEmpty()) { + ResolverChangeEvent event = new ResolverChangeEvent(fModel, this); + for (int i = 0; i < deltas.size(); ++i) { + ResolverDelta delta = (ResolverDelta)deltas.get(i); + event.addDelta(delta); + } + fModel.fireEvent(event); + } + + // add + if (null != addAssocs && addAssocs.length > 0) { + List inclusion = getInclusionAssociations(); + inclusion.addAll(Arrays.asList(addAssocs)); + ICFileTypeAssociation[] newInclusion = ((ICFileTypeAssociation[]) inclusion.toArray(new ICFileTypeAssociation[inclusion.size()])); + setInclusionAssociations(newInclusion); + } + // remove + if (null != delAssocs && delAssocs.length > 0) { + List exclusion = getExclusionAssociations(); + exclusion.addAll(Arrays.asList(delAssocs)); + ICFileTypeAssociation[] newExclusion = ((ICFileTypeAssociation[]) exclusion.toArray(new ICFileTypeAssociation[exclusion.size()])); + setExclusionAssociations(newExclusion); + } + if ((null != addAssocs && addAssocs.length > 0) || (null != delAssocs && delAssocs.length > 0)) { + CCorePlugin.getDefault().savePluginPreferences(); + } + } + + public List getExtensionsAssociations() { + List assoc = new ArrayList(); + IExtensionPoint point = getExtensionPoint(EXTENSION_ASSOC); + IExtension[] extensions = point.getExtensions(); + IConfigurationElement[] elements = null; + + for (int i = 0; i < extensions.length; i++) { + elements = extensions[i].getConfigurationElements(); + for (int j = 0; j < elements.length; j++) { + ICFileType typeRef = fModel.getFileTypeById(elements[j].getAttribute(ATTR_TYPE)); + if (null != typeRef) { + assoc.addAll(getAssocFromExtension(typeRef, elements[j])); + assoc.addAll(getAssocFromFile(typeRef, elements[j])); + } + } + } + return assoc; + } + + public List getDefaultInclusionAssociations() { + Preferences prefs = CCorePlugin.getDefault().getPluginPreferences(); + String s = prefs.getDefaultString(PREFS_ASSOCIATIONS_INCLUSION); + String[] items = s.split(";"); //$NON-NLS-1$ + List assoc = getAssocFromPreferences(items); + return assoc; + } + + public List getInclusionAssociations() { + Preferences prefs = CCorePlugin.getDefault().getPluginPreferences(); + String s = prefs.getString(PREFS_ASSOCIATIONS_INCLUSION); + String[] items = s.split(";"); //$NON-NLS-1$ + List assoc = getAssocFromPreferences(items); + return assoc; + } + + private void setInclusionAssociations(ICFileTypeAssociation[] addAssocs) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < addAssocs.length; ++i) { + if (sb.length() > 0) { + sb.append(';'); + } + sb.append(addAssocs[i].getPattern()); + sb.append("!!"); //$NON-NLS-1 + sb.append(addAssocs[i].getType().getId()); + } + Preferences prefs = CCorePlugin.getDefault().getPluginPreferences(); + String s = prefs.getString(PREFS_ASSOCIATIONS_INCLUSION); + if (s.length() > 0) { + sb.append(';').append(s); + } + prefs.setValue(PREFS_ASSOCIATIONS_INCLUSION, sb.toString()); + } + + public List getDefaultExclusionAssociations() { + Preferences prefs = CCorePlugin.getDefault().getPluginPreferences(); + String s = prefs.getDefaultString(PREFS_ASSOCIATIONS_EXCLUSION); + String[] items = s.split(";"); //$NON-NLS-1$ + List assocs = getAssocFromPreferences(items); + return assocs; + } + + public List getExclusionAssociations() { + Preferences prefs = CCorePlugin.getDefault().getPluginPreferences(); + String s = prefs.getString(PREFS_ASSOCIATIONS_EXCLUSION); + String[] items = s.split(";"); //$NON-NLS-1$ + List assocs = getAssocFromPreferences(items); + return assocs; + } + + private void setExclusionAssociations(ICFileTypeAssociation[] addAssocs) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < addAssocs.length; ++i) { + if (sb.length() > 0) { + sb.append(';'); + } + sb.append(addAssocs[i].getPattern()); + sb.append("!!"); //$NON-NLS-1 + sb.append(addAssocs[i].getType().getId()); + } + Preferences prefs = CCorePlugin.getDefault().getPluginPreferences(); + String s = prefs.getString(PREFS_ASSOCIATIONS_EXCLUSION); + if (s.length() > 0) { + sb.append(';').append(s); + } + prefs.setValue(PREFS_ASSOCIATIONS_EXCLUSION, sb.toString()); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.internal.filetype.CFileTypeResolver#loadAssociations() + */ + protected ICFileTypeAssociation[] loadAssociations() { + List assocs = new ArrayList(); + List exclusion = getExclusionAssociations(); + List inclusion = getInclusionAssociations(); + for (int i = 0; i < inclusion.size(); ++i) { + Object inc = inclusion.get(i); + if (!exclusion.contains(inc)) { + assocs.add(inc); + } + } + List extensions = getExtensionsAssociations(); + for (int i = 0; i < extensions.size(); ++i) { + Object ext = extensions.get(i); + if (!exclusion.contains(ext)) { + assocs.add(ext); + } + } + return ((ICFileTypeAssociation[]) assocs.toArray(new ICFileTypeAssociation[assocs.size()])); + } + + /** + * Associate one or more file extensions with an ICFileType instance. + * + * @param typeRef reference to the ICFileType instance + * + * @param element configuration element to get file extensions from + */ + private List getAssocFromExtension(ICFileType typeRef, IConfigurationElement element) { + List assocs = new ArrayList(); + String attr = element.getAttribute(ATTR_PATTERN); + if (null != attr) { + String[] item = attr.split(","); //$NON-NLS-1$ + for (int i = 0; i < item.length; i++) { + try { + assocs.add(fModel.createAssocation(item[i].trim(), typeRef)); + } catch (IllegalArgumentException e) { + CCorePlugin.log(e); + } + } + } + return assocs; + } + + private List getAssocFromPreferences(String[] items) { + List assocs = new ArrayList(); + for (int i = 0; i < items.length; ++i) { + String[] item = items[i].split("!!"); //$NON-NLS-1$ + if (item.length == 2) { + String pattern = item[0].trim(); + ICFileType typeRef = fModel.getFileTypeById(item[1]); + try { + assocs.add(fModel.createAssocation(pattern, typeRef)); + } catch (IllegalArgumentException e) { + CCorePlugin.log(e); + } + } + } + return assocs; + } + + /** + * Associate the contents of a file with an ICFileType instance. + * + * The file is read, one entry per line; each line is taken as + * a pattern that should be associated with the specified ICFileType + * instance. + * + * @param typeRef reference to the ICFileType instance + * + * @param element configuration element to get file extensions from + */ + private List getAssocFromFile(ICFileType typeRef, IConfigurationElement element) { + List assocs = new ArrayList(); + String attr = element.getAttribute(ATTR_FILE); + + if (null != attr) { + URL baseURL = null; + URL fileURL = null; + BufferedReader in = null; + String line = null; + + try { + baseURL = Platform.getBundle(element.getDeclaringExtension().getNamespace()).getEntry("/"); //$NON-NLS-1$ + fileURL = new URL(baseURL, attr); + in = new BufferedReader(new InputStreamReader(fileURL.openStream())); + line = in.readLine(); + while (null != line) { + try { + assocs.add(fModel.createAssocation(line.trim(), typeRef)); + } catch (IllegalArgumentException e) { + CCorePlugin.log(e); + } + line = in.readLine(); + } + in.close(); + } catch (IOException e) { + CCorePlugin.log(e); + } + } + return assocs; + } + + private IExtensionPoint getExtensionPoint(String extensionPointId) { + return Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, extensionPointId); + } + +}