From d83f3ab70e91d023fc992b50f9e5f7fe0f8e2cf3 Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Mon, 26 Apr 2004 04:44:29 +0000 Subject: [PATCH] Move the persistency of the PathEntry in a different class and provide an extension point for it. --- core/org.eclipse.cdt.core/ChangeLog | 14 + .../cdt/internal/core/model/CProject.java | 25 +- .../internal/core/model/PathEntryManager.java | 393 ++++-------------- .../internal/core/model/PathEntryStore.java | 371 +++++++++++++++++ core/org.eclipse.cdt.core/plugin.xml | 20 + .../src/org/eclipse/cdt/core/CCorePlugin.java | 56 ++- .../cdt/core/resources/IPathEntryStore.java | 27 ++ .../resources/IPathEntryStoreListener.java | 25 ++ .../resources/PathEntryStoreChangedEvent.java | 33 ++ 9 files changed, 639 insertions(+), 325 deletions(-) create mode 100644 core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryStore.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryStore.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryStoreListener.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/PathEntryStoreChangedEvent.java diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 7a9dce4c6ce..c1749f4f167 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,17 @@ +2004-04-26 Alain Magloire + + Move the persistency of the IPathEntry in a differenct + class and provide an extension point for it. + + * plugin.xml + * model/org/eclipse/cdt/internal/core/model/CProject.java + * model/org/eclipse/cdt/internal/core/model/PathEntryManager.java + * model/org/eclipse/cdt/internal/core/model/PathEntryStore.java + + * src/org/eclipe/cdt/core/CCorePlugin.java + * src/org/eclipse/cdt/internal/core/resources/IPathEntryStore.java + * src/org/eclipse/cdt/internal/core/resources/IPathEntryStoreListener.java + * src/org/eclipse/cdt/internal/core/resources/PathEntryStoreChangedEvent.java 2004-04-23 Alain Magloire Tentative fix for PR 59098. diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java index 97800c0de92..acf5925c293 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java @@ -13,10 +13,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.eclipse.cdt.core.BinaryParserConfig; import org.eclipse.cdt.core.CCProjectNature; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CProjectNature; -import org.eclipse.cdt.core.IBinaryParser; import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; @@ -150,17 +150,13 @@ public class CProject extends Openable implements ICProject { } public ILibraryReference[] getLibraryReferences() throws CModelException { - IBinaryParser[] binParsers = null; - try { - binParsers = CCorePlugin.getDefault().getBinaryParser(getProject()); - } catch (CoreException e) { - } + BinaryParserConfig[] binConfigs = CModelManager.getDefault().getBinaryParser(getProject()); IPathEntry[] entries = getResolvedPathEntries(); ArrayList list = new ArrayList(entries.length); for (int i = 0; i < entries.length; i++) { if (entries[i].getEntryKind() == IPathEntry.CDT_LIBRARY) { ILibraryEntry entry = (ILibraryEntry) entries[i]; - ILibraryReference lib = getLibraryReference(this, binParsers, entry); + ILibraryReference lib = getLibraryReference(this, binConfigs, entry); if (lib != null) { list.add(lib); } @@ -169,19 +165,16 @@ public class CProject extends Openable implements ICProject { return (ILibraryReference[]) list.toArray(new ILibraryReference[0]); } - public static ILibraryReference getLibraryReference(ICProject cproject, IBinaryParser[] binParsers, ILibraryEntry entry) { - if (binParsers == null) { - try { - binParsers = CCorePlugin.getDefault().getBinaryParser(cproject.getProject()); - } catch (CoreException e) { - } + public static ILibraryReference getLibraryReference(ICProject cproject, BinaryParserConfig[] binConfigs, ILibraryEntry entry) { + if (binConfigs == null) { + binConfigs = CModelManager.getDefault().getBinaryParser(cproject.getProject()); } ILibraryReference lib = null; - if (binParsers != null) { - for (int i = 0; i < binParsers.length; i++) { + if (binConfigs != null) { + for (int i = 0; i < binConfigs.length; i++) { IBinaryFile bin; try { - bin = binParsers[i].getBinary(entry.getPath()); + bin = binConfigs[i].getBinaryParser().getBinary(entry.getPath()); if (bin != null) { if (bin.getType() == IBinaryFile.ARCHIVE) { lib = new LibraryReferenceArchive(cproject, entry, (IBinaryArchive)bin); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java index 8984535fb13..dda408decd1 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java @@ -16,17 +16,14 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.CDescriptorEvent; -import org.eclipse.cdt.core.ICDescriptor; -import org.eclipse.cdt.core.ICDescriptorListener; 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.ICElementDelta; -import org.eclipse.cdt.core.model.ICModelStatus; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.IContainerEntry; +import org.eclipse.cdt.core.model.IElementChangedListener; import org.eclipse.cdt.core.model.IIncludeEntry; import org.eclipse.cdt.core.model.ILibraryEntry; import org.eclipse.cdt.core.model.IMacroEntry; @@ -36,7 +33,9 @@ import org.eclipse.cdt.core.model.IPathEntryContainer; import org.eclipse.cdt.core.model.IProjectEntry; import org.eclipse.cdt.core.model.ISourceEntry; import org.eclipse.cdt.core.model.PathEntryContainerInitializer; -import org.eclipse.cdt.internal.core.CharOperation; +import org.eclipse.cdt.core.resources.IPathEntryStore; +import org.eclipse.cdt.core.resources.IPathEntryStoreListener; +import org.eclipse.cdt.core.resources.PathEntryStoreChangedEvent; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.runtime.CoreException; @@ -49,35 +48,14 @@ import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; /** * @author alain * */ -public class PathEntryManager implements ICDescriptorListener { +public class PathEntryManager implements IPathEntryStoreListener, IElementChangedListener { static String CONTAINER_INITIALIZER_EXTPOINT_ID = "pathEntryContainerInitializer"; //$NON-NLS-1$ - static String PATH_ENTRY = "pathentry"; //$NON-NLS-1$ - static String PATH_ENTRY_ID = "org.eclipse.cdt.core.pathentry"; //$NON-NLS-1$ - static String ATTRIBUTE_KIND = "kind"; //$NON-NLS-1$ - static String ATTRIBUTE_PATH = "path"; //$NON-NLS-1$ - static String ATTRIBUTE_BASE_PATH = "base-path"; //$NON-NLS-1$ - static String ATTRIBUTE_BASE_REF = "base-ref"; //$NON-NLS-1$ - static String ATTRIBUTE_EXPORTED = "exported"; //$NON-NLS-1$ - static String ATTRIBUTE_SOURCEPATH = "sourcepath"; //$NON-NLS-1$ - static String ATTRIBUTE_ROOTPATH = "roopath"; //$NON-NLS-1$ - static String ATTRIBUTE_PREFIXMAPPING = "prefixmapping"; //$NON-NLS-1$ - static String ATTRIBUTE_EXCLUDING = "excluding"; //$NON-NLS-1$ - static String ATTRIBUTE_INCLUDE = "include"; //$NON-NLS-1$ - static String ATTRIBUTE_SYSTEM = "system"; //$NON-NLS-1$ - static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$ - static String ATTRIBUTE_VALUE = "value"; //$NON-NLS-1$ - static String VALUE_TRUE = "true"; //$NON-NLS-1$ - final static IPathEntry[] EMPTY = {}; /** * An empty array of strings indicating that a project doesn't have any prerequesite projects. */ @@ -90,8 +68,10 @@ public class PathEntryManager implements ICDescriptorListener { static final IPathEntry[] NO_PATHENTRIES = new IPathEntry[0]; HashMap resolvedMap = new HashMap(); - private static PathEntryManager pathEntryManager; + HashMap storeMap = new HashMap(); + + private static PathEntryManager pathEntryManager; private PathEntryManager() { } @@ -101,10 +81,7 @@ public class PathEntryManager implements ICDescriptorListener { public static PathEntryManager getDefault() { if (pathEntryManager == null) { pathEntryManager = new PathEntryManager(); - // Register the Core Model on the Descriptor - // Manager, it needs to know about changes. - CCorePlugin.getDefault().getCDescriptorManager().addDescriptorListener(pathEntryManager); - + CoreModel.getDefault().addElementChangedListener(pathEntryManager); } return pathEntryManager; } @@ -228,23 +205,14 @@ public class PathEntryManager implements ICDescriptorListener { } public IPathEntry[] getRawPathEntries(ICProject cproject) throws CModelException { - CModelManager factory = CModelManager.getDefault(); - if (!(CoreModel.hasCNature(cproject.getProject()) || CoreModel.hasCCNature(cproject.getProject()))) { + IProject project = cproject.getProject(); + if (!(CoreModel.hasCNature(project) || CoreModel.hasCCNature(project))) { return NO_PATHENTRIES; } - ArrayList pathEntries = new ArrayList(); + IPathEntry[] pathEntries = NO_PATHENTRIES; try { - ICDescriptor cdesc = CCorePlugin.getDefault().getCProjectDescription(cproject.getProject()); - Element element = cdesc.getProjectData(PATH_ENTRY_ID); - NodeList list = element.getChildNodes(); - for (int i = 0; i < list.getLength(); i++) { - Node childNode = list.item(i); - if (childNode.getNodeType() == Node.ELEMENT_NODE) { - if (childNode.getNodeName().equals(PATH_ENTRY)) { - pathEntries.add(decodePathEntry(cproject, (Element) childNode)); - } - } - } + IPathEntryStore store = getPathEntryStore(project); + pathEntries = store.getRawPathEntries(project); } catch (CoreException e) { throw new CModelException(e); } @@ -254,8 +222,8 @@ public class PathEntryManager implements ICDescriptorListener { // if no source is specified we return the project boolean foundSource = false; boolean foundOutput = false; - for (int i = 0; i < pathEntries.size(); i++) { - IPathEntry rawEntry = (IPathEntry) pathEntries.get(i); + for (int i = 0; i < pathEntries.length; i++) { + IPathEntry rawEntry = (IPathEntry) pathEntries[i]; if (rawEntry.getEntryKind() == IPathEntry.CDT_SOURCE) { foundSource = true; } @@ -265,12 +233,18 @@ public class PathEntryManager implements ICDescriptorListener { } if (!foundSource) { - pathEntries.add(CoreModel.newSourceEntry(cproject.getPath())); + IPathEntry[] newEntries = new IPathEntry[pathEntries.length + 1]; + System.arraycopy(pathEntries, 0, newEntries, 0, pathEntries.length); + newEntries[pathEntries.length] = CoreModel.newSourceEntry(cproject.getPath()); + pathEntries = newEntries; } if (!foundOutput) { - pathEntries.add(CoreModel.newOutputEntry(cproject.getPath())); + IPathEntry[] newEntries = new IPathEntry[pathEntries.length + 1]; + System.arraycopy(pathEntries, 0, newEntries, 0, pathEntries.length); + newEntries[pathEntries.length] = CoreModel.newOutputEntry(cproject.getPath()); + pathEntries = newEntries; } - return (IPathEntry[]) pathEntries.toArray(EMPTY); + return pathEntries; } public void setPathEntryContainer(ICProject[] affectedProjects, IPathEntryContainer newContainer, IProgressMonitor monitor) @@ -486,21 +460,9 @@ public class PathEntryManager implements ICDescriptorListener { public void saveRawPathEntries(ICProject cproject, IPathEntry[] newRawEntries) throws CModelException { try { - ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(cproject.getProject()); - Element rootElement = descriptor.getProjectData(PATH_ENTRY_ID); - // Clear out all current children - Node child = rootElement.getFirstChild(); - while (child != null) { - rootElement.removeChild(child); - child = rootElement.getFirstChild(); - } - // Save the entries - if (newRawEntries != null && newRawEntries.length > 0) { - // Serialize the include paths - Document doc = rootElement.getOwnerDocument(); - encodePathEntries(cproject.getPath(), doc, rootElement, newRawEntries); - } - descriptor.saveProjectData(); + IProject project = cproject.getProject(); + IPathEntryStore store = getPathEntryStore(project); + store.setRawPathEntries(project, newRawEntries); resolvedMap.remove(cproject); } catch (CoreException e) { throw new CModelException(e); @@ -653,255 +615,70 @@ public class PathEntryManager implements ICDescriptorListener { return containerIDs; } - static IPathEntry decodePathEntry(ICProject cProject, Element element) throws CModelException { - IPath projectPath = cProject.getProject().getFullPath(); - - // kind - String kindAttr = element.getAttribute(ATTRIBUTE_KIND); - int kind = PathEntry.kindFromString(kindAttr); - - // exported flag - boolean isExported = false; - if (element.hasAttribute(ATTRIBUTE_EXPORTED)) { - isExported = element.getAttribute(ATTRIBUTE_EXPORTED).equals(VALUE_TRUE); - } - - // get path and ensure it is absolute - //String pathAttr = element.getAttribute(ATTRIBUTE_PATH); - IPath path = new Path(element.getAttribute(ATTRIBUTE_PATH)); - if (!path.isAbsolute()) { - path = projectPath.append(path); - } - - // check fo the base path - IPath basePath = new Path(element.getAttribute(ATTRIBUTE_BASE_PATH)); - - // get the base ref - IPath baseRef = new Path(element.getAttribute(ATTRIBUTE_BASE_REF)); - - // source attachment info (optional) - IPath sourceAttachmentPath = element.hasAttribute(ATTRIBUTE_SOURCEPATH) ? new Path( - element.getAttribute(ATTRIBUTE_SOURCEPATH)) : null; - IPath sourceAttachmentRootPath = element.hasAttribute(ATTRIBUTE_ROOTPATH) ? new Path( - element.getAttribute(ATTRIBUTE_ROOTPATH)) : null; - IPath sourceAttachmentPrefixMapping = element.hasAttribute(ATTRIBUTE_PREFIXMAPPING) ? new Path( - element.getAttribute(ATTRIBUTE_PREFIXMAPPING)) : null; - - // exclusion patterns (optional) - String exclusion = element.getAttribute(ATTRIBUTE_EXCLUDING); - IPath[] exclusionPatterns = APathEntry.NO_EXCLUSION_PATTERNS; - if (!exclusion.equals("")) { //$NON-NLS-1$ - char[][] patterns = CharOperation.splitOn('|', exclusion.toCharArray()); - int patternCount; - if ((patternCount = patterns.length) > 0) { - exclusionPatterns = new IPath[patternCount]; - for (int j = 0; j < patterns.length; j++) { - exclusionPatterns[j] = new Path(new String(patterns[j])); - } - } - } - - // recreate the entry - switch (kind) { - case IPathEntry.CDT_PROJECT : - return CoreModel.newProjectEntry(path, isExported); - case IPathEntry.CDT_LIBRARY : - if (!baseRef.isEmpty()) { - return CoreModel.newLibraryRefEntry(baseRef, path); - } - return CoreModel.newLibraryEntry(basePath, path, sourceAttachmentPath, sourceAttachmentRootPath, - sourceAttachmentPrefixMapping, isExported); - case IPathEntry.CDT_SOURCE : - { - // must be an entry in this project or specify another - // project - String projSegment = path.segment(0); - if (projSegment != null && projSegment.equals(cProject.getElementName())) { // this - // project - return CoreModel.newSourceEntry(path, exclusionPatterns); - } else { // another project - return CoreModel.newProjectEntry(path, isExported); - } - } - case IPathEntry.CDT_OUTPUT : - { - return CoreModel.newOutputEntry(path, exclusionPatterns); - } - case IPathEntry.CDT_INCLUDE : - { - // include path info - IPath includePath = new Path(element.getAttribute(ATTRIBUTE_INCLUDE)); - // isSysteminclude - boolean isSystemInclude = false; - if (element.hasAttribute(ATTRIBUTE_SYSTEM)) { - isSystemInclude = element.getAttribute(ATTRIBUTE_SYSTEM).equals(VALUE_TRUE); - } - if (!baseRef.isEmpty()) { - return CoreModel.newIncludeRefEntry(path, baseRef, includePath); - } - return CoreModel.newIncludeEntry(path, basePath, includePath, isSystemInclude, exclusionPatterns, isExported); - } - case IPathEntry.CDT_MACRO : - { - String macroName = element.getAttribute(ATTRIBUTE_NAME); - String macroValue = element.getAttribute(ATTRIBUTE_VALUE); - if (!baseRef.isEmpty()) { - return CoreModel.newMacroRefEntry(path, baseRef, macroName); - } - return CoreModel.newMacroEntry(path, macroName, macroValue, exclusionPatterns, isExported); - } - case IPathEntry.CDT_CONTAINER : - { - IPath id = new Path(element.getAttribute(ATTRIBUTE_PATH)); - return CoreModel.newContainerEntry(id, isExported); - } - default : - { - ICModelStatus status = new CModelStatus(ICModelStatus.ERROR, "PathEntry: unknown kind (" + kindAttr + ")"); //$NON-NLS-1$ //$NON-NLS-2$ - throw new CModelException(status); - } + IPathEntryStore getPathEntryStore(IProject project) throws CoreException { + IPathEntryStore store = (IPathEntryStore)storeMap.get(project); + if (store == null) { + store = CCorePlugin.getDefault().getPathEntryStore(project); + storeMap.put(project, store); + store.addPathEntryStoreListener(this); } + return store; } - static void encodePathEntries(IPath projectPath, Document doc, Element configRootElement, IPathEntry[] entries) { - Element element; - for (int i = 0; i < entries.length; i++) { - element = doc.createElement(PATH_ENTRY); - - configRootElement.appendChild(element); - int kind = entries[i].getEntryKind(); - // Set the kind - element.setAttribute(ATTRIBUTE_KIND, PathEntry.kindToString(kind)); - - // translate the project prefix. - IPath xmlPath = entries[i].getPath(); - if (xmlPath == null) { - xmlPath = new Path(""); - } - if (kind != IPathEntry.CDT_CONTAINER) { - // translate to project relative from absolute (unless a device path) - if (xmlPath.isAbsolute()) { - if (projectPath != null && projectPath.isPrefixOf(xmlPath)) { - if (xmlPath.segment(0).equals(projectPath.segment(0))) { - xmlPath = xmlPath.removeFirstSegments(1); - xmlPath = xmlPath.makeRelative(); - } else { - xmlPath = xmlPath.makeAbsolute(); - } - } - } - } - - // Save the path - element.setAttribute(ATTRIBUTE_PATH, xmlPath.toString()); - - // Specifics to the entries - switch(kind) { - case IPathEntry.CDT_SOURCE: - case IPathEntry.CDT_OUTPUT: - case IPathEntry.CDT_PROJECT: - case IPathEntry.CDT_CONTAINER: - break; - case IPathEntry.CDT_LIBRARY: { - ILibraryEntry lib = (ILibraryEntry) entries[i]; - IPath sourcePath = lib.getSourceAttachmentPath(); - if (sourcePath != null) { - // translate to project relative from absolute - if (projectPath != null && projectPath.isPrefixOf(sourcePath)) { - if (sourcePath.segment(0).equals(projectPath.segment(0))) { - sourcePath = sourcePath.removeFirstSegments(1); - sourcePath = sourcePath.makeRelative(); - } - } - element.setAttribute(ATTRIBUTE_SOURCEPATH, sourcePath.toString()); - } - if (lib.getSourceAttachmentRootPath() != null) { - element.setAttribute(ATTRIBUTE_ROOTPATH, lib.getSourceAttachmentRootPath().toString()); - } - if (lib.getSourceAttachmentPrefixMapping() != null) { - element.setAttribute(ATTRIBUTE_PREFIXMAPPING, lib.getSourceAttachmentPrefixMapping().toString()); - } - break; - } - case IPathEntry.CDT_INCLUDE: { - IIncludeEntry include = (IIncludeEntry) entries[i]; - IPath includePath = include.getIncludePath(); - element.setAttribute(ATTRIBUTE_INCLUDE, includePath.toString()); - if (include.isSystemInclude()) { - element.setAttribute(ATTRIBUTE_SYSTEM, VALUE_TRUE); - } - break; - } - case IPathEntry.CDT_MACRO: { - IMacroEntry macro = (IMacroEntry) entries[i]; - element.setAttribute(ATTRIBUTE_NAME, macro.getMacroName()); - element.setAttribute(ATTRIBUTE_VALUE, macro.getMacroValue()); - break; - } - } - - if (entries[i] instanceof APathEntry) { - APathEntry entry = (APathEntry) entries[i]; - - // save the basePath or the baseRef - IPath basePath = entry.getBasePath(); - IPath baseRef = entry.getBaseReference(); - if (basePath != null && !basePath.isEmpty()) { - element.setAttribute(ATTRIBUTE_BASE_PATH, basePath.toString()); - } else if (baseRef != null && !baseRef.isEmpty()) { - element.setAttribute(ATTRIBUTE_BASE_REF, baseRef.toString()); - } - - // Save the exclusions attributes - IPath[] exclusionPatterns = entry.getExclusionPatterns(); - if (exclusionPatterns.length > 0) { - StringBuffer excludeRule = new StringBuffer(10); - for (int j = 0, max = exclusionPatterns.length; j < max; j++) { - if (j > 0) { - excludeRule.append('|'); - } - excludeRule.append(exclusionPatterns[j]); - } - element.setAttribute(ATTRIBUTE_EXCLUDING, excludeRule.toString()); - } - } - - // Save the export attribute - if (entries[i].isExported()) { - element.setAttribute(ATTRIBUTE_EXPORTED, VALUE_TRUE); - } - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.cdt.core.ICDescriptorListener#descriptorChanged(org.eclipse.cdt.core.CDescriptorEvent) + /* (non-Javadoc) + * @see org.eclipse.cdt.core.resources.IPathEntryStoreListener#pathEntryStoreChanged(org.eclipse.cdt.core.resources.PathEntryChangedEvent) */ - public void descriptorChanged(CDescriptorEvent event) { - if (event.getType() == CDescriptorEvent.CDTPROJECT_CHANGED) { - ICDescriptor cdesc = event.getDescriptor(); - if (cdesc != null) { - CModelManager manager = CModelManager.getDefault(); - IProject project = cdesc.getProject(); - if (CoreModel.hasCNature(project) || CoreModel.hasCCNature(project)) { - ICProject cproject = manager.create(project); - try { - IPathEntry[] oldResolvedEntries = getResolvedPathEntries(cproject); - resolvedMap.remove(cproject); - IPathEntry[] newResolvedEntries = getResolvedPathEntries(cproject); - ICElementDelta[] deltas = generatePathEntryDeltas(cproject, oldResolvedEntries, newResolvedEntries); - if (deltas.length > 0) { - cproject.close(); - for (int i = 0; i < deltas.length; i++) { - manager.registerCModelDelta(deltas[i]); - } - manager.fire(ElementChangedEvent.POST_CHANGE); - } - } catch (CModelException e) { + public void pathEntryStoreChanged(PathEntryStoreChangedEvent event) { + IProject project = event.getProject(); + if (project != null && (CoreModel.hasCNature(project) || CoreModel.hasCCNature(project))) { + CModelManager manager = CModelManager.getDefault(); + ICProject cproject = manager.create(project); + try { + IPathEntry[] oldResolvedEntries = getResolvedPathEntries(cproject); + resolvedMap.remove(cproject); + IPathEntry[] newResolvedEntries = getResolvedPathEntries(cproject); + ICElementDelta[] deltas = generatePathEntryDeltas(cproject, oldResolvedEntries, newResolvedEntries); + if (deltas.length > 0) { + cproject.close(); + for (int i = 0; i < deltas.length; i++) { + manager.registerCModelDelta(deltas[i]); } + manager.fire(ElementChangedEvent.POST_CHANGE); } + } catch (CModelException e) { } } } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.model.IElementChangedListener#elementChanged(org.eclipse.cdt.core.model.ElementChangedEvent) + */ + public void elementChanged(ElementChangedEvent event) { + try { + processDelta(event.getDelta()); + } catch(CModelException e) { + } + } + + protected void processDelta(ICElementDelta delta) throws CModelException { + int kind= delta.getKind(); + int flags= delta.getFlags(); + ICElement element= delta.getElement(); + + //System.out.println("Processing " + element); + + // handle closing and removing of projects + if (((flags & ICElementDelta.F_CLOSED) != 0) || (kind == ICElementDelta.REMOVED)) { + if (element.getElementType() == ICElement.C_PROJECT) { + IProject project = element.getCProject().getProject(); + IPathEntryStore store = (IPathEntryStore)storeMap.remove(project); + store.removePathEntryStoreListener(this); + resolvedMap.remove(project); + } + } + ICElementDelta[] affectedChildren= delta.getAffectedChildren(); + for (int i= 0; i < affectedChildren.length; i++) { + processDelta(affectedChildren[i]); + } + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryStore.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryStore.java new file mode 100644 index 00000000000..44909a73d2e --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryStore.java @@ -0,0 +1,371 @@ +/********************************************************************** + * Copyright (c) 2002,2003,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.internal.core.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.cdt.core.AbstractCExtension; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CDescriptorEvent; +import org.eclipse.cdt.core.ICDescriptor; +import org.eclipse.cdt.core.ICDescriptorListener; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICModelStatus; +import org.eclipse.cdt.core.model.IIncludeEntry; +import org.eclipse.cdt.core.model.ILibraryEntry; +import org.eclipse.cdt.core.model.IMacroEntry; +import org.eclipse.cdt.core.model.IPathEntry; +import org.eclipse.cdt.core.resources.IPathEntryStore; +import org.eclipse.cdt.core.resources.IPathEntryStoreListener; +import org.eclipse.cdt.core.resources.PathEntryStoreChangedEvent; +import org.eclipse.cdt.internal.core.CharOperation; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * PathEntryStore + */ +public class PathEntryStore extends AbstractCExtension implements IPathEntryStore, ICDescriptorListener { + + static String PATH_ENTRY = "pathentry"; //$NON-NLS-1$ + static String PATH_ENTRY_ID = "org.eclipse.cdt.core.pathentry"; //$NON-NLS-1$ + static String ATTRIBUTE_KIND = "kind"; //$NON-NLS-1$ + static String ATTRIBUTE_PATH = "path"; //$NON-NLS-1$ + static String ATTRIBUTE_BASE_PATH = "base-path"; //$NON-NLS-1$ + static String ATTRIBUTE_BASE_REF = "base-ref"; //$NON-NLS-1$ + static String ATTRIBUTE_EXPORTED = "exported"; //$NON-NLS-1$ + static String ATTRIBUTE_SOURCEPATH = "sourcepath"; //$NON-NLS-1$ + static String ATTRIBUTE_ROOTPATH = "roopath"; //$NON-NLS-1$ + static String ATTRIBUTE_PREFIXMAPPING = "prefixmapping"; //$NON-NLS-1$ + static String ATTRIBUTE_EXCLUDING = "excluding"; //$NON-NLS-1$ + static String ATTRIBUTE_INCLUDE = "include"; //$NON-NLS-1$ + static String ATTRIBUTE_SYSTEM = "system"; //$NON-NLS-1$ + static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$ + static String ATTRIBUTE_VALUE = "value"; //$NON-NLS-1$ + static String VALUE_TRUE = "true"; //$NON-NLS-1$ + + static final IPathEntry[] NO_PATHENTRIES = new IPathEntry[0]; + + List listeners; + + /** + * + */ + public PathEntryStore() { + super(); + listeners = Collections.synchronizedList(new ArrayList()); + // Register the Core Model on the Descriptor + // Manager, it needs to know about changes. + CCorePlugin.getDefault().getCDescriptorManager().addDescriptorListener(this); + } + + public IPathEntry[] getRawPathEntries(IProject project) throws CoreException { + ArrayList pathEntries = new ArrayList(); + ICDescriptor cdesc = CCorePlugin.getDefault().getCProjectDescription(project); + Element element = cdesc.getProjectData(PATH_ENTRY_ID); + NodeList list = element.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node childNode = list.item(i); + if (childNode.getNodeType() == Node.ELEMENT_NODE) { + if (childNode.getNodeName().equals(PATH_ENTRY)) { + pathEntries.add(decodePathEntry(project, (Element) childNode)); + } + } + } + + return (IPathEntry[]) pathEntries.toArray(NO_PATHENTRIES); + } + + public void setRawPathEntries(IProject project, IPathEntry[] newRawEntries) throws CoreException { + ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(project); + Element rootElement = descriptor.getProjectData(PATH_ENTRY_ID); + // Clear out all current children + Node child = rootElement.getFirstChild(); + while (child != null) { + rootElement.removeChild(child); + child = rootElement.getFirstChild(); + } + // Save the entries + if (newRawEntries != null && newRawEntries.length > 0) { + // Serialize the include paths + Document doc = rootElement.getOwnerDocument(); + encodePathEntries(project.getFullPath(), doc, rootElement, newRawEntries); + } + descriptor.saveProjectData(); + } + + static IPathEntry decodePathEntry(IProject project, Element element) throws CModelException { + IPath projectPath = project.getFullPath(); + + // kind + String kindAttr = element.getAttribute(ATTRIBUTE_KIND); + int kind = PathEntry.kindFromString(kindAttr); + + // exported flag + boolean isExported = false; + if (element.hasAttribute(ATTRIBUTE_EXPORTED)) { + isExported = element.getAttribute(ATTRIBUTE_EXPORTED).equals(VALUE_TRUE); + } + + // get path and ensure it is absolute + //String pathAttr = element.getAttribute(ATTRIBUTE_PATH); + IPath path = new Path(element.getAttribute(ATTRIBUTE_PATH)); + if (!path.isAbsolute()) { + path = projectPath.append(path); + } + + // check fo the base path + IPath basePath = new Path(element.getAttribute(ATTRIBUTE_BASE_PATH)); + + // get the base ref + IPath baseRef = new Path(element.getAttribute(ATTRIBUTE_BASE_REF)); + + // source attachment info (optional) + IPath sourceAttachmentPath = element.hasAttribute(ATTRIBUTE_SOURCEPATH) ? new Path( + element.getAttribute(ATTRIBUTE_SOURCEPATH)) : null; + IPath sourceAttachmentRootPath = element.hasAttribute(ATTRIBUTE_ROOTPATH) ? new Path( + element.getAttribute(ATTRIBUTE_ROOTPATH)) : null; + IPath sourceAttachmentPrefixMapping = element.hasAttribute(ATTRIBUTE_PREFIXMAPPING) ? new Path( + element.getAttribute(ATTRIBUTE_PREFIXMAPPING)) : null; + + // exclusion patterns (optional) + String exclusion = element.getAttribute(ATTRIBUTE_EXCLUDING); + IPath[] exclusionPatterns = APathEntry.NO_EXCLUSION_PATTERNS; + if (!exclusion.equals("")) { //$NON-NLS-1$ + char[][] patterns = CharOperation.splitOn('|', exclusion.toCharArray()); + int patternCount; + if ((patternCount = patterns.length) > 0) { + exclusionPatterns = new IPath[patternCount]; + for (int j = 0; j < patterns.length; j++) { + exclusionPatterns[j] = new Path(new String(patterns[j])); + } + } + } + + // recreate the entry + switch (kind) { + case IPathEntry.CDT_PROJECT : + return CoreModel.newProjectEntry(path, isExported); + case IPathEntry.CDT_LIBRARY : + if (!baseRef.isEmpty()) { + return CoreModel.newLibraryRefEntry(baseRef, path); + } + return CoreModel.newLibraryEntry(basePath, path, sourceAttachmentPath, sourceAttachmentRootPath, + sourceAttachmentPrefixMapping, isExported); + case IPathEntry.CDT_SOURCE : + { + // must be an entry in this project or specify another + // project + String projSegment = path.segment(0); + if (projSegment != null && projSegment.equals(project.getName())) { // this + // project + return CoreModel.newSourceEntry(path, exclusionPatterns); + } else { // another project + return CoreModel.newProjectEntry(path, isExported); + } + } + case IPathEntry.CDT_OUTPUT : + { + return CoreModel.newOutputEntry(path, exclusionPatterns); + } + case IPathEntry.CDT_INCLUDE : + { + // include path info + IPath includePath = new Path(element.getAttribute(ATTRIBUTE_INCLUDE)); + // isSysteminclude + boolean isSystemInclude = false; + if (element.hasAttribute(ATTRIBUTE_SYSTEM)) { + isSystemInclude = element.getAttribute(ATTRIBUTE_SYSTEM).equals(VALUE_TRUE); + } + if (!baseRef.isEmpty()) { + return CoreModel.newIncludeRefEntry(path, baseRef, includePath); + } + return CoreModel.newIncludeEntry(path, basePath, includePath, isSystemInclude, exclusionPatterns, isExported); + } + case IPathEntry.CDT_MACRO : + { + String macroName = element.getAttribute(ATTRIBUTE_NAME); + String macroValue = element.getAttribute(ATTRIBUTE_VALUE); + if (!baseRef.isEmpty()) { + return CoreModel.newMacroRefEntry(path, baseRef, macroName); + } + return CoreModel.newMacroEntry(path, macroName, macroValue, exclusionPatterns, isExported); + } + case IPathEntry.CDT_CONTAINER : + { + IPath id = new Path(element.getAttribute(ATTRIBUTE_PATH)); + return CoreModel.newContainerEntry(id, isExported); + } + default : + { + ICModelStatus status = new CModelStatus(ICModelStatus.ERROR, "PathEntry: unknown kind (" + kindAttr + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + throw new CModelException(status); + } + } + } + + static void encodePathEntries(IPath projectPath, Document doc, Element configRootElement, IPathEntry[] entries) { + Element element; + for (int i = 0; i < entries.length; i++) { + element = doc.createElement(PATH_ENTRY); + + configRootElement.appendChild(element); + int kind = entries[i].getEntryKind(); + // Set the kind + element.setAttribute(ATTRIBUTE_KIND, PathEntry.kindToString(kind)); + + // translate the project prefix. + IPath xmlPath = entries[i].getPath(); + if (xmlPath == null) { + xmlPath = new Path(""); + } + if (kind != IPathEntry.CDT_CONTAINER) { + // translate to project relative from absolute (unless a device path) + if (xmlPath.isAbsolute()) { + if (projectPath != null && projectPath.isPrefixOf(xmlPath)) { + if (xmlPath.segment(0).equals(projectPath.segment(0))) { + xmlPath = xmlPath.removeFirstSegments(1); + xmlPath = xmlPath.makeRelative(); + } else { + xmlPath = xmlPath.makeAbsolute(); + } + } + } + } + + // Save the path + element.setAttribute(ATTRIBUTE_PATH, xmlPath.toString()); + + // Specifics to the entries + switch(kind) { + case IPathEntry.CDT_SOURCE: + case IPathEntry.CDT_OUTPUT: + case IPathEntry.CDT_PROJECT: + case IPathEntry.CDT_CONTAINER: + break; + case IPathEntry.CDT_LIBRARY: { + ILibraryEntry lib = (ILibraryEntry) entries[i]; + IPath sourcePath = lib.getSourceAttachmentPath(); + if (sourcePath != null) { + // translate to project relative from absolute + if (projectPath != null && projectPath.isPrefixOf(sourcePath)) { + if (sourcePath.segment(0).equals(projectPath.segment(0))) { + sourcePath = sourcePath.removeFirstSegments(1); + sourcePath = sourcePath.makeRelative(); + } + } + element.setAttribute(ATTRIBUTE_SOURCEPATH, sourcePath.toString()); + } + if (lib.getSourceAttachmentRootPath() != null) { + element.setAttribute(ATTRIBUTE_ROOTPATH, lib.getSourceAttachmentRootPath().toString()); + } + if (lib.getSourceAttachmentPrefixMapping() != null) { + element.setAttribute(ATTRIBUTE_PREFIXMAPPING, lib.getSourceAttachmentPrefixMapping().toString()); + } + break; + } + case IPathEntry.CDT_INCLUDE: { + IIncludeEntry include = (IIncludeEntry) entries[i]; + IPath includePath = include.getIncludePath(); + element.setAttribute(ATTRIBUTE_INCLUDE, includePath.toString()); + if (include.isSystemInclude()) { + element.setAttribute(ATTRIBUTE_SYSTEM, VALUE_TRUE); + } + break; + } + case IPathEntry.CDT_MACRO: { + IMacroEntry macro = (IMacroEntry) entries[i]; + element.setAttribute(ATTRIBUTE_NAME, macro.getMacroName()); + element.setAttribute(ATTRIBUTE_VALUE, macro.getMacroValue()); + break; + } + } + + if (entries[i] instanceof APathEntry) { + APathEntry entry = (APathEntry) entries[i]; + + // save the basePath or the baseRef + IPath basePath = entry.getBasePath(); + IPath baseRef = entry.getBaseReference(); + if (basePath != null && !basePath.isEmpty()) { + element.setAttribute(ATTRIBUTE_BASE_PATH, basePath.toString()); + } else if (baseRef != null && !baseRef.isEmpty()) { + element.setAttribute(ATTRIBUTE_BASE_REF, baseRef.toString()); + } + + // Save the exclusions attributes + IPath[] exclusionPatterns = entry.getExclusionPatterns(); + if (exclusionPatterns.length > 0) { + StringBuffer excludeRule = new StringBuffer(10); + for (int j = 0, max = exclusionPatterns.length; j < max; j++) { + if (j > 0) { + excludeRule.append('|'); + } + excludeRule.append(exclusionPatterns[j]); + } + element.setAttribute(ATTRIBUTE_EXCLUDING, excludeRule.toString()); + } + } + + // Save the export attribute + if (entries[i].isExported()) { + element.setAttribute(ATTRIBUTE_EXPORTED, VALUE_TRUE); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.core.ICDescriptorListener#descriptorChanged(org.eclipse.cdt.core.CDescriptorEvent) + */ + public void descriptorChanged(CDescriptorEvent event) { + if (event.getType() == CDescriptorEvent.CDTPROJECT_CHANGED) { + ICDescriptor cdesc = event.getDescriptor(); + if (cdesc != null) { + CModelManager manager = CModelManager.getDefault(); + IProject project = cdesc.getProject(); + // Call the listeners. + PathEntryStoreChangedEvent evt = new PathEntryStoreChangedEvent(project); + IPathEntryStoreListener[] observers = new IPathEntryStoreListener[listeners.size()]; + listeners.toArray(observers); + for (int i = 0; i < observers.length; i++) { + observers[i].pathEntryStoreChanged(evt); + } + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.resources.IPathEntryStore#addPathEntryStoreListener(org.eclipse.cdt.core.resources.IPathEntryStoreListener) + */ + public void addPathEntryStoreListener(IPathEntryStoreListener listener) { + listeners.add(listener); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.resources.IPathEntryStore#removePathEntryStoreListener(org.eclipse.cdt.core.resources.IPathEntryStoreListener) + */ + public void removePathEntryStoreListener(IPathEntryStoreListener listener) { + listeners.remove(listener); + } + +} diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml index b1eb2d209cc..1163befcf9a 100644 --- a/core/org.eclipse.cdt.core/plugin.xml +++ b/core/org.eclipse.cdt.core/plugin.xml @@ -39,6 +39,12 @@ + + + + + + @@ -92,6 +98,20 @@ + + + + + + + + + + 0) { + ArrayList list = new ArrayList(cextensions.length); + for (int i = 0; i < cextensions.length; i++) { + try { + store = (IPathEntryStore) cextensions[i].createExtension(); + break; + } catch (ClassCastException e) { + // + log(e); + } + } + } + } catch (CoreException e) { + // ignore since we fall back to a default.... + } + } + if (store == null) { + store = getDefaultPathEntryStore(); + } + return store; + } + + public IPathEntryStore getDefaultPathEntryStore() throws CoreException { + IPathEntryStore store = null; + IExtensionPoint extensionPoint = getDescriptor().getExtensionPoint(PATHENTRY_STORE_ID); + IExtension extension = extensionPoint.getExtension(DEFAULT_PATHENTRY_STORE_ID); + if (extension != null) { + IConfigurationElement element[] = extension.getConfigurationElements(); + for (int i = 0; i < element.length; i++) { + if (element[i].getName().equalsIgnoreCase("cextension")) { //$NON-NLS-1$ + store = (IPathEntryStore) element[i].createExecutableExtension("run"); //$NON-NLS-1$ + break; + } + } + } else { + IStatus s = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("CCorePlugin.exception.noBinaryFormat"), null); //$NON-NLS-1$ + throw new CoreException(s); + } + return store; + } + /** * Returns the file type object corresponding to the provided * file name. diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryStore.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryStore.java new file mode 100644 index 00000000000..7c857ec47d7 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryStore.java @@ -0,0 +1,27 @@ +/********************************************************************** + * Copyright (c) 2002,2003,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.resources; + +import org.eclipse.cdt.core.model.IPathEntry; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; + +/** + * IPathEntryStore + */ +public interface IPathEntryStore { + + IPathEntry[] getRawPathEntries(IProject project) throws CoreException; + void setRawPathEntries(IProject project, IPathEntry[] engries) throws CoreException; + void addPathEntryStoreListener(IPathEntryStoreListener listener); + void removePathEntryStoreListener(IPathEntryStoreListener listener); +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryStoreListener.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryStoreListener.java new file mode 100644 index 00000000000..ba75074f22d --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/IPathEntryStoreListener.java @@ -0,0 +1,25 @@ +/********************************************************************** + * Copyright (c) 2002,2003,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.resources; + +import java.util.EventListener; + +/** + * IPathEntryStoreListener + */ +public interface IPathEntryStoreListener extends EventListener { + /** + * + * @param event + */ + void pathEntryStoreChanged(PathEntryStoreChangedEvent event); +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/PathEntryStoreChangedEvent.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/PathEntryStoreChangedEvent.java new file mode 100644 index 00000000000..e3483766862 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/PathEntryStoreChangedEvent.java @@ -0,0 +1,33 @@ +/********************************************************************** + * Copyright (c) 2002,2003,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.resources; + +import java.util.EventObject; + +import org.eclipse.core.resources.IProject; + +/** + * PathEntryChangedEvent + */ +public class PathEntryStoreChangedEvent extends EventObject { + /** + * + */ + public PathEntryStoreChangedEvent(Object object) { + super(object); + } + + public IProject getProject() { + return (IProject)getSource(); + } + +}