diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 0de374040eb..b38df8f08f9 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,30 @@ +2004-03-17 David Inglis + + - Added new ICDescriptorManager providing listerner abilities on ICDescriptor and batch operations + - Now listen for ondisk modifications and verify and update ICDescriptor + - Restore .cdtproject if deleted. + - Handle case where no owner extension exisits for a project. + - Update .cdtproject file without notification to prevent deadlocking. + + Modified + * plugin.xml + * src/org/eclipse/cdt/core/CCorePlugin.java + * src/org/eclipse/cdt/core/ICDescriptor.java + * src/org/eclipse/cdt/core/ICExtensionReference.java + * src/org/eclipse/cdt/internal/core/CCorePluginResources.properties + * src/org/eclipse/cdt/internal/core/CDescriptor.java + * src/org/eclipse/cdt/internal/core/CDescriptorManager.java + * src/org/eclipse/cdt/internal/core/CExtensionReference.java + * src/org/eclipse/cdt/internal/core/COwner.java + * src/org/eclipse/cdt/internal/core/InternalCExtension.java + + New + * src/org/eclipse/cdt/core/CDescriptorEvent.java + * src/org/eclipse/cdt/core/ICDescriptorListener.java + * src/org/eclipse/cdt/core/ICDescriptorManager.java + * src/org/eclipse/cdt/core/ICDescriptorOperation.java + + 2004-03-16 Thomas Fletcher - Fix to address PR 45320 where we would mark warnings with diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml index e7d9be1a3b7..b03370e0401 100644 --- a/core/org.eclipse.cdt.core/plugin.xml +++ b/core/org.eclipse.cdt.core/plugin.xml @@ -17,7 +17,6 @@ - diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java index f190576c418..1a865ad8e9b 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java @@ -36,6 +36,7 @@ import org.eclipse.cdt.internal.core.search.processing.JobManager; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; @@ -558,6 +559,10 @@ public class CCorePlugin extends Plugin { fDescriptorManager.convert(project, id); } } + + public ICDescriptorManager getCDescriptorManager() { + return fDescriptorManager; + } /** * Creates a C project resource given the project handle and description. @@ -571,33 +576,39 @@ public class CCorePlugin extends Plugin { * @exception OperationCanceledException if the operation is canceled */ public IProject createCProject( - IProjectDescription description, - IProject projectHandle, + final IProjectDescription description, + final IProject projectHandle, IProgressMonitor monitor, - String projectID) + final String projectID) throws CoreException, OperationCanceledException { - try { - if (monitor == null) { - monitor = new NullProgressMonitor(); - } - monitor.beginTask("Creating C Project...", 3); //$NON-NLS-1$ - if (!projectHandle.exists()) { - projectHandle.create(description, new SubProgressMonitor(monitor, 1)); - } - if (monitor.isCanceled()) { - throw new OperationCanceledException(); + getWorkspace().run(new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + try { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + monitor.beginTask("Creating C Project...", 3); //$NON-NLS-1$ + if (!projectHandle.exists()) { + projectHandle.create(description, new SubProgressMonitor(monitor, 1)); + } + + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + + // Open first. + projectHandle.open(new SubProgressMonitor(monitor, 1)); + + mapCProjectOwner(projectHandle, projectID, false); + + // Add C Nature ... does not add duplicates + CProjectNature.addCNature(projectHandle, new SubProgressMonitor(monitor, 1)); + } finally { + monitor.done(); + } } - - // Open first. - projectHandle.open(new SubProgressMonitor(monitor, 1)); - - // Add C Nature ... does not add duplicates - mapCProjectOwner(projectHandle, projectID, false); - CProjectNature.addCNature(projectHandle, new SubProgressMonitor(monitor, 1)); - } finally { - monitor.done(); - } + }, getWorkspace().getRoot(), 0, monitor); return projectHandle; } @@ -614,7 +625,7 @@ public class CCorePlugin extends Plugin { public void convertProjectFromCtoCC(IProject projectHandle, IProgressMonitor monitor) throws CoreException { if ((projectHandle != null) - && projectHandle.hasNature(CCProjectNature.C_NATURE_ID) + && projectHandle.hasNature(CProjectNature.C_NATURE_ID) && !projectHandle.hasNature(CCProjectNature.CC_NATURE_ID)) { // Add C++ Nature ... does not add duplicates CCProjectNature.addCCNature(projectHandle, monitor); diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CDescriptorEvent.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CDescriptorEvent.java new file mode 100644 index 00000000000..6bdab45c681 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CDescriptorEvent.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2002, 2003, 2004 QNX Software Systems Ltd. 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; + +import java.util.EventObject; + +public class CDescriptorEvent extends EventObject { + + public static final int CDTPROJECT_CHANGED = 1; + public static final int CDTPROJECT_ADDED = 2; + public static final int CDTPROJECT_REMOVED = 3; + + public static final int OWNER_CHANGED = 0x10; + public static final int EXTENSION_CHANGED = 0x20; + + private static final int FLAGS_MASK = 0xf; + + private int fType; + + public CDescriptorEvent(ICDescriptor descriptor, int type, int flags) { + super(descriptor); + fType = type | flags; + } + + public ICDescriptor getDescriptor() { + return (ICDescriptor) getSource(); + } + + public int getType() { + return fType & FLAGS_MASK; + } + + public int getFlags() { + return fType & ~FLAGS_MASK; + } +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptor.java index edc1c385758..7a4c4f63eb2 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptor.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptor.java @@ -1,13 +1,12 @@ -/********************************************************************** - * Copyright (c) 2002,2003 QNX Software Systems Ltd. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html +/******************************************************************************* + * Copyright (c) 2002, 2003, 2004 QNX Software Systems Ltd. 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 -***********************************************************************/ + * Contributors: QNX Software Systems - Initial API and implementation + ******************************************************************************/ package org.eclipse.cdt.core; import org.eclipse.core.resources.IProject; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptorListener.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptorListener.java new file mode 100644 index 00000000000..324bb4cf7c0 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptorListener.java @@ -0,0 +1,14 @@ +/******************************************************************************* + * Copyright (c) 2002, 2003, 2004 QNX Software Systems Ltd. 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; + +public interface ICDescriptorListener { + public void descriptorChanged(CDescriptorEvent event); +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptorManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptorManager.java new file mode 100644 index 00000000000..b42bee97bc0 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptorManager.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2002, 2003, 2004 QNX Software Systems Ltd. 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; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; + +public interface ICDescriptorManager { + public ICDescriptor getDescriptor(IProject project) throws CoreException; + + public void runDescriptorOperation(ICDescriptor descriptor, ICDescriptorOperation op) throws CoreException; + + public void addDescriptorListener(ICDescriptorListener listener); + public void removeDescriptorListener(ICDescriptorListener listener); +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptorOperation.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptorOperation.java new file mode 100644 index 00000000000..59439d6e555 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICDescriptorOperation.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2002, 2003, 2004 QNX Software Systems Ltd. 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; + +import org.eclipse.core.runtime.CoreException; + +public interface ICDescriptorOperation { + + void execute(ICDescriptor descriptor) throws CoreException; + +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICExtensionReference.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICExtensionReference.java index f940e4ebb5b..cd1b694aaba 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICExtensionReference.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICExtensionReference.java @@ -32,7 +32,7 @@ public interface ICExtensionReference { /** * Sets a name/value data pair on this reference in the .cdtproject file */ - public void setExtensionData(String key, String value); + public void setExtensionData(String key, String value) throws CoreException; /** * Gets a value of the key from the .cdtproject file set by diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties index cf8d084785e..06640ff4bb8 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties @@ -21,7 +21,8 @@ CCProjectNature.exception.noNature=Project must have a cnature CCorePlugin.exception.noBinaryFormat=No Binary Format CDescriptorManager.exception.alreadyConfigured=CDTProject already configured - +CDescriptorManager.exception.notAC/C++Project=Not a C/C++ Project +CDescriptorManager.exception.listenerError=An exception occurred during descriptor notification COwner.exception.invalidOwnerID=Invalid CDTProject owner ID COwner.exception.invalidOwnerExtension=Invalid CDTProject owner extension @@ -31,6 +32,7 @@ CDescriptor.exception.fileNotFound=CDTProject file not found CDescriptor.exception.missingOwnerId=Missing owner id CDescriptor.exception.missingElement=Missing cdtproject element CDescriptor.exception.providerNotFound=Extension provider not found. +CDescriptor.extension.internalError=Internal Error Util.exception.invalidArchive=Not a valid archive file. Util.exception.arrayToSmall=Array to small diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CDescriptor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CDescriptor.java index 56db99d8883..98698dc5150 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CDescriptor.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CDescriptor.java @@ -1,13 +1,12 @@ -/********************************************************************** - * Copyright (c) 2002,2003 QNX Software Systems Ltd. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html +/******************************************************************************* + * Copyright (c) 2002, 2003, 2004 QNX Software Systems Ltd. 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 -***********************************************************************/ + * Contributors: QNX Software Systems - Initial API and implementation + ******************************************************************************/ package org.eclipse.cdt.internal.core; import java.io.ByteArrayInputStream; @@ -15,7 +14,7 @@ import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStreamWriter; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; @@ -23,13 +22,15 @@ import java.util.Map.Entry; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; -import org.apache.xerces.dom.DocumentImpl; -import org.apache.xml.serialize.Method; -import org.apache.xml.serialize.OutputFormat; -import org.apache.xml.serialize.Serializer; -import org.apache.xml.serialize.SerializerFactory; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CDescriptorEvent; import org.eclipse.cdt.core.ICDescriptor; import org.eclipse.cdt.core.ICExtension; import org.eclipse.cdt.core.ICExtensionReference; @@ -51,29 +52,42 @@ import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.w3c.dom.ProcessingInstruction; public class CDescriptor implements ICDescriptor { + + final CDescriptorManager fManager; + private final IProject fProject; + private COwner fOwner; - private IProject fProject; + private HashMap extMap = new HashMap(4); private HashMap extInfoMap = new HashMap(4); private Document dataDoc; - static final String CEXTENSION_NAME = "cextension"; //$NON-NLS-1$ static final String DESCRIPTION_FILE_NAME = ".cdtproject"; //$NON-NLS-1$ - private static final char[][] NO_CHAR_CHAR = new char[0][]; + + private static final String CEXTENSION_NAME = "cextension"; //$NON-NLS-1$ + private static final String PROJECT_DESCRIPTION = "cdtproject"; //$NON-NLS-1$ + private static final String PROJECT_OWNER_ID = "id"; //$NON-NLS-1$ private static final String PROJECT_EXTENSION = "extension"; //$NON-NLS-1$ + private static final String PROJECT_EXTENSION_ATTR_POINT = "point"; //$NON-NLS-1$ + private static final String PROJECT_EXTENSION_ATTR_ID = "id"; //$NON-NLS-1$ private static final String PROJECT_EXTENSION_ATTRIBUTE = "attribute"; //$NON-NLS-1$ + private static final String PROJECT_EXTENSION_ATTRIBUTE_KEY = "key"; //$NON-NLS-1$ + private static final String PROJECT_EXTENSION_ATTRIBUTE_VALUE = "value"; //$NON-NLS-1$ + private static final String PROJECT_DATA = "data"; //$NON-NLS-1$ private static final String PROJECT_DATA_ITEM = "item"; //$NON-NLS-1$ private static final String PROJECT_DATA_ID = "id"; //$NON-NLS-1$ private boolean fDirty; - private boolean autoSave; + private boolean fAutoSave; - protected CDescriptor(IProject project, String id) throws CoreException { + protected CDescriptor(CDescriptorManager manager, IProject project, String id) throws CoreException { fProject = project; + fManager = manager; IPath projectLocation = project.getDescription().getLocation(); if (projectLocation == null) { @@ -83,32 +97,23 @@ public class CDescriptor implements ICDescriptor { if (descriptionPath.toFile().exists()) { IStatus status; - String ownerID = readCDTProject(descriptionPath); + String ownerID = readCDTProjectFile(descriptionPath); if (ownerID.equals(id)) { fOwner = new COwner(ownerID); - status = - new Status( - IStatus.WARNING, - CCorePlugin.PLUGIN_ID, - CCorePlugin.STATUS_CDTPROJECT_EXISTS, - CCorePlugin.getResourceString("CDescriptor.exception.projectAlreadyExists"), //$NON-NLS-1$ - (Throwable) null); + status = new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, CCorePlugin.STATUS_CDTPROJECT_EXISTS, + CCorePlugin.getResourceString("CDescriptor.exception.projectAlreadyExists"), (Throwable) null); //$NON-NLS-1$ } else { - status = - new Status( - IStatus.ERROR, - CCorePlugin.PLUGIN_ID, - CCorePlugin.STATUS_CDTPROJECT_MISMATCH, - CCorePlugin.getResourceString("CDescriptor.exception.unmatchedOwnerId"), //$NON-NLS-1$ - (Throwable) null); + status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, CCorePlugin.STATUS_CDTPROJECT_MISMATCH, + CCorePlugin.getResourceString("CDescriptor.exception.unmatchedOwnerId"), (Throwable) null); //$NON-NLS-1$ } throw new CoreException(status); } fOwner = new COwner(id); } - protected CDescriptor(IProject project) throws CoreException { + protected CDescriptor(CDescriptorManager manager, IProject project) throws CoreException { fProject = project; + fManager = manager; IPath projectLocation = project.getDescription().getLocation(); if (projectLocation == null) { @@ -117,14 +122,16 @@ public class CDescriptor implements ICDescriptor { IPath descriptionPath = projectLocation.append(DESCRIPTION_FILE_NAME); if (!descriptionPath.toFile().exists()) { - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("CDescriptor.exception.fileNotFound"), (Throwable) null); //$NON-NLS-1$ + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("CDescriptor.exception.fileNotFound"), (Throwable) null); //$NON-NLS-1$ throw new CoreException(status); } - fOwner = new COwner(readCDTProject(descriptionPath)); + fOwner = new COwner(readCDTProjectFile(descriptionPath)); } - protected CDescriptor(IProject project, COwner owner) throws CoreException { + protected CDescriptor(CDescriptorManager manager, IProject project, COwner owner) throws CoreException { fProject = project; + fManager = manager; IPath projectLocation = project.getDescription().getLocation(); if (projectLocation == null) { @@ -133,10 +140,11 @@ public class CDescriptor implements ICDescriptor { IPath descriptionPath = projectLocation.append(DESCRIPTION_FILE_NAME); if (!descriptionPath.toFile().exists()) { - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("CDescriptor.exception.fileNotFound"), (Throwable) null); //$NON-NLS-1$ + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("CDescriptor.exception.fileNotFound"), (Throwable) null); //$NON-NLS-1$ throw new CoreException(status); } - readCDTProject(descriptionPath); + readCDTProjectFile(descriptionPath); fOwner = owner; setDirty(); } @@ -145,26 +153,29 @@ public class CDescriptor implements ICDescriptor { return fOwner; } - private String readCDTProject(IPath descriptionPath) throws CoreException { + private String readCDTProjectFile(IPath descriptionPath) throws CoreException { FileInputStream file = null; try { file = new FileInputStream(descriptionPath.toFile()); DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = parser.parse(file); - Node node = document.getFirstChild(); - if (node.getNodeName().equals(PROJECT_DESCRIPTION)) { - String ownerID = node.getAttributes().getNamedItem("id").getNodeValue(); //$NON-NLS-1$ - if ( ownerID != null) { + NodeList nodeList = document.getElementsByTagName(PROJECT_DESCRIPTION); + if (nodeList != null && nodeList.getLength() > 0) { + Node node = nodeList.item(0); + String ownerID = node.getAttributes().getNamedItem(PROJECT_OWNER_ID).getNodeValue(); + if (ownerID != null) { readProjectDescription(node); return ownerID; } - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("CDescriptor.exception.missingOwnerId"), null); //$NON-NLS-1$ + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("CDescriptor.exception.missingOwnerId"), null); //$NON-NLS-1$ throw new CoreException(status); } - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("CDescriptor.exception.missingElement"), null); //$NON-NLS-1$ + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("CDescriptor.exception.missingElement"), null); //$NON-NLS-1$ throw new CoreException(status); } catch (Exception e) { - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, e.getLocalizedMessage(), e); + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, e.toString(), e); throw new CoreException(status); } finally { if (file != null) { @@ -192,19 +203,19 @@ public class CDescriptor implements ICDescriptor { return fProject; } - public ICExtensionReference[] get(String extensionID) { + synchronized public ICExtensionReference[] get(String extensionID) { CExtensionReference[] refs = (CExtensionReference[]) extMap.get(extensionID); if (refs == null) return new ICExtensionReference[0]; return refs; } - public ICExtensionReference[] get(String extensionID, boolean update) { + synchronized public ICExtensionReference[] get(String extensionID, boolean update) { ICExtensionReference[] ext = get(extensionID); if (ext.length == 0 && update) { try { fOwner.update(fProject, this, extensionID); - saveInfo(); + setDirty(); ext = get(extensionID); } catch (CoreException e) { } @@ -212,7 +223,7 @@ public class CDescriptor implements ICDescriptor { return ext; } - public ICExtensionReference create(String extensionPoint, String extensionID) throws CoreException { + synchronized public ICExtensionReference create(String extensionPoint, String extensionID) throws CoreException { CExtensionReference extensions[] = (CExtensionReference[]) extMap.get(extensionPoint); if (extensions == null) { extensions = new CExtensionReference[1]; @@ -225,36 +236,38 @@ public class CDescriptor implements ICDescriptor { } extensions[extensions.length - 1] = new CExtensionReference(this, extensionPoint, extensionID); setDirty(); + fManager.fireEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.EXTENSION_CHANGED)); return extensions[extensions.length - 1]; } - public void remove(ICExtensionReference ext) throws CoreException { + synchronized public void remove(ICExtensionReference ext) throws CoreException { CExtensionReference extensions[] = (CExtensionReference[]) extMap.get(ext.getExtension()); for (int i = 0; i < extensions.length; i++) { if (extensions[i] == ext) { System.arraycopy(extensions, i, extensions, i + 1, extensions.length - 1 - i); - CExtensionReference[] newExtensions = new CExtensionReference[extensions.length - 1]; - System.arraycopy(extensions, 0, newExtensions, 0, extensions.length); - extensions = newExtensions; - if (extensions.length == 0) { - extMap.put(ext.getExtension(), null); + if (extensions.length > 1) { + CExtensionReference[] newExtensions = new CExtensionReference[extensions.length - 1]; + System.arraycopy(extensions, 0, newExtensions, 0, newExtensions.length); + extMap.put(ext.getExtension(), newExtensions); } else { - extMap.put(ext.getExtension(), extensions); + extMap.remove(ext.getExtension()); } setDirty(); } } + fManager.fireEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.EXTENSION_CHANGED)); } - public void remove(String extensionPoint) throws CoreException { + synchronized public void remove(String extensionPoint) throws CoreException { CExtensionReference extensions[] = (CExtensionReference[]) extMap.get(extensionPoint); if (extensions != null) { extMap.remove(extensionPoint); setDirty(); } + fManager.fireEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.EXTENSION_CHANGED)); } - public CExtensionInfo getInfo(CExtensionReference cProjectExtension) { + synchronized CExtensionInfo getInfo(CExtensionReference cProjectExtension) { CExtensionInfo info = (CExtensionInfo) extInfoMap.get(cProjectExtension); if (info == null) { info = new CExtensionInfo(); @@ -263,7 +276,7 @@ public class CDescriptor implements ICDescriptor { return info; } - protected void saveInfo() throws CoreException { + synchronized protected void saveInfo() throws CoreException { String xml; if (!isDirty()) { return; @@ -273,9 +286,15 @@ public class CDescriptor implements ICDescriptor { } catch (IOException e) { IStatus s = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, e.getMessage(), e); throw new CoreException(s); + } catch (TransformerException e) { + IStatus s = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, e.getMessage(), e); + throw new CoreException(s); + } catch (ParserConfigurationException e) { + IStatus s = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, e.getMessage(), e); + throw new CoreException(s); } - IFile rscFile = getProject().getFile(DESCRIPTION_FILE_NAME); + IFile rscFile = getFile(); InputStream inputStream = new ByteArrayInputStream(xml.getBytes()); // update the resource content if (rscFile.exists()) { @@ -286,33 +305,103 @@ public class CDescriptor implements ICDescriptor { fDirty = false; } + protected IFile getFile() { + return getProject().getFile(DESCRIPTION_FILE_NAME); + } + public boolean isAutoSave() { - return autoSave; + return fAutoSave; } public void setAutoSave(boolean autoSave) { - this.autoSave = autoSave; + fAutoSave = autoSave; } protected void setDirty() throws CoreException { fDirty = true; if (isAutoSave()) - saveInfo(); + fManager.updateDescriptor(this); } protected boolean isDirty() { return fDirty; } - protected String serializeDocument(Document doc) throws IOException { + protected String serializeDocument(Document doc) throws IOException, TransformerException { ByteArrayOutputStream s = new ByteArrayOutputStream(); - OutputFormat format = new OutputFormat(); - format.setIndenting(true); - format.setLineSeparator(System.getProperty("line.separator")); //$NON-NLS-1$ - Serializer serializer = - SerializerFactory.getSerializerFactory(Method.XML).makeSerializer(new OutputStreamWriter(s, "UTF8"), format); //$NON-NLS-1$ - serializer.asDOMSerializer().serialize(doc); - return s.toString("UTF8"); //$NON-NLS-1$ + + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer transformer = factory.newTransformer(); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ + + DOMSource source = new DOMSource(doc); + StreamResult outputTarget = new StreamResult(s); + transformer.transform(source, outputTarget); + + return s.toString("UTF8"); //$NON-NLS-1$ + } + + void updateFromDisk() throws CoreException { + synchronized (this) { + IPath projectLocation = fProject.getDescription().getLocation(); + + if (projectLocation == null) { + projectLocation = getProjectDefaultLocation(fProject); + } + IPath descriptionPath = projectLocation.append(DESCRIPTION_FILE_NAME); + if (!descriptionPath.toFile().exists()) { + setDirty(); + return; + } + COwner origOwner = fOwner; + HashMap origExtMap = extMap; + HashMap origExtInfoMap = extInfoMap; + Document origDataDoc = dataDoc; + + extMap = new HashMap(4); + extInfoMap = new HashMap(4); + dataDoc = null; + + try { + fOwner = new COwner(readCDTProjectFile(descriptionPath)); + } catch (CoreException e) { + CCorePlugin.log(e); + fOwner = origOwner; + extMap = origExtMap; + extInfoMap = origExtInfoMap; + dataDoc = origDataDoc; + } + setDirty(); + if (!fOwner.equals(origOwner)) { + fManager.fireEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.OWNER_CHANGED)); + } else { + boolean extChanges = true; + if (extMap.size() == origExtMap.size() && extInfoMap.size() == origExtInfoMap.size()) { + extChanges = false; + Iterator entries = extMap.entrySet().iterator(); + while (entries.hasNext()) { + Entry entry = (Entry) entries.next(); + if (!origExtMap.containsKey(entry.getKey())) { + extChanges = true; + break; + } + CExtensionReference origExt[] = (CExtensionReference[]) origExtMap.get(entry.getKey()); + CExtensionReference newExt[] = (CExtensionReference[]) entry.getValue(); + if (!Arrays.equals(origExt, newExt)) { + extChanges = true; + break; + } + } + } + if (extChanges) { + fManager.fireEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, + CDescriptorEvent.EXTENSION_CHANGED)); + } else { + fManager.fireEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, 0)); + } + } + } } private void readProjectDescription(Node node) { @@ -329,7 +418,7 @@ public class CDescriptor implements ICDescriptor { } } else if (childNode.getNodeName().equals(PROJECT_DATA)) { try { - decodeProjectData((Element)childNode); + decodeProjectData((Element) childNode); } catch (CoreException e) { CCorePlugin.log(e); } @@ -339,22 +428,28 @@ public class CDescriptor implements ICDescriptor { } private void decodeProjectExtension(Element element) throws CoreException { - ICExtensionReference ext = create(element.getAttribute("point"), element.getAttribute("id")); //$NON-NLS-1$ //$NON-NLS-2$ + String point = element.getAttribute(PROJECT_EXTENSION_ATTR_POINT); + String id = element.getAttribute(PROJECT_EXTENSION_ATTR_ID); + ICExtensionReference ext = create(point, id); NodeList extAttrib = element.getChildNodes(); for (int j = 0; j < extAttrib.getLength(); j++) { if (extAttrib.item(j).getNodeName().equals(PROJECT_EXTENSION_ATTRIBUTE)) { NamedNodeMap attrib = extAttrib.item(j).getAttributes(); - ext.setExtensionData(attrib.getNamedItem("key").getNodeValue(), attrib.getNamedItem("value").getNodeValue()); //$NON-NLS-1$ //$NON-NLS-2$ + ext.setExtensionData(attrib.getNamedItem(PROJECT_EXTENSION_ATTRIBUTE_KEY).getNodeValue(), attrib.getNamedItem( + PROJECT_EXTENSION_ATTRIBUTE_VALUE).getNodeValue()); //$NON-NLS-1$ //$NON-NLS-2$ } } } - - protected String getAsXML() throws IOException { - Document doc = new DocumentImpl(); + protected String getAsXML() throws IOException, TransformerException, ParserConfigurationException { + DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); + Document doc = docBuilder.newDocument(); + ProcessingInstruction version = doc.createProcessingInstruction("eclipse-cdt", "version=\"2.0\""); //$NON-NLS-1$ //$NON-NLS-2$ + doc.appendChild(version); Element configRootElement = doc.createElement(PROJECT_DESCRIPTION); doc.appendChild(configRootElement); - configRootElement.setAttribute("id", fOwner.getID()); //$NON-NLS-1$ + configRootElement.setAttribute(PROJECT_OWNER_ID, fOwner.getID()); encodeProjectExtensions(doc, configRootElement); encodeProjectData(doc, configRootElement); return serializeDocument(doc); @@ -367,16 +462,16 @@ public class CDescriptor implements ICDescriptor { CExtensionReference extension[] = (CExtensionReference[]) extIterator.next(); for (int i = 0; i < extension.length; i++) { configRootElement.appendChild(element = doc.createElement(PROJECT_EXTENSION)); - element.setAttribute("point", extension[i].getExtension()); //$NON-NLS-1$ - element.setAttribute("id", extension[i].getID()); //$NON-NLS-1$ + element.setAttribute(PROJECT_EXTENSION_ATTR_POINT, extension[i].getExtension()); + element.setAttribute(PROJECT_EXTENSION_ATTR_ID, extension[i].getID()); CExtensionInfo info = (CExtensionInfo) extInfoMap.get(extension[i]); if (info != null) { Iterator attribIterator = info.getAttributes().entrySet().iterator(); while (attribIterator.hasNext()) { Entry entry = (Entry) attribIterator.next(); Element extAttributes = doc.createElement(PROJECT_EXTENSION_ATTRIBUTE); - extAttributes.setAttribute("key", (String) entry.getKey()); //$NON-NLS-1$ - extAttributes.setAttribute("value", (String) entry.getValue()); //$NON-NLS-1$ + extAttributes.setAttribute(PROJECT_EXTENSION_ATTRIBUTE_KEY, (String) entry.getKey()); + extAttributes.setAttribute(PROJECT_EXTENSION_ATTRIBUTE_VALUE, (String) entry.getValue()); element.appendChild(extAttributes); } } @@ -384,18 +479,18 @@ public class CDescriptor implements ICDescriptor { } } - protected ICExtension createExtensions(ICExtensionReference ext) throws CoreException { InternalCExtension cExtension = null; IPluginRegistry pluginRegistry = Platform.getPluginRegistry(); IExtensionPoint extensionPoint = pluginRegistry.getExtensionPoint(ext.getExtension()); IExtension extension = extensionPoint.getExtension(ext.getID()); - if ( extension == null) { - throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("CDescriptor.exception.providerNotFound"), null)); //$NON-NLS-1$ + if (extension == null) { + throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("CDescriptor.exception.providerNotFound"), null)); //$NON-NLS-1$ } IConfigurationElement element[] = extension.getConfigurationElements(); for (int i = 0; i < element.length; i++) { - if (element[i].getName().equalsIgnoreCase(CEXTENSION_NAME)) { + if (element[i].getName().equalsIgnoreCase("cextension")) { //$NON-NLS-1$ cExtension = (InternalCExtension) element[i].createExecutableExtension("run"); //$NON-NLS-1$ cExtension.setExtenionReference(ext); cExtension.setProject(fProject); @@ -404,44 +499,40 @@ public class CDescriptor implements ICDescriptor { } return (ICExtension) cExtension; } - + protected IConfigurationElement[] getConfigurationElement(ICExtensionReference ext) throws CoreException { IPluginRegistry pluginRegistry = Platform.getPluginRegistry(); IExtensionPoint extensionPoint = pluginRegistry.getExtensionPoint(ext.getExtension()); IExtension extension = extensionPoint.getExtension(ext.getID()); - if ( extension == null) { - throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("CDescriptor.exception.providerNotFound"), null)); //$NON-NLS-1$ + if (extension == null) { + throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("CDescriptor.exception.providerNotFound"), null)); //$NON-NLS-1$ } IConfigurationElement element[] = extension.getConfigurationElements(); for (int i = 0; i < element.length; i++) { if (element[i].getName().equalsIgnoreCase(CEXTENSION_NAME)) { - return element[i].getChildren(); + return element[i].getChildren(); } } return new IConfigurationElement[0]; } - + // The project data allows for the storage of any structured information // into the cdtproject file. - private Document getProjectDataDoc() throws CoreException { + synchronized private Document getProjectDataDoc() throws CoreException { if (dataDoc == null) { try { dataDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); } catch (ParserConfigurationException e) { - throw new CoreException( - new Status( - IStatus.ERROR, - CCorePlugin.PLUGIN_ID, - IStatus.ERROR, - "getProjectDataDoc", //$NON-NLS-1$ - e)); + throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, IStatus.ERROR, + CCorePlugin.getResourceString("CDescriptor.extension.internalError"), e)); //$NON-NLS-1$ } Element rootElem = dataDoc.createElement(PROJECT_DATA); dataDoc.appendChild(rootElem); } return dataDoc; } - + private void decodeProjectData(Element data) throws CoreException { Document doc = getProjectDataDoc(); doc.replaceChild(doc.importNode(data, true), doc.getDocumentElement()); @@ -450,9 +541,9 @@ public class CDescriptor implements ICDescriptor { public Element getProjectData(String id) throws CoreException { NodeList nodes = getProjectDataDoc().getDocumentElement().getElementsByTagName(PROJECT_DATA_ITEM); for (int i = 0; i < nodes.getLength(); ++i) { - Element element = (Element)nodes.item(i); + Element element = (Element) nodes.item(i); if (element.getAttribute(PROJECT_DATA_ID).equals(id)) - return element; + return element; } // Not found, make a new one @@ -461,14 +552,25 @@ public class CDescriptor implements ICDescriptor { dataDoc.getDocumentElement().appendChild(element); return element; } - + public void saveProjectData() throws CoreException { setDirty(); + fManager.fireEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, 0)); } - + private void encodeProjectData(Document doc, Element root) { // Don't create or encode the doc if it isn't there already - if (dataDoc != null) + if (dataDoc != null) { + Element dataElements = dataDoc.getDocumentElement(); + NodeList nodes = dataElements.getElementsByTagName(PROJECT_DATA_ITEM); + for (int i = 0; i < nodes.getLength(); ++i) { + Element item = (Element) nodes.item(i); + if (!item.hasChildNodes()) { // remove any empty item tags + dataElements.removeChild(item); + i--; //nodeList is live.... removeal changes nodelist + } + } root.appendChild(doc.importNode(dataDoc.getDocumentElement(), true)); + } } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CDescriptorManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CDescriptorManager.java index d1ffafcd83b..08ffe22994d 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CDescriptorManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CDescriptorManager.java @@ -1,33 +1,48 @@ -/********************************************************************** - * Copyright (c) 2002,2003 QNX Software Systems Ltd. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html +/******************************************************************************* + * Copyright (c) 2002, 2003, 2004 QNX Software Systems Ltd. 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 -***********************************************************************/ + * Contributors: QNX Software Systems - Initial API and implementation + ******************************************************************************/ package org.eclipse.cdt.internal.core; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Vector; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CDescriptorEvent; +import org.eclipse.cdt.core.CProjectNature; import org.eclipse.cdt.core.ICDescriptor; -import org.eclipse.core.resources.IFile; +import org.eclipse.cdt.core.ICDescriptorListener; +import org.eclipse.cdt.core.ICDescriptorManager; +import org.eclipse.cdt.core.ICDescriptorOperation; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; -public class CDescriptorManager implements IResourceChangeListener { - private static HashMap fDescriptorMap; +public class CDescriptorManager implements ICDescriptorManager, IResourceChangeListener { + + HashMap fOperationMap = new HashMap(); + HashMap fDescriptorMap = new HashMap(); + List listeners = new Vector(); private IWorkspace getWorkspace() { return ResourcesPlugin.getWorkspace(); @@ -37,110 +52,249 @@ public class CDescriptorManager implements IResourceChangeListener { getWorkspace().removeResourceChangeListener(this); } - public void startup() { - getWorkspace().addResourceChangeListener(this); + public void startup() throws CoreException { + getWorkspace().getRoot().accept(new IResourceVisitor() { + + public boolean visit(IResource resource) { + if (resource.getType() == IResource.PROJECT) { + IProject project = (IProject) resource; + try { + if (project.hasNature(CProjectNature.C_NATURE_ID)) { + if (project.isOpen()) { + getDescriptor(project); + } + } + } catch (CoreException e) { + CCorePlugin.log(e); + } + return false; + } + return resource.getType() == IResource.ROOT; + } + }); + getWorkspace().addResourceChangeListener(this, + IResourceChangeEvent.PRE_AUTO_BUILD | IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.PRE_CLOSE); } /** - * Traverses the delta looking for added/removed/changed launch - * configuration files. + * Watch for changes/deletions of the .cdtproject file. * * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent) */ public void resourceChanged(IResourceChangeEvent event) { - if ( fDescriptorMap == null ) { - return; - } - IResource resource = event.getResource(); - - int eventType = event.getType(); - - switch(eventType) { - case IResourceChangeEvent.PRE_DELETE: - if (resource.getType() == IResource.PROJECT){ - fDescriptorMap.remove(resource); - } - break; - case IResourceChangeEvent.POST_CHANGE: - IResourceDelta delta= event.getDelta(); - if (delta == null) { - break; - } - IResource dResource = delta.getResource(); - //if (0 != (delta.getFlags() & IResourceDelta.OPEN)) { - if (dResource instanceof IFile) { - IFile file = (IFile)dResource; + if (event.getSource() instanceof IWorkspace) { + IResource resource = event.getResource(); - // the .cdtproject file has been deleted - if ((file != null) && (file.getName().endsWith(CDescriptor.DESCRIPTION_FILE_NAME)) && !file.exists()){ - // must remove the corresponding reference to it in the fDescriptorMap - if (fDescriptorMap != null){ - fDescriptorMap.remove(resource); + switch (event.getType()) { + case IResourceChangeEvent.PRE_DELETE: + case IResourceChangeEvent.PRE_CLOSE: + try { + if (resource.getType() == IResource.PROJECT && ((IProject) resource).hasNature(CProjectNature.C_NATURE_ID)) { + CDescriptor descriptor = (CDescriptor) fDescriptorMap.remove(resource); + if (descriptor != null) { + fireEvent(new CDescriptorEvent(descriptor, CDescriptorEvent.CDTPROJECT_REMOVED, 0)); } } - + } catch (CoreException e) { + CCorePlugin.log(e); } - //} - break; - } + break; + case IResourceChangeEvent.PRE_AUTO_BUILD: + IResourceDelta resDelta = event.getDelta(); + if (resDelta == null) { + break; + } + try { + resDelta.accept(new IResourceDeltaVisitor() { + + public boolean visit(IResourceDelta delta) throws CoreException { + IResource dResource = delta.getResource(); + if (dResource.getType() == IResource.PROJECT) { + if (0 != (delta.getFlags() & IResourceDelta.OPEN)) { + IProject project = (IProject) dResource; + if (project.hasNature(CProjectNature.C_NATURE_ID)) { + if (project.isOpen()) { + getDescriptor(project); + } else { + CDescriptor descriptor = (CDescriptor) fDescriptorMap.remove(project); + if (descriptor != null) { + fireEvent(new CDescriptorEvent(descriptor, CDescriptorEvent.CDTPROJECT_REMOVED, + 0)); + } + } + } + return false; + } + return true; + } else if (dResource.getType() == IResource.FILE) { + if (dResource.getName().equals(CDescriptor.DESCRIPTION_FILE_NAME)) { + CDescriptor descriptor = (CDescriptor) fDescriptorMap.get(dResource.getProject()); + if (descriptor != null) { + if ((delta.getKind() & IResourceDelta.REMOVED) != 0) { + // the file got deleted lets + // try + // and restore for memory. + updateDescriptor(descriptor); + } else if ((delta.getFlags() & IResourceDelta.CONTENT) != 0) { + // content change lets try to + // read and update + descriptor.updateFromDisk(); + } + } + return false; + } + return true; + } + return dResource.getType() == IResource.ROOT; + } + }); + } catch (CoreException e) { + CCorePlugin.log(e); + } + break; + } + } } - public synchronized ICDescriptor getDescriptor(IProject project) throws CoreException { - if ( fDescriptorMap == null ) { - fDescriptorMap = new HashMap(); + CDescriptor descriptor = (CDescriptor) fDescriptorMap.get(project); + if (descriptor == null) { + descriptor = new CDescriptor(this, project); + descriptor.setAutoSave(true); + fDescriptorMap.put(project, descriptor); } - CDescriptor cproject; - cproject = (CDescriptor)fDescriptorMap.get(project) ; - if ( cproject == null ) { - cproject = new CDescriptor(project); - cproject.setAutoSave(true); - fDescriptorMap.put(project, cproject); - } - return cproject; + return descriptor; } - public synchronized void configure(IProject project, String id) throws CoreException { - CDescriptor cproject; - if ( fDescriptorMap == null ) { - fDescriptorMap = new HashMap(); + public void configure(IProject project, String id) throws CoreException { + CDescriptor descriptor; + synchronized (this) { + descriptor = (CDescriptor) fDescriptorMap.get(project); + if (descriptor != null) { + if (!descriptor.getOwner().getID().equals(id)) { + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, CCorePlugin.STATUS_CDTPROJECT_EXISTS, + CCorePlugin.getResourceString("CDescriptorManager.exception.alreadyConfigured"), //$NON-NLS-1$ + (Throwable) null); + throw new CoreException(status); + } + return; + } + try { + descriptor = new CDescriptor(this, project, id); + descriptor.getOwner().configure(project, descriptor); + } catch (CoreException e) { // if .cdtproject already exists will + // use that + IStatus status = e.getStatus(); + if (status.getCode() == CCorePlugin.STATUS_CDTPROJECT_EXISTS) { + descriptor = new CDescriptor(this, project); + } else + throw e; + } + fDescriptorMap.put(project, descriptor); } - cproject = (CDescriptor) fDescriptorMap.get(project); - if ( cproject != null ) { - if ( !cproject.getProjectOwner().getID().equals(id) ) { - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, CCorePlugin.STATUS_CDTPROJECT_EXISTS, CCorePlugin.getResourceString("CDescriptorManager.exception.alreadyConfigured"), (Throwable)null); //$NON-NLS-1$ - throw new CoreException(status); + fireEvent(new CDescriptorEvent(descriptor, CDescriptorEvent.CDTPROJECT_ADDED, 0)); + descriptor.setAutoSave(true); + updateDescriptor(descriptor); + } + + public void convert(IProject project, String id) throws CoreException { + CDescriptor descriptor; + synchronized (this) { + descriptor = new CDescriptor(this, project, new COwner(id)); + fDescriptorMap.put(project, descriptor); + descriptor.getOwner().configure(project, descriptor); + } + fireEvent(new CDescriptorEvent(descriptor, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.OWNER_CHANGED)); + descriptor.setAutoSave(true); + updateDescriptor(descriptor); + } + + public void addDescriptorListener(ICDescriptorListener listener) { + listeners.add(listener); + } + + public void removeDescriptorListener(ICDescriptorListener listener) { + listeners.remove(listener); + } + + protected void fireEvent(final CDescriptorEvent event) { + if (fOperationMap.containsKey(event.getDescriptor())) { + // lets just hold on to the important event in order of; + // ADD/REMOVE shouldn' every receive the remove but.... + // OWNER_CHANGED + // EXT_CHANGED + // other + if (event.getType() != CDescriptorEvent.CDTPROJECT_ADDED) { + fOperationMap.put(event.getDescriptor(), event); + } else if (event.getType() == CDescriptorEvent.CDTPROJECT_REMOVED) { + fOperationMap.put(event.getDescriptor(), event); + } else { + CDescriptorEvent ev = (CDescriptorEvent) fOperationMap.get(event.getDescriptor()); + if (ev.getType() == CDescriptorEvent.CDTPROJECT_CHANGED) { + if (ev.getFlags() == 0) { + fOperationMap.put(event.getDescriptor(), event); + } else if (ev.getFlags() != CDescriptorEvent.OWNER_CHANGED) { + fOperationMap.put(event.getDescriptor(), event); + } + } } return; } - try { - cproject = new CDescriptor(project, id); + final Iterator iterator = listeners.iterator(); + while (iterator.hasNext()) { + Platform.run(new ISafeRunnable() { + + public void handleException(Throwable exception) { + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("CDescriptorManager.exception.listenerError"), exception); //$NON-NLS-1$ + CCorePlugin.log(status); + } + + public void run() throws Exception { + ((ICDescriptorListener) iterator.next()).descriptorChanged(event); + } + }); } - catch (CoreException e) { // if .cdtproject already exists will use that - IStatus status = e.getStatus(); - if ( status.getCode() == CCorePlugin.STATUS_CDTPROJECT_EXISTS ) { - cproject = new CDescriptor(project); - fDescriptorMap.put(project, cproject); - return; - } - else - throw e; - } - cproject.getOwner().configure(project, cproject); - cproject.saveInfo(); - cproject.setAutoSave(true); - fDescriptorMap.put(project, cproject); } - - public synchronized void convert(IProject project, String id) throws CoreException { - CDescriptor cproject; - if ( fDescriptorMap == null ) { - fDescriptorMap = new HashMap(); + + public void runDescriptorOperation(ICDescriptor descriptor, ICDescriptorOperation op) throws CoreException { + synchronized (descriptor) { + beginOperation(descriptor); + try { + op.execute(descriptor); + } finally { + endOperation(descriptor); + } } - cproject = new CDescriptor(project, new COwner(id)); - cproject.getOwner().configure(project, cproject); - cproject.saveInfo(); - cproject.setAutoSave(true); - fDescriptorMap.put(project, cproject); + } + + private void beginOperation(ICDescriptor descriptor) { + fOperationMap.put(descriptor, null); + } + + private void endOperation(ICDescriptor descriptor) { + CDescriptorEvent event = (CDescriptorEvent) fOperationMap.remove(descriptor); + if (event != null) { + fireEvent(event); + } + } + + /* + * Perform a update of the ondisk .cdtproject file. This is nessecary to + * avoid deadlocking when the descriptor has change from a call to + * ICDescriptor.get(project, true) which may update the descriptor via the + * owner update method, while the workspace is locked (ie during a + * resourceChange event). + */ + protected void updateDescriptor(final CDescriptor descriptor) throws CoreException { + if (fOperationMap.containsKey(descriptor)) { + return; + } + getWorkspace().run(new IWorkspaceRunnable() { + + public void run(IProgressMonitor monitor) throws CoreException { + descriptor.saveInfo(); + } + }, descriptor.getProject(), IWorkspace.AVOID_UPDATE, null); } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CExtensionReference.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CExtensionReference.java index 6f62c895d24..d05ac60e67d 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CExtensionReference.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CExtensionReference.java @@ -1,33 +1,33 @@ -/********************************************************************** - * Copyright (c) 2002,2003 QNX Software Systems Ltd. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html +/******************************************************************************* + * Copyright (c) 2002,2003 QNX Software Systems Ltd. and others. All rights + * reserved. This program and the accompanying materials are made available + * under the terms of the Common Public License v0.5 which accompanies this + * distribution, and is available at http://www.eclipse.org/legal/cpl-v05.html * - * Contributors: - * QNX Software Systems - Initial API and implementation -***********************************************************************/ + * Contributors: QNX Software Systems - Initial API and implementation + ******************************************************************************/ package org.eclipse.cdt.internal.core; +import org.eclipse.cdt.core.CDescriptorEvent; import org.eclipse.cdt.core.ICExtension; import org.eclipse.cdt.core.ICExtensionReference; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; public class CExtensionReference implements ICExtensionReference { + private CDescriptor fDescriptor; - private String fName; + private String fExtPoint; private String fId; - - public CExtensionReference(CDescriptor descriptor, String name, String id) { + + public CExtensionReference(CDescriptor descriptor, String extPoint, String id) { fDescriptor = descriptor; - fName = name; + fExtPoint = extPoint; fId = id; } public String getExtension() { - return fName; + return fExtPoint; } public String getID() { @@ -38,19 +38,35 @@ public class CExtensionReference implements ICExtensionReference { return fDescriptor.getInfo(this); } - public void setExtensionData(String key, String value) { + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof CExtensionReference) { + CExtensionReference ext = (CExtensionReference) obj; + if (ext.fExtPoint.equals(fExtPoint) && ext.fId.equals(fId)) { + return true; + } + } + return false; + } + + public void setExtensionData(String key, String value) throws CoreException { getInfo().setAttribute(key, value); + fDescriptor.setDirty(); + fDescriptor.fManager.fireEvent(new CDescriptorEvent(fDescriptor, CDescriptorEvent.CDTPROJECT_CHANGED, 0)); + } public String getExtensionData(String key) { return getInfo().getAttribute(key); } - + public ICExtension createExtension() throws CoreException { return fDescriptor.createExtensions(this); } - public IConfigurationElement[] getExtensionElements() throws CoreException { + public IConfigurationElement[] getExtensionElements() throws CoreException { return fDescriptor.getConfigurationElement(this); - } + } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/COwner.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/COwner.java index 35219ba0b04..767f8fb2217 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/COwner.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/COwner.java @@ -1,13 +1,12 @@ -/********************************************************************** - * Copyright (c) 2002,2003 QNX Software Systems Ltd. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html +/******************************************************************************* + * Copyright (c) 2002, 2003, 2004 QNX Software Systems Ltd. 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 -***********************************************************************/ + * Contributors: QNX Software Systems - Initial API and implementation + ******************************************************************************/ package org.eclipse.cdt.internal.core; import org.eclipse.cdt.core.CCorePlugin; @@ -23,34 +22,30 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; public class COwner implements ICOwnerInfo { + String ownerID; String fPlatform; IExtension extension; - + public COwner(String id) throws CoreException { ownerID = id; IExtensionPoint extpoint = CCorePlugin.getDefault().getDescriptor().getExtensionPoint("CProject"); //$NON-NLS-1$ - extension = extpoint.getExtension(ownerID); - - if (extension == null) { - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("COwner.exception.invalidOwnerID"), (Throwable)null); //$NON-NLS-1$ - throw new CoreException(status); - } + extension = extpoint.getExtension(ownerID); } public String getID() { return ownerID; } - + public String getName() { - return extension == null ? null : extension.getLabel(); + return extension == null ? "Unknown" : extension.getLabel(); //$NON-NLS-1$ } public String getPlatform() { - if ( fPlatform == null ) { + if (fPlatform == null && extension != null) { IConfigurationElement element[] = extension.getConfigurationElements(); - for( int i = 0; i < element.length; i++ ) { - if ( element[i].getName().equalsIgnoreCase("cproject") ) { //$NON-NLS-1$ + for (int i = 0; i < element.length; i++) { + if (element[i].getName().equalsIgnoreCase("cproject")) { //$NON-NLS-1$ fPlatform = element[i].getAttribute("platform"); //$NON-NLS-1$ break; } @@ -58,31 +53,51 @@ public class COwner implements ICOwnerInfo { } return fPlatform == null ? "*" : fPlatform; //$NON-NLS-1$ } - + void configure(IProject project, ICDescriptor cproject) throws CoreException { + if (extension == null) { + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("COwner.exception.invalidOwnerID"), (Throwable) null); //$NON-NLS-1$ + throw new CoreException(status); + } IConfigurationElement element[] = extension.getConfigurationElements(); - for( int i = 0; i < element.length; i++ ) { - if ( element[i].getName().equalsIgnoreCase("cproject") ) { //$NON-NLS-1$ + for (int i = 0; i < element.length; i++) { + if (element[i].getName().equalsIgnoreCase("cproject")) { //$NON-NLS-1$ ICOwner owner = (ICOwner) element[i].createExecutableExtension("class"); //$NON-NLS-1$ owner.configure(cproject); return; } } - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("COwner.exception.invalidOwnerExtension"), (Throwable)null); //$NON-NLS-1$ + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("COwner.exception.invalidOwnerExtension"), //$NON-NLS-1$ + (Throwable) null); throw new CoreException(status); } void update(IProject project, ICDescriptor cproject, String extensionID) throws CoreException { - IConfigurationElement element[] = extension.getConfigurationElements(); - for( int i = 0; i < element.length; i++ ) { - if ( element[i].getName().equalsIgnoreCase("cproject") ) { //$NON-NLS-1$ - ICOwner owner = (ICOwner) element[i].createExecutableExtension("class"); //$NON-NLS-1$ - owner.update(cproject, extensionID); - return; + if (extension != null) { + IConfigurationElement element[] = extension.getConfigurationElements(); + for (int i = 0; i < element.length; i++) { + if (element[i].getName().equalsIgnoreCase("cproject")) { //$NON-NLS-1$ + ICOwner owner = (ICOwner) element[i].createExecutableExtension("class"); //$NON-NLS-1$ + owner.update(cproject, extensionID); + return; + } } + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("COwner.exception.invalidOwnerExtension"), //$NON-NLS-1$ + (Throwable) null); + throw new CoreException(status); } - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("COwner.exception.invalidOwnerExtension"), (Throwable)null); //$NON-NLS-1$ - throw new CoreException(status); } + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if ( obj instanceof COwner) { + return ((COwner)obj).ownerID.equals(ownerID); + } + return false; + } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/InternalCExtension.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/InternalCExtension.java index 183a3baa4cb..7d953a8a807 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/InternalCExtension.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/InternalCExtension.java @@ -1,13 +1,12 @@ -/********************************************************************** - * Copyright (c) 2002,2003 QNX Software Systems Ltd. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html +/******************************************************************************* + * Copyright (c) 2002, 2003, 2004 QNX Software Systems Ltd. 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 -***********************************************************************/ + * Contributors: QNX Software Systems - Initial API and implementation + ******************************************************************************/ package org.eclipse.cdt.internal.core; import org.eclipse.cdt.core.ICExtensionReference; @@ -16,11 +15,11 @@ import org.eclipse.core.runtime.PlatformObject; public abstract class InternalCExtension extends PlatformObject { - private IProject project; + private IProject fProject; private ICExtensionReference extensionRef; void setProject(IProject project) { - this.project = project; + fProject = project; } void setExtenionReference(ICExtensionReference extReference) { @@ -28,7 +27,7 @@ public abstract class InternalCExtension extends PlatformObject { } protected IProject getProject() { - return project; + return fProject; } protected ICExtensionReference getExtensionReference() {