1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 09:25:31 +02:00

RESOLVED - bug 252966: ProjectDescription Storage: It should be possible to extend / override persistence mechanism

https://bugs.eclipse.org/bugs/show_bug.cgi?id=252966
This commit is contained in:
Chris Recoskie 2009-01-21 15:51:07 +00:00
parent a091e59733
commit 38fb615b8d
81 changed files with 6753 additions and 3732 deletions

View file

@ -0,0 +1,83 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.make.scannerdiscovery;
import java.io.ByteArrayInputStream;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.make.core.MakeCorePlugin;
import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2;
import org.eclipse.cdt.make.core.tests.StandardBuildTestHelper;
import org.eclipse.cdt.make.internal.core.scannerconfig2.ScannerConfigProfileManager;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
* This class tests ScannerConfigProfileManager
*/
public class ScannerConfigProfileTests extends BaseTestCase {
private IProject fCProject = null;
private IFile fCFile = null;
protected void setUp() throws Exception {
fCProject = StandardBuildTestHelper.createProject("SCD", (IPath)null, MakeCorePlugin.MAKE_PROJECT_ID);
fCFile = fCProject.getProject().getFile("main.c");
if (!fCFile.exists()) {
fCFile.create(new ByteArrayInputStream(" \n".getBytes()), false, new NullProgressMonitor());
}
}
protected void tearDown() throws Exception {
StandardBuildTestHelper.removeProject("SCDC");
}
/**
* Test Basic get of scanner config profile for a project
*/
public void testBasicScannerConfigProfile() throws CoreException {
// Add a scanner config profile to the project
IScannerConfigBuilderInfo2 scProjInfo = ScannerConfigProfileManager.createScannerConfigBuildInfo2(fCProject, ScannerConfigProfileManager.DEFAULT_SI_PROFILE_ID);
// Save
scProjInfo.save();
// Get all the settings and invert them
boolean autoDiscovery = scProjInfo.isAutoDiscoveryEnabled();
scProjInfo.setAutoDiscoveryEnabled(!autoDiscovery);
boolean problemReport = scProjInfo.isProblemReportingEnabled();
scProjInfo.setProblemReportingEnabled(!problemReport);
boolean buildOutputParser = scProjInfo.isBuildOutputParserEnabled();
scProjInfo.setBuildOutputParserEnabled(!buildOutputParser);
boolean buildOutputFileAction = scProjInfo.isBuildOutputFileActionEnabled();
scProjInfo.setBuildOutputFileActionEnabled(!buildOutputFileAction);
String buildOutputFilePath = "dummyFile";
scProjInfo.setBuildOutputFilePath(buildOutputFilePath);
// Save
scProjInfo.save();
fCProject.close(new NullProgressMonitor());
fCProject.open(new NullProgressMonitor());
scProjInfo = ScannerConfigProfileManager.createScannerConfigBuildInfo2(fCProject, ScannerConfigProfileManager.DEFAULT_SI_PROFILE_ID);
// Check that the previously set items have persisted...
Assert.isTrue(autoDiscovery != scProjInfo.isAutoDiscoveryEnabled());
Assert.isTrue(problemReport != scProjInfo.isProblemReportingEnabled());
Assert.isTrue(buildOutputParser != scProjInfo.isBuildOutputParserEnabled());
Assert.isTrue(buildOutputFileAction != scProjInfo.isBuildOutputFileActionEnabled());
Assert.isTrue(buildOutputFilePath.equals(scProjInfo.getBuildOutputFilePath()));
}
}

View file

@ -24,5 +24,6 @@ public class ScannerDiscoveryTests extends TestSuite {
addTestSuite(ScannerConfigDiscoveryTests.class);
addTest(GCCScannerInfoConsoleParserTests.suite());
addTest(GCCPerFileBOPConsoleParserTests.suite());
addTestSuite(ScannerConfigProfileTests.class);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 QNX Software Systems and others.
* Copyright (c) 2000, 2008 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.make.core;
@ -26,6 +27,7 @@ import org.eclipse.cdt.core.model.IMacroEntry;
import org.eclipse.cdt.core.model.IPathEntry;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.resources.ScannerProvider;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
@ -111,20 +113,20 @@ public class MakeScannerProvider extends ScannerProvider {
* Loads the build file and parses the nodes for build information. The information is then associated with the resource for the
* duration of the session.
*/
private MakeScannerInfo loadScannerInfo(IProject project) throws CoreException {
private MakeScannerInfo loadScannerInfo(IProject project) throws CoreException {
ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(project);
Node child = descriptor.getProjectData(CDESCRIPTOR_ID).getFirstChild();
ICStorageElement storage = descriptor.getProjectStorageElement(CDESCRIPTOR_ID);
ArrayList includes = new ArrayList();
ArrayList symbols = new ArrayList();
while (child != null) {
if (child.getNodeName().equals(INCLUDE_PATH)) {
for (ICStorageElement child : storage.getChildren()) {
if (child.getName().equals(INCLUDE_PATH)) {
// Add the path to the property list
includes.add( ((Element)child).getAttribute(PATH));
} else if (child.getNodeName().equals(DEFINED_SYMBOL)) {
} else if (child.getName().equals(DEFINED_SYMBOL)) {
// Add the symbol to the symbol list
symbols.add( ((Element)child).getAttribute(SYMBOL));
}
child = child.getNextSibling();
}
MakeScannerInfo info = new MakeScannerInfo(project);
info.setIncludePaths((String[])includes.toArray(new String[includes.size()]));
@ -193,15 +195,11 @@ public class MakeScannerProvider extends ScannerProvider {
ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(project);
Element rootElement = descriptor.getProjectData(CDESCRIPTOR_ID);
ICStorageElement rootElement = descriptor.getProjectStorageElement(CDESCRIPTOR_ID);
// Clear out all current children
// Note: Probably would be a better idea to merge in the data
Node child = rootElement.getFirstChild();
while (child != null) {
rootElement.removeChild(child);
child = rootElement.getFirstChild();
}
rootElement.clear();
descriptor.saveProjectData();
migrateToCPathEntries(scannerInfo);

View file

@ -21,7 +21,7 @@ public interface IScannerConfigBuilderInfo2Set {
*
* @return InfoContext - to IScannerConfigBuilderInfo2 map
*/
Map<InfoContext, Object> getInfoMap();
Map getInfoMap();
IScannerConfigBuilderInfo2 getInfo(InfoContext context);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 QNX Software Systems and others.
* Copyright (c) 2000, 2008 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* James Blackburn (Broadcom Corp.) - Use ICStorageElement
*******************************************************************************/
package org.eclipse.cdt.make.internal.core;
@ -14,24 +15,17 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
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.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.XmlStorageUtil;
import org.eclipse.cdt.make.core.IMakeCommonBuildInfo;
import org.eclipse.cdt.make.core.IMakeTarget;
import org.eclipse.cdt.make.core.MakeCorePlugin;
@ -42,10 +36,6 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class ProjectTargets {
@ -65,7 +55,7 @@ public class ProjectTargets {
private static final String BAD_TARGET = "buidlTarget"; //$NON-NLS-1$
private static final String TARGET = "buildTarget"; //$NON-NLS-1$
private HashMap targetMap = new HashMap();
private HashMap<IContainer, List<IMakeTarget>> targetMap = new HashMap<IContainer, List<IMakeTarget>>();
private IProject project;
@ -75,68 +65,54 @@ public class ProjectTargets {
this.project = project;
Document document = translateCDTProjectToDocument();
ICStorageElement rootElement = null;
try {
ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(getProject(), true);
rootElement = descriptor.getProjectStorageElement(MAKE_TARGET_KEY);
//Historical ... fall back to the workspace and look in previous
// location
if (document == null || !document.hasChildNodes()) {
IPath targetFilePath = MakeCorePlugin.getDefault().getStateLocation().append(project.getName()).addFileExtension(
TARGETS_EXT);
targetFile = targetFilePath.toFile();
try {
InputStream input = new FileInputStream(targetFile);
document = translateInputStreamToDocument(input);
writeTargets = true; // update cdtproject
} catch (FileNotFoundException ex) {
/* Ignore */
}
}
if (document != null) {
extractMakeTargetsFromDocument(document, manager);
if (writeTargets) {
//Historical ... fall back to the workspace and look in previous XML file location
if (rootElement.getChildren().length == 0) {
IPath targetFilePath = MakeCorePlugin.getDefault().getStateLocation().append(project.getName()).addFileExtension(
TARGETS_EXT);
targetFile = targetFilePath.toFile();
try {
Document doc = getAsXML();
translateDocumentToCDTProject(doc);
} catch (Exception e) {
targetFile = null;
}
if (targetFile != null) {
targetFile.delete(); // removed old
InputStream input = new FileInputStream(targetFile);
ICStorageElement oldElement = translateInputStreamToDocument(input);
rootElement.importChild(oldElement);
writeTargets = true; // update the project description
} catch (FileNotFoundException ex) {
/* Ignore */
}
}
}
}
protected String getString(Node target, String tagName) {
Node node = searchNode(target, tagName);
return node != null ? (node.getFirstChild() == null ? null : node.getFirstChild().getNodeValue()) : null;
}
protected Node searchNode(Node target, String tagName) {
NodeList list = target.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i).getNodeName().equals(tagName))
return list.item(i);
if (rootElement != null) {
extractMakeTargetsFromDocument(rootElement, manager);
// If write targets then we have converted previous make targets
if (writeTargets) {
saveTargets();
if (targetFile != null) {
targetFile.delete(); // removed old
}
}
}
} catch (Exception e) {
MakeCorePlugin.log(e);
}
return null;
}
public IMakeTarget[] get(IContainer container) {
ArrayList list = (ArrayList) targetMap.get(container);
List<IMakeTarget> list = targetMap.get(container);
if (list != null) {
return (IMakeTarget[]) list.toArray(new IMakeTarget[list.size()]);
return list.toArray(new IMakeTarget[list.size()]);
}
return new IMakeTarget[0];
}
public IMakeTarget findTarget(IContainer container, String name) {
ArrayList list = (ArrayList) targetMap.get(container);
List<IMakeTarget> list = targetMap.get(container);
if (list != null) {
Iterator targets = list.iterator();
while (targets.hasNext()) {
IMakeTarget target = (IMakeTarget) targets.next();
if (target.getName().equals(name)) {
for (IMakeTarget target : list) {
if (name.equals(target.getName())) {
return target;
}
}
@ -145,20 +121,20 @@ public class ProjectTargets {
}
public void add(MakeTarget target) throws CoreException {
ArrayList list = (ArrayList) targetMap.get(target.getContainer());
List<IMakeTarget> list = targetMap.get(target.getContainer());
if (list != null && list.contains(target)) {
throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1,
MakeMessages.getString("MakeTargetManager.target_exists"), null)); //$NON-NLS-1$
}
if (list == null) {
list = new ArrayList();
list = new ArrayList<IMakeTarget>();
targetMap.put(target.getContainer(), list);
}
list.add(target);
}
public boolean contains(MakeTarget target) {
ArrayList list = (ArrayList) targetMap.get(target.getContainer());
List<IMakeTarget> list = targetMap.get(target.getContainer());
if (list != null && list.contains(target)) {
return true;
}
@ -166,7 +142,7 @@ public class ProjectTargets {
}
public boolean remove(MakeTarget target) {
ArrayList list = (ArrayList) targetMap.get(target.getContainer());
List<IMakeTarget> list = targetMap.get(target.getContainer());
if (list == null || !list.contains(target)) {
return false;
}
@ -181,219 +157,138 @@ public class ProjectTargets {
return project;
}
protected Document getAsXML() throws CoreException {
Document doc;
try {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
} catch (ParserConfigurationException ex) {
//This should never happen.
throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1,
"Error creating new XML storage document", ex)); //$NON-NLS-1$
}
Element targetsRootElement = doc.createElement(BUILD_TARGET_ELEMENT);
doc.appendChild(targetsRootElement);
Iterator container = targetMap.entrySet().iterator();
while (container.hasNext()) {
List targets = (List) ((Map.Entry) container.next()).getValue();
for (int i = 0; i < targets.size(); i++) {
MakeTarget target = (MakeTarget) targets.get(i);
targetsRootElement.appendChild(createTargetElement(doc, target));
}
}
return doc;
}
private Node createTargetElement(Document doc, MakeTarget target) {
Element targetElem = doc.createElement(TARGET_ELEMENT);
/**
* Persist the MakeTarget as a child of parent
* @param parent
* @param target
* @return create ICStorageElement
*/
private ICStorageElement createTargetElement(ICStorageElement parent, IMakeTarget target) {
ICStorageElement targetElem = parent.createChild(TARGET_ELEMENT);
targetElem.setAttribute(TARGET_ATTR_NAME, target.getName());
targetElem.setAttribute(TARGET_ATTR_ID, target.getTargetBuilderID());
targetElem.setAttribute(TARGET_ATTR_PATH, target.getContainer().getProjectRelativePath().toString());
Element elem = doc.createElement(TARGET_COMMAND);
targetElem.appendChild(elem);
elem.appendChild(doc.createTextNode(target.getBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, "make"))); //$NON-NLS-1$
ICStorageElement elem = targetElem.createChild(TARGET_COMMAND);
elem.setValue(target.getBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, "make")); //$NON-NLS-1$
String targetAttr = target.getBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, null);
if ( targetAttr != null) {
elem = doc.createElement(TARGET_ARGUMENTS);
elem.appendChild(doc.createTextNode(targetAttr));
targetElem.appendChild(elem);
elem = targetElem.createChild(TARGET_ARGUMENTS);
elem.setValue(targetAttr);
}
targetAttr = target.getBuildAttribute(IMakeTarget.BUILD_TARGET, null);
if (targetAttr != null) {
elem = doc.createElement(TARGET);
elem.appendChild(doc.createTextNode(targetAttr));
targetElem.appendChild(elem);
elem = targetElem.createChild(TARGET);
elem.setValue(targetAttr);
}
elem = doc.createElement(TARGET_STOP_ON_ERROR);
elem.appendChild(doc.createTextNode(new Boolean(target.isStopOnError()).toString()));
targetElem.appendChild(elem);
elem = targetElem.createChild(TARGET_STOP_ON_ERROR);
elem.setValue(new Boolean(target.isStopOnError()).toString());
elem = targetElem.createChild(TARGET_USE_DEFAULT_CMD);
elem.setValue(new Boolean(target.isDefaultBuildCmd()).toString());
elem = targetElem.createChild(TARGET_RUN_ALL_BUILDERS);
elem.setValue(new Boolean(target.runAllBuilders()).toString());
elem = doc.createElement(TARGET_USE_DEFAULT_CMD);
elem.appendChild(doc.createTextNode(new Boolean(target.isDefaultBuildCmd()).toString()));
targetElem.appendChild(elem);
elem = doc.createElement(TARGET_RUN_ALL_BUILDERS);
elem.appendChild(doc.createTextNode(new Boolean(target.runAllBuilders()).toString()));
targetElem.appendChild(elem);
return targetElem;
}
public void saveTargets() throws CoreException {
Document doc = getAsXML();
//Historical method would save the output to the stream specified
//translateDocumentToOutputStream(doc, output);
translateDocumentToCDTProject(doc);
}
protected void saveTargets(Document doc, OutputStream output) throws TransformerException {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer 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(output);
transformer.transform(source, outputTarget);
}
/**
* This output method saves the information into the .cdtproject metadata file.
*
* @param doc
* Saves the targets to the project description
* @throws CoreException
*/
protected void translateDocumentToCDTProject(Document doc) throws CoreException {
ICDescriptor descriptor;
descriptor = CCorePlugin.getDefault().getCProjectDescription(getProject(), true);
Element rootElement = descriptor.getProjectData(MAKE_TARGET_KEY);
public void saveTargets() throws CoreException {
ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(getProject(), true);
ICStorageElement rootElement = descriptor.getProjectStorageElement(MAKE_TARGET_KEY);
//Nuke the children since we are going to write out new ones
NodeList kids = rootElement.getChildNodes();
for (int i = 0; i < kids.getLength(); i++) {
rootElement.removeChild(kids.item(i));
i--;
}
rootElement.clear();
// Fetch the ProjectTargets as ICStorageElements
rootElement = rootElement.createChild(BUILD_TARGET_ELEMENT);
for (Entry<IContainer, List<IMakeTarget>> e : targetMap.entrySet())
for (IMakeTarget target : e.getValue())
createTargetElement(rootElement, target);
//Extract the root of our temporary document
Node node = doc.getFirstChild();
if (node.hasChildNodes()) {
//Create a copy which is a part of the new document
Node appendNode = rootElement.getOwnerDocument().importNode(node, true);
//Put the copy into the document in the appropriate location
rootElement.appendChild(appendNode);
}
//Save the results
descriptor.saveProjectData();
}
/**
* This method parses the .cdtproject file for the XML document describing the build targets.
*
* This method loads an old style XML document provided in the input stream
* and returns an ICStorageElemnt wrapping it.
* @param input
* @return
* @return ICStorageElement or null
*/
protected Document translateCDTProjectToDocument() {
Document document = null;
Element rootElement = null;
protected ICStorageElement translateInputStreamToDocument(InputStream input) {
try {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
ICDescriptor descriptor;
descriptor = CCorePlugin.getDefault().getCProjectDescription(getProject(), true);
rootElement = descriptor.getProjectData(MAKE_TARGET_KEY);
} catch (ParserConfigurationException e) {
return document;
} catch (CoreException e) {
return document;
}
NodeList list = rootElement.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i).getNodeType() == Node.ELEMENT_NODE) {
Node appendNode = document.importNode(list.item(i), true);
document.appendChild(appendNode);
break; // should never have multiple <buildtargets>
}
}
return document;
}
/**
* This method parses the input stream for the XML document describing the build targets.
*
* @param input
* @return
*/
protected Document translateInputStreamToDocument(InputStream input) {
Document document = null;
try {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input);
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input);
return XmlStorageUtil.createCStorageTree(document);
} catch (Exception e) {
MakeCorePlugin.log(e);
}
return document;
return null;
}
/**
* Extract the make target information which is contained in the XML Document
*
*
* @param document
*/
protected void extractMakeTargetsFromDocument(Document document, MakeTargetManager manager) {
Node node = document.getFirstChild();
if (node != null && node.getNodeName().equals(BUILD_TARGET_ELEMENT)) {
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
node = list.item(i);
if (node.getNodeName().equals(TARGET_ELEMENT)) {
IContainer container = null;
NamedNodeMap attr = node.getAttributes();
String path = attr.getNamedItem(TARGET_ATTR_PATH).getNodeValue();
if (path != null && !path.equals("")) { //$NON-NLS-1$
container = project.getFolder(path);
} else {
container = project;
}
try {
MakeTarget target = new MakeTarget(manager, project, attr.getNamedItem(TARGET_ATTR_ID).getNodeValue(),
attr.getNamedItem(TARGET_ATTR_NAME).getNodeValue());
target.setContainer(container);
String option = getString(node, TARGET_STOP_ON_ERROR);
if (option != null) {
target.setStopOnError(Boolean.valueOf(option).booleanValue());
protected void extractMakeTargetsFromDocument(ICStorageElement root, MakeTargetManager manager) {
for (ICStorageElement node : root.getChildren()) {
if (node.getName().equals(BUILD_TARGET_ELEMENT)) {
for (ICStorageElement child : node.getChildren()) {
node = child;
if (node.getName().equals(TARGET_ELEMENT)) {
IContainer container = null;
String path = node.getAttribute(TARGET_ATTR_PATH);
if (path != null && !path.equals("")) { //$NON-NLS-1$
container = project.getFolder(path);
} else {
container = project;
}
option = getString(node, TARGET_USE_DEFAULT_CMD);
if (option != null) {
target.setUseDefaultBuildCmd(Boolean.valueOf(option).booleanValue());
try {
MakeTarget target = new MakeTarget(manager, project, node.getAttribute(TARGET_ATTR_ID),
node.getAttribute(TARGET_ATTR_NAME));
target.setContainer(container);
ICStorageElement[] option = node.getChildrenByName(TARGET_STOP_ON_ERROR);
if (option.length > 0) {
target.setStopOnError(Boolean.valueOf(option[0].getValue()).booleanValue());
}
option = node.getChildrenByName(TARGET_USE_DEFAULT_CMD);
if (option.length > 0) {
target.setUseDefaultBuildCmd(Boolean.valueOf(option[0].getValue()).booleanValue());
}
option = node.getChildrenByName(TARGET_COMMAND);
if (option.length > 0) {
target.setBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, option[0].getValue());
}
option = node.getChildrenByName(TARGET_ARGUMENTS);
if (option.length > 0) {
target.setBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, option[0].getValue());
} else if (!target.isDefaultBuildCmd()) {
// Clear build-arguments set in target constructor to project defaults
target.setBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, ""); //$NON-NLS-1$
}
option = node.getChildrenByName(BAD_TARGET);
if (option.length > 0) {
target.setBuildAttribute(IMakeTarget.BUILD_TARGET, option[0].getValue());
}
option = node.getChildrenByName(TARGET);
if (option.length > 0) {
target.setBuildAttribute(IMakeTarget.BUILD_TARGET, option[0].getValue());
}
option = node.getChildrenByName(TARGET_RUN_ALL_BUILDERS);
if (option.length > 0) {
target.setRunAllBuilders(Boolean.valueOf(option[0].getValue()).booleanValue());
}
add(target);
} catch (CoreException e) {
MakeCorePlugin.log(e);
}
option = getString(node, TARGET_COMMAND);
if (option != null) {
target.setBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, option);
}
option = getString(node, TARGET_ARGUMENTS);
if (option != null) {
target.setBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, option);
} else if (!target.isDefaultBuildCmd()) {
// Clear build-arguments set in target constructor to project defaults
target.setBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, ""); //$NON-NLS-1$
}
option = getString(node, BAD_TARGET);
if (option != null) {
target.setBuildAttribute(IMakeTarget.BUILD_TARGET, option);
}
option = getString(node, TARGET);
if (option != null) {
target.setBuildAttribute(IMakeTarget.BUILD_TARGET, option);
}
option = getString(node, TARGET_RUN_ALL_BUILDERS);
if (option != null) {
target.setRunAllBuilders(Boolean.valueOf(option).booleanValue());
}
add(target);
} catch (CoreException e) {
MakeCorePlugin.log(e);
}
}
}

View file

@ -365,7 +365,7 @@ public class PerProjectSICollector implements IScannerInfoCollector3, IScannerIn
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector2#getDefinedSymbols()
*/
public Map<?, ?> getDefinedSymbols() {
public Map getDefinedSymbols() {
Map<?, ?> definedSymbols = ScannerConfigUtil.scSymbolEntryMap2Map(sumDiscoveredSymbols);
return definedSymbols;
}

View file

@ -7,6 +7,7 @@
*
* Contributors:
* IBM - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.make.internal.core.scannerconfig2;
@ -22,6 +23,7 @@ import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.make.core.MakeCorePlugin;
import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo;
@ -35,9 +37,6 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Status;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* New ScannerConfigInfoFactory
@ -93,31 +92,29 @@ public class ScannerConfigInfoFactory2 {
load(profileId);
}
private void load(String profileId) {
private void load(String profileId) {
ICDescriptor descriptor;
try {
descriptor = CCorePlugin.getDefault().getCProjectDescription(fProject, false);
Element rootEl = descriptor != null ? descriptor.getProjectData(SCANNER_CONFIG) : null;
ICStorageElement rootEl = descriptor != null ? descriptor.getProjectStorageElement(SCANNER_CONFIG) : null;
InfoContext defaultContext = new InfoContext(fProject);
if(rootEl == null || !rootEl.hasChildNodes()){
if(rootEl == null || !rootEl.hasChildren()){
BuildProperty prop = new BuildProperty(this, fProject, defaultContext, (Store)create(MakeCorePlugin.getDefault().getPluginPreferences(), profileId, false), profileId);
fMap.put(defaultContext, prop);
prop.isDirty = true;
} else {
BuildProperty prop = new BuildProperty(this, fProject,defaultContext, profileId, rootEl);
BuildProperty prop = new BuildProperty(this, fProject, defaultContext, profileId, rootEl);
fMap.put(defaultContext, prop);
for (Node sc = rootEl.getFirstChild();
sc != null; sc = sc.getNextSibling()) {
if (sc.getNodeName().equals(ELEMENT_CS_INFO)) {
Element el = (Element)sc;
String instanceId = el.getAttribute(ATTRIBUTE_CS_INFO_INSTANCE_ID);
if(instanceId.length() != 0){
InfoContext c = new InfoContext(fProject, instanceId);
BuildProperty p = new BuildProperty(this, fProject, c, profileId, el);
fMap.put(c, p);
}
}
for (ICStorageElement sc : rootEl.getChildren()) {
if (sc.getName().equals(ELEMENT_CS_INFO)) {
String instanceId = sc.getAttribute(ATTRIBUTE_CS_INFO_INSTANCE_ID);
if(instanceId != null && instanceId.length() > 0){
InfoContext c = new InfoContext(fProject, instanceId);
BuildProperty p = new BuildProperty(this, fProject, c, profileId, sc);
fMap.put(c, p);
}
}
}
}
} catch (CoreException e) {
@ -132,16 +129,10 @@ public class ScannerConfigInfoFactory2 {
public void save(boolean serializeDescriptor) throws CoreException {
if (isDirty()) {
ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
Element sc = descriptor.getProjectData(SCANNER_CONFIG);
ICStorageElement sc = descriptor.getProjectStorageElement(SCANNER_CONFIG);
Document doc = sc.getOwnerDocument();
// Clear out all current children
Node child = sc.getFirstChild();
while (child != null) {
sc.removeChild(child);
child = sc.getFirstChild();
}
// Clear all child settings
sc.clear();
BuildProperty prop = (BuildProperty)fMap.get(new InfoContext(fProject));
prop.store(sc);
@ -161,10 +152,9 @@ public class ScannerConfigInfoFactory2 {
if(p == prop)
continue;
Element el = doc.createElement(ELEMENT_CS_INFO);
ICStorageElement el = sc.createChild(ELEMENT_CS_INFO);
el.setAttribute(ATTRIBUTE_CS_INFO_INSTANCE_ID, instanceId);
p.store(el);
sc.appendChild(el);
}
if(serializeDescriptor)
@ -218,7 +208,7 @@ public class ScannerConfigInfoFactory2 {
public void save() throws CoreException {
if (isDirty()) {
Set idSet = new HashSet(fMap.size() - 1);
Set<String> idSet = new HashSet<String>(fMap.size() - 1);
Preference pref = (Preference)fMap.get(new InfoContext(null));
pref.store();
@ -244,7 +234,7 @@ public class ScannerConfigInfoFactory2 {
}
if(idSet.size() != 0){
String[] ids = (String[])idSet.toArray(new String[idSet.size()]);
String[] ids = idSet.toArray(new String[idSet.size()]);
String idsString = CDataUtil.arrayToString(ids, DELIMITER);
set(INFO_INSTANCE_IDS, idsString);
}
@ -281,7 +271,7 @@ public class ScannerConfigInfoFactory2 {
private static abstract class StoreSet implements IScannerConfigBuilderInfo2Set {
protected HashMap fMap = new HashMap();
protected HashMap<InfoContext, Store> fMap = new HashMap<InfoContext, Store>();
protected boolean fIsDirty;
StoreSet(){
@ -304,21 +294,21 @@ public class ScannerConfigInfoFactory2 {
}
public InfoContext[] getContexts() {
return (InfoContext[])fMap.keySet().toArray(new InfoContext[fMap.size()]);
return fMap.keySet().toArray(new InfoContext[fMap.size()]);
}
public IScannerConfigBuilderInfo2 getInfo(InfoContext context) {
return (IScannerConfigBuilderInfo2)fMap.get(context);
return fMap.get(context);
}
public Map getInfoMap() {
public Map<InfoContext, Store> getInfoMap() {
return Collections.unmodifiableMap(fMap);
}
public IScannerConfigBuilderInfo2 removeInfo(InfoContext context) throws CoreException {
checkRemoveInfo(context);
fIsDirty = true;
return (IScannerConfigBuilderInfo2)fMap.remove(context);
return fMap.remove(context);
}
private void checkRemoveInfo(InfoContext context) throws CoreException{
@ -329,8 +319,8 @@ public class ScannerConfigInfoFactory2 {
public boolean isDirty(){
if(fIsDirty)
return true;
for(Iterator iter = fMap.values().iterator(); iter.hasNext();){
Store prop = (Store)iter.next();
for(Iterator<Store> iter = fMap.values().iterator(); iter.hasNext();){
Store prop = iter.next();
if(prop.isDirty)
return true;
}
@ -358,12 +348,14 @@ public class ScannerConfigInfoFactory2 {
protected boolean autoDiscoveryEnabled;
protected boolean problemReportingEnabled;
protected String selectedProfile = EMPTY_STRING;
protected Map profileOptionsMap; // (profileId, options)
/** Map from profile ID -> ProfileOptions */
protected Map<String, ProfileOptions> profileOptionsMap;
static class ProfileOptions {
protected boolean buildOutputFileActionEnabled;
protected String buildOutputFilePath = EMPTY_STRING;
protected boolean buildOutputParserEnabled;
protected Map providerOptionsMap; // {providerId, options}
/** Map from provider ID -> providerOptions */
protected Map<String, ProviderOptions> providerOptionsMap;
static class ProviderOptions {
protected String providerKind; // derived
protected boolean providerOutputParserEnabled;
@ -393,10 +385,9 @@ public class ScannerConfigInfoFactory2 {
this.buildOutputFileActionEnabled = base.buildOutputFileActionEnabled;
this.buildOutputFilePath = base.buildOutputFilePath;
this.buildOutputParserEnabled = base.buildOutputParserEnabled;
this.providerOptionsMap = new LinkedHashMap(base.providerOptionsMap);
for(Iterator iter = this.providerOptionsMap.entrySet().iterator(); iter.hasNext();){
Map.Entry entry = (Map.Entry)iter.next();
ProviderOptions basePo = (ProviderOptions)entry.getValue();
this.providerOptionsMap = new LinkedHashMap<String, ProviderOptions>(base.providerOptionsMap);
for (Map.Entry<String, ProviderOptions> entry : providerOptionsMap.entrySet()) {
ProviderOptions basePo = entry.getValue();
entry.setValue(new ProviderOptions(basePo));
}
}
@ -411,10 +402,9 @@ public class ScannerConfigInfoFactory2 {
this.autoDiscoveryEnabled = base.autoDiscoveryEnabled;
this.problemReportingEnabled = base.problemReportingEnabled;
this.selectedProfile = ScannerConfigProfileManager.NULL_PROFILE_ID.equals(profileId) ? base.selectedProfile : profileId;
this.profileOptionsMap = new LinkedHashMap(base.profileOptionsMap);
for(Iterator iter = this.profileOptionsMap.entrySet().iterator(); iter.hasNext();){
Map.Entry entry = (Map.Entry)iter.next();
ProfileOptions basePo = (ProfileOptions)entry.getValue();
this.profileOptionsMap = new LinkedHashMap<String, ProfileOptions>(base.profileOptionsMap);
for (Map.Entry<String, ProfileOptions> entry : profileOptionsMap.entrySet()) {
ProfileOptions basePo = entry.getValue();
entry.setValue(new ProfileOptions(basePo));
}
@ -473,15 +463,15 @@ public class ScannerConfigInfoFactory2 {
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#getProfileIdList()
*/
public List getProfileIdList() {
return new ArrayList(profileOptionsMap.keySet());
public List<String> getProfileIdList() {
return new ArrayList<String>(profileOptionsMap.keySet());
}
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#isBuildOutputFileActionEnabled()
*/
public boolean isBuildOutputFileActionEnabled() {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
return (po != null) ? po.buildOutputFileActionEnabled : false;
}
@ -489,7 +479,7 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#setBuildOutputFileActionEnabled(boolean)
*/
public void setBuildOutputFileActionEnabled(boolean enable) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
po.buildOutputFileActionEnabled = setDirty(po.buildOutputFileActionEnabled, enable);
}
@ -499,7 +489,7 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#getBuildOutputFilePath()
*/
public String getBuildOutputFilePath() {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
return (po != null) ? po.buildOutputFilePath : EMPTY_STRING;
}
@ -507,7 +497,7 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#setBuildOutputFilePath(java.lang.String)
*/
public void setBuildOutputFilePath(String path) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
po.buildOutputFilePath = setDirty(po.buildOutputFilePath, path);
}
@ -517,7 +507,7 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#isBuildOutputParserEnabled()
*/
public boolean isBuildOutputParserEnabled() {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
return (po != null) ? po.buildOutputParserEnabled : true;
}
@ -525,7 +515,7 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#setBuildOutputParserEnabled(boolean)
*/
public void setBuildOutputParserEnabled(boolean enable) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
po.buildOutputParserEnabled = setDirty(po.buildOutputParserEnabled, enable);
}
@ -536,7 +526,7 @@ public class ScannerConfigInfoFactory2 {
*/
@SuppressWarnings("unchecked")
public List<String> getProviderIdList() {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
return (po != null) ? new ArrayList<String>(po.providerOptionsMap.keySet()) : new ArrayList<String>(0);
}
@ -558,9 +548,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#isSIProviderOutputParserEnabled(java.lang.String)
*/
public boolean isProviderOutputParserEnabled(String providerId) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
return (ppo == null) ? false : ppo.providerOutputParserEnabled;
}
return false;
@ -570,9 +560,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#setSIProviderOutputParserEnabled(java.lang.String, boolean)
*/
public void setProviderOutputParserEnabled(String providerId, boolean enable) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
if (ppo != null) {
ppo.providerOutputParserEnabled = setDirty(ppo.providerOutputParserEnabled, enable);
}
@ -583,9 +573,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#isUseDefaultProviderCommand(java.lang.String)
*/
public boolean isUseDefaultProviderCommand(String providerId) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
return (ppo == null) ? false : ppo.providerRunUseDefault;
}
return false;
@ -595,9 +585,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#setUseDefaultProviderCommand(java.lang.String, boolean)
*/
public void setUseDefaultProviderCommand(String providerId, boolean enable) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
if (ppo != null) {
ppo.providerRunUseDefault = setDirty(ppo.providerRunUseDefault, enable);
}
@ -608,9 +598,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#getProviderRunCommand(java.lang.String)
*/
public String getProviderRunCommand(String providerId) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
return (ppo == null) ? null : ppo.providerRunCommand;
}
return null;
@ -620,9 +610,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#setProviderRunCommand(java.lang.String, java.lang.String)
*/
public void setProviderRunCommand(String providerId, String command) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
if (ppo != null) {
ppo.providerRunCommand = setDirty(ppo.providerRunCommand, command);
}
@ -633,9 +623,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#getProviderRunArguments(java.lang.String)
*/
public String getProviderRunArguments(String providerId) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
return (ppo == null) ? null : ppo.providerRunArguments;
}
return null;
@ -645,9 +635,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#setProviderRunArguments(java.lang.String, java.lang.String)
*/
public void setProviderRunArguments(String providerId, String arguments) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
if (ppo != null) {
ppo.providerRunArguments = setDirty(ppo.providerRunArguments, arguments);
}
@ -658,9 +648,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#getProviderOpenFilePath(java.lang.String)
*/
public String getProviderOpenFilePath(String providerId) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
return (ppo == null) ? null : ppo.providerOpenFilePath;
}
return null;
@ -670,9 +660,9 @@ public class ScannerConfigInfoFactory2 {
* @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2#setProviderOpenFilePath(java.lang.String, java.lang.String)
*/
public void setProviderOpenFilePath(String providerId, String filePath) {
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(selectedProfile);
ProfileOptions po = profileOptionsMap.get(selectedProfile);
if (po != null) {
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
if (ppo != null) {
ppo.providerOpenFilePath = setDirty(ppo.providerOpenFilePath, filePath);
}
@ -711,7 +701,7 @@ public class ScannerConfigInfoFactory2 {
po.buildOutputFilePath = (buildOutputFilePath != null) ? buildOutputFilePath : EMPTY_STRING;
}
}
po.providerOptionsMap = new LinkedHashMap(providerIds.size());
po.providerOptionsMap = new LinkedHashMap<String, ProfileOptions.ProviderOptions>(providerIds.size());
for (int i = 0; i < providerIds.size(); ++i) {
ProfileOptions.ProviderOptions ppo = new ProfileOptions.ProviderOptions();
String providerId = (String) providerIds.get(i);
@ -751,7 +741,7 @@ public class ScannerConfigInfoFactory2 {
private String profileId;
private ScannerConfigInfoSet container;
BuildProperty(ScannerConfigInfoSet container, IProject project, InfoContext context, String profileId, Element element) {
BuildProperty(ScannerConfigInfoSet container, IProject project, InfoContext context, String profileId, ICStorageElement element) {
super();
this.project = project;
this.context = context;
@ -779,27 +769,26 @@ public class ScannerConfigInfoFactory2 {
/* (non-Javadoc)
* @see org.eclipse.cdt.make.internal.core.scannerconfig2.ScannerConfigInfoFactory2.Store#load()
*/
protected void load(Element element) {
protected void load(ICStorageElement element) {
// ICDescriptor descriptor;
List profileIds = ScannerConfigProfileManager.getInstance().getProfileIds(context);
List loadedProfiles = new ArrayList();
List<String> profileIds = ScannerConfigProfileManager.getInstance().getProfileIds(context);
List<String> loadedProfiles = new ArrayList<String>();
// try {
// descriptor = CCorePlugin.getDefault().getCProjectDescription(project, false);
for (Node sc = element.getFirstChild();
sc != null; sc = sc.getNextSibling()) {
if (sc.getNodeName().equals(SC_AUTODISCOVERY)) {
for (ICStorageElement sc : element.getChildren()) {
if (sc.getName().equals(SC_AUTODISCOVERY)) {
autoDiscoveryEnabled = Boolean.valueOf(
((Element)sc).getAttribute(ENABLED)).booleanValue();
sc.getAttribute(ENABLED)).booleanValue();
selectedProfile = (profileId == ScannerConfigProfileManager.NULL_PROFILE_ID)
? ((Element)sc).getAttribute(SELECTED_PROFILE_ID)
? sc.getAttribute(SELECTED_PROFILE_ID)
: profileId;
problemReportingEnabled = Boolean.valueOf(
((Element)sc).getAttribute(PROBLEM_REPORTING_ENABLED)).booleanValue();
sc.getAttribute(PROBLEM_REPORTING_ENABLED)).booleanValue();
}
else if (sc.getNodeName().equals(PROFILE)) {
if (profileIds.contains(((Element)sc).getAttribute(ID))) {
load(sc);
loadedProfiles.add(((Element)sc).getAttribute(ID));
else if (sc.getName().equals(PROFILE)) {
if (profileIds.contains(sc.getAttribute(ID))) {
loadProfile(sc);
loadedProfiles.add(sc.getAttribute(ID));
}
}
}
@ -844,7 +833,7 @@ public class ScannerConfigInfoFactory2 {
ScannerConfigProfile configuredProfile = ScannerConfigProfileManager.getInstance().
getSCProfileConfiguration(profileId);
po.providerOptionsMap = new LinkedHashMap();
po.providerOptionsMap = new LinkedHashMap<String, ProfileOptions.ProviderOptions>();
for (Iterator i = configuredProfile.getSIProviderIds().iterator(); i.hasNext(); ) {
String providerId = (String) i.next();
ProfileOptions.ProviderOptions ppo = new ProfileOptions.ProviderOptions();
@ -865,7 +854,7 @@ public class ScannerConfigInfoFactory2 {
}
if (profileOptionsMap == null) {
profileOptionsMap = new LinkedHashMap();
profileOptionsMap = new LinkedHashMap<String, ProfileOptions>();
}
profileOptionsMap.put(profileId, po);
}
@ -898,10 +887,10 @@ public class ScannerConfigInfoFactory2 {
getSCProfileConfiguration(selectedProfile);
// get the one and only provider id
String providerId = (String) configuredProfile.getSIProviderIds().get(0);
po.providerOptionsMap = new LinkedHashMap(1);
po.providerOptionsMap = new LinkedHashMap<String, ProfileOptions.ProviderOptions>(1);
po.providerOptionsMap.put(providerId, ppo);
profileOptionsMap = new LinkedHashMap(1);
profileOptionsMap = new LinkedHashMap<String, ProfileOptions>(1);
profileOptionsMap.put(profileId, po);
// store migrated data
@ -918,42 +907,37 @@ public class ScannerConfigInfoFactory2 {
/**
* @param profile
*/
private void load(Node profile) {
private void loadProfile(ICStorageElement profile) {
if (profileOptionsMap == null) {
profileOptionsMap = new LinkedHashMap(1);
profileOptionsMap = new LinkedHashMap<String, ProfileOptions>(1);
}
ProfileOptions po = new ProfileOptions();
String profileId = ((Element)profile).getAttribute(ID);
String profileId = profile.getAttribute(ID);
profileOptionsMap.put(profileId, po);
// get the list of providers from the profile configuration
ScannerConfigProfile configuredProfile = ScannerConfigProfileManager.getInstance().
getSCProfileConfiguration(profileId);
List providerIds = configuredProfile.getSIProviderIds();
List<String> providerIds = configuredProfile.getSIProviderIds();
int providerCounter = 0;
po.providerOptionsMap = new LinkedHashMap(providerIds.size());
po.providerOptionsMap = new LinkedHashMap<String, ProfileOptions.ProviderOptions>(providerIds.size());
for (Node child = profile.getFirstChild();
child != null;
child = child.getNextSibling()) {
for (ICStorageElement child : profile.getChildren()) {
// buildOutputProvider element
if (BUILD_OUTPUT_PROVIDER.equals(child.getNodeName())) {
for (Node grandchild = child.getFirstChild();
grandchild != null;
grandchild = grandchild.getNextSibling()) {
if (OPEN_ACTION.equals(grandchild.getNodeName())) {
if (BUILD_OUTPUT_PROVIDER.equals(child.getName())) {
for (ICStorageElement grandchild : child.getChildren()) {
if (OPEN_ACTION.equals(grandchild.getName())) {
po.buildOutputFileActionEnabled = Boolean.valueOf(
((Element)grandchild).getAttribute(ENABLED)).booleanValue();
po.buildOutputFilePath = ((Element)grandchild).getAttribute(FILE_PATH);
grandchild.getAttribute(ENABLED)).booleanValue();
po.buildOutputFilePath = grandchild.getAttribute(FILE_PATH);
}
else if (PARSER.equals(grandchild.getNodeName())) {
else if (PARSER.equals(grandchild.getName())) {
po.buildOutputParserEnabled = Boolean.valueOf(
((Element)grandchild).getAttribute(ENABLED)).booleanValue();
grandchild.getAttribute(ENABLED)).booleanValue();
}
}
}
else if (SCANNER_INFO_PROVIDER.equals(child.getNodeName())) {
String providerId = ((Element)child).getAttribute(ID);
else if (SCANNER_INFO_PROVIDER.equals(child.getName())) {
String providerId = child.getAttribute(ID);
if (providerIds.get(providerCounter).equals(providerId)) {
// new provider
ProfileOptions.ProviderOptions ppo = new ProfileOptions.ProviderOptions();
@ -961,23 +945,21 @@ public class ScannerConfigInfoFactory2 {
ppo.providerKind = configuredProfile.getScannerInfoProviderElement(
providerId).getProviderKind();
for (Node grandchild = child.getFirstChild();
grandchild != null;
grandchild = grandchild.getNextSibling()) {
for (ICStorageElement grandchild : child.getChildren()) {
// action
if (RUN_ACTION.equals(grandchild.getNodeName())) {
if (RUN_ACTION.equals(grandchild.getName())) {
ppo.providerRunUseDefault = Boolean.valueOf(
((Element)grandchild).getAttribute(USE_DEFAULT)).booleanValue();
ppo.providerRunCommand = ((Element)grandchild).getAttribute(COMMAND);
ppo.providerRunArguments = ((Element)grandchild).getAttribute(ARGUMENTS);
grandchild.getAttribute(USE_DEFAULT)).booleanValue();
ppo.providerRunCommand = grandchild.getAttribute(COMMAND);
ppo.providerRunArguments = grandchild.getAttribute(ARGUMENTS);
}
else if (OPEN_ACTION.equals(grandchild.getNodeName())) {
ppo.providerOpenFilePath = ((Element)grandchild).getAttribute(FILE_PATH);
else if (OPEN_ACTION.equals(grandchild.getName())) {
ppo.providerOpenFilePath = grandchild.getAttribute(FILE_PATH);
}
// parser
else if (PARSER.equals(grandchild.getNodeName())) {
else if (PARSER.equals(grandchild.getName())) {
ppo.providerOutputParserEnabled = Boolean.valueOf(
((Element)grandchild).getAttribute(ENABLED)).booleanValue();
grandchild.getAttribute(ENABLED)).booleanValue();
}
}
++providerCounter;
@ -990,31 +972,25 @@ public class ScannerConfigInfoFactory2 {
}
}
private void store(Element sc)/* throws CoreException */{
private void store(ICStorageElement sc)/* throws CoreException */{
// if (isDirty || force) {
// ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(project, true);
// Element sc = descriptor.getProjectData(SCANNER_CONFIG);
Document doc = sc.getOwnerDocument();
// Clear out all current children
Node child = sc.getFirstChild();
while (child != null) {
sc.removeChild(child);
child = sc.getFirstChild();
}
// Clear children
for (ICStorageElement child : sc.getChildren())
sc.removeChild(child);
Element autod = doc.createElement(SC_AUTODISCOVERY);
sc.appendChild(autod);
ICStorageElement autod = sc.createChild(SC_AUTODISCOVERY);
autod.setAttribute(ENABLED, Boolean.toString(autoDiscoveryEnabled));
autod.setAttribute(SELECTED_PROFILE_ID, selectedProfile);
autod.setAttribute(PROBLEM_REPORTING_ENABLED, Boolean.toString(problemReportingEnabled));
for (Iterator i = profileOptionsMap.keySet().iterator(); i.hasNext();) {
String profileId = (String) i.next();
Element profile = doc.createElement(PROFILE);
for (Iterator<String> i = profileOptionsMap.keySet().iterator(); i.hasNext();) {
String profileId = i.next();
ICStorageElement profile = sc.createChild(PROFILE);
profile.setAttribute(ID, profileId);
store(profile, (ProfileOptions) profileOptionsMap.get(profileId));
sc.appendChild(profile);
store(profile, profileOptionsMap.get(profileId));
}
isDirty = false;
@ -1027,32 +1003,28 @@ public class ScannerConfigInfoFactory2 {
* @param profile element
* @param profile options
*/
private void store(Element profile, ProfileOptions po) {
Element child, grandchild;
Document doc = profile.getOwnerDocument();
private void store(ICStorageElement profile, ProfileOptions po) {
ICStorageElement child, grandchild;
// buildOutputProvider element
child = doc.createElement(BUILD_OUTPUT_PROVIDER);
grandchild = doc.createElement(OPEN_ACTION);
child = profile.createChild(BUILD_OUTPUT_PROVIDER);
grandchild = child.createChild(OPEN_ACTION);
grandchild.setAttribute(ENABLED, Boolean.toString(po.buildOutputFileActionEnabled));
if(po.buildOutputFilePath != null)
grandchild.setAttribute(FILE_PATH, po.buildOutputFilePath);
child.appendChild(grandchild);
grandchild = doc.createElement(PARSER);
grandchild = child.createChild(PARSER);
grandchild.setAttribute(ENABLED, Boolean.toString(po.buildOutputParserEnabled));
child.appendChild(grandchild);
profile.appendChild(child);
// scannerInfoProvider elements
// get the list of providers from the profile configuration
// ScannerConfigProfile configuredProfile = ScannerConfigProfileManager.getInstance().
// getSCProfileConfiguration(selectedProfile);
// List providerIds = configuredProfile.getSIProviderIds();
List providerIds = new ArrayList(po.providerOptionsMap.keySet());
List<String> providerIds = new ArrayList<String>(po.providerOptionsMap.keySet());
for (int i = 0; i < providerIds.size(); ++i) {
String providerId = (String) providerIds.get(i);
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions) po.providerOptionsMap.get(providerId);
String providerId = providerIds.get(i);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
if (ppo != null) {
child = doc.createElement(SCANNER_INFO_PROVIDER);
child = profile.createChild(SCANNER_INFO_PROVIDER);
child.setAttribute(ID, providerId);
// action
@ -1061,7 +1033,7 @@ public class ScannerConfigInfoFactory2 {
String providerKind = ppo.providerKind;
if (providerKind.equals(ScannerConfigProfile.ScannerInfoProvider.RUN)) {
grandchild = doc.createElement(RUN_ACTION);
grandchild = child.createChild(RUN_ACTION);
grandchild.setAttribute(USE_DEFAULT, Boolean.toString(ppo.providerRunUseDefault));
if(ppo.providerRunCommand != null)
grandchild.setAttribute(COMMAND, ppo.providerRunCommand);
@ -1069,16 +1041,13 @@ public class ScannerConfigInfoFactory2 {
grandchild.setAttribute(ARGUMENTS, ppo.providerRunArguments);
}
else if (providerKind.equals(ScannerConfigProfile.ScannerInfoProvider.OPEN)) {
grandchild = doc.createElement(OPEN_ACTION);
grandchild = child.createChild(OPEN_ACTION);
if(ppo.providerOpenFilePath != null)
grandchild.setAttribute(FILE_PATH, ppo.providerOpenFilePath);
}
child.appendChild(grandchild);
// parser
grandchild = doc.createElement(PARSER);
grandchild = child.createChild(PARSER);
grandchild.setAttribute(ENABLED, Boolean.toString(ppo.providerOutputParserEnabled));
child.appendChild(grandchild);
profile.appendChild(child);
}
else {
// missing provider options - error
@ -1095,17 +1064,6 @@ public class ScannerConfigInfoFactory2 {
container.save(true);
isDirty = false;
}
// if (store()) {
// ICDescriptorOperation op = new ICDescriptorOperation() {
//
// public void execute(ICDescriptor descriptor, IProgressMonitor monitor) throws CoreException {
// descriptor.saveProjectData();
// }
//
// };
// CCorePlugin.getDefault().getCDescriptorManager().
// runDescriptorOperation(project, op, null);
// }
}
public InfoContext getContext(){
@ -1176,7 +1134,7 @@ public class ScannerConfigInfoFactory2 {
selectedProfile = prefs.getDefaultString(prefix + SCANNER_CONFIG_SELECTED_PROFILE_ID_SUFFIX);
}
List profileIds = ScannerConfigProfileManager.getInstance().getProfileIds(context);
profileOptionsMap = new LinkedHashMap(profileIds.size());
profileOptionsMap = new LinkedHashMap<String, ProfileOptions>(profileIds.size());
for (Iterator I = profileIds.iterator(); I.hasNext(); ) {
String profileId = (String) I.next();
ProfileOptions po = new ProfileOptions();
@ -1195,7 +1153,7 @@ public class ScannerConfigInfoFactory2 {
ScannerConfigProfile configuredProfile = ScannerConfigProfileManager.getInstance().
getSCProfileConfiguration(profileId);
List providerIds = configuredProfile.getSIProviderIds();
po.providerOptionsMap = new LinkedHashMap(providerIds.size());
po.providerOptionsMap = new LinkedHashMap<String, ProfileOptions.ProviderOptions>(providerIds.size());
for (int i = 0; i < providerIds.size(); ++i) {
String providerId = (String) providerIds.get(i);
ProfileOptions.ProviderOptions ppo = new ProfileOptions.ProviderOptions();
@ -1229,10 +1187,10 @@ public class ScannerConfigInfoFactory2 {
set(prefix + SCANNER_CONFIG_SELECTED_PROFILE_ID_SUFFIX, selectedProfile);
set(prefix + SCANNER_CONFIG_PROBLEM_REPORTING_ENABLED_SUFFIX, problemReportingEnabled);
List profileIds = new ArrayList(profileOptionsMap.keySet());
for (Iterator I = profileIds.iterator(); I.hasNext(); ) {
String profileId = (String) I.next();
ProfileOptions po = (ProfileOptions) profileOptionsMap.get(profileId);
List<String> profileIds = new ArrayList<String>(profileOptionsMap.keySet());
for (Iterator<String> I = profileIds.iterator(); I.hasNext(); ) {
String profileId = I.next();
ProfileOptions po = profileOptionsMap.get(profileId);
set(SCD + prefix + profileId + DOT + ENABLED, !useDefaults);
set(SCD + prefix + profileId + BUILD_OUTPUT_OPEN_ACTION_ENABLED, po.buildOutputFileActionEnabled);
@ -1244,8 +1202,7 @@ public class ScannerConfigInfoFactory2 {
List providerIds = configuredProfile.getSIProviderIds();
for (int i = 0; i < providerIds.size(); ++i) {
String providerId = (String) providerIds.get(i);
ProfileOptions.ProviderOptions ppo = (ProfileOptions.ProviderOptions)
po.providerOptionsMap.get(providerId);
ProfileOptions.ProviderOptions ppo = po.providerOptionsMap.get(providerId);
set(SCD + prefix + profileId + DOT + providerId + SI_PROVIDER_PARSER_ENABLED,
ppo.providerOutputParserEnabled);

View file

@ -17,6 +17,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.ui,
org.eclipse.ui.ide,
org.eclipse.cdt.core,
org.eclipse.cdt.managedbuilder.core
org.eclipse.cdt.managedbuilder.core,
org.eclipse.cdt.core.tests;bundle-version="5.0.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5

View file

@ -8,12 +8,14 @@
* Contributors:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.tests.suite;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.cdt.build.core.scannerconfig.tests.CfgScannerConfigProfileManagerTests;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.managedbuilder.core.tests.BuildDescriptionModelTests;
@ -32,28 +34,28 @@ import org.eclipse.cdt.managedbuilder.core.tests.MultiVersionSupportTests;
import org.eclipse.cdt.managedbuilder.core.tests.OptionEnablementTests;
import org.eclipse.cdt.managedbuilder.core.tests.PathConverterTest;
import org.eclipse.cdt.managedbuilder.core.tests.ResourceBuildCoreTests;
import org.eclipse.cdt.managedbuilder.templateengine.tests.AllTemplateEngineTests;
import org.eclipse.cdt.projectmodel.tests.BackwardCompatiblityTests;
import org.eclipse.cdt.projectmodel.tests.CProjectDescriptionSerializationTests;
import org.eclipse.cdt.projectmodel.tests.OptionStringListValueTests;
import org.eclipse.cdt.projectmodel.tests.ProjectModelTests;
/**
*
* Main TestSuite for all the managed build tests
*/
public class AllManagedBuildTests {
public static void main(String[] args) {
junit.textui.TestRunner.run(AllManagedBuildTests.suite());
}
public static Test suite() {
// May/2005 Turning off all indexing for now because the "original" indexer causes hangs...
CCorePlugin.getDefault().getPluginPreferences().setValue(CCorePlugin.PREF_INDEXER, IPDOMManager.ID_NO_INDEXER);
// We could enable this later...
//CCorePlugin.getDefault().getPluginPreferences().setValue(CCorePlugin.PREF_INDEXER, IPDOMManager.ID_FULL_INDEXER);
CCorePlugin.getDefault().getPluginPreferences().setValue(CCorePlugin.PREF_INDEXER, IPDOMManager.ID_FAST_INDEXER);
TestSuite suite = new TestSuite(
"Test for org.eclipse.cdt.managedbuild.core.tests");
TestSuite suite = new TestSuite("Test for org.eclipse.cdt.managedbuild.core.tests");
//$JUnit-BEGIN$
// TODO uncoment this
// build.core.scannerconfig.tests
suite.addTest(CfgScannerConfigProfileManagerTests.suite());
// managedbuilder.core.tests
suite.addTest(ManagedBuildCoreTests20.suite());
suite.addTest(ManagedBuildCoreTests.suite());
suite.addTest(ManagedProjectUpdateTests.suite());
@ -68,13 +70,17 @@ public class AllManagedBuildTests {
suite.addTest(MultiVersionSupportTests.suite());
suite.addTest(OptionEnablementTests.suite());
suite.addTest(ManagedBuildDependencyCalculatorTests.suite());
suite.addTest(BuildDescriptionModelTests.suite());
suite.addTest(PathConverterTest.suite());
suite.addTest(ProjectModelTests.suite());
suite.addTest(OptionStringListValueTests.suite());
// managedbuilder.templateengine.tests
suite.addTest(AllTemplateEngineTests.suite());
// projectmodel.tests
suite.addTest(BackwardCompatiblityTests.suite());
suite.addTest(CProjectDescriptionSerializationTests.suite());
suite.addTest(OptionStringListValueTests.suite());
suite.addTest(ProjectModelTests.suite());
//$JUnit-END$
return suite;
}

View file

@ -0,0 +1,117 @@
package org.eclipse.cdt.build.core.scannerconfig.tests;
import java.util.Map;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.cdt.build.core.scannerconfig.CfgInfoContext;
import org.eclipse.cdt.build.core.scannerconfig.ICfgScannerConfigBuilderInfo2Set;
import org.eclipse.cdt.build.internal.core.scannerconfig2.CfgScannerConfigProfileManager;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.testplugin.ManagedBuildTestHelper;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
public class CfgScannerConfigProfileManagerTests extends BaseTestCase {
IProject fProject;
public static Test suite() {
TestSuite suite = new TestSuite(CfgScannerConfigProfileManagerTests.class.getName());
suite.addTestSuite(CfgScannerConfigProfileManagerTests.class);
return suite;
}
@Override
protected void setUp() throws Exception {
fProject = ManagedBuildTestHelper.createProject("CfgScannerConfigProfileManagerProj",
"cdt.managedbuild.target.gnu.exe");
ManagedBuildTestHelper.addManagedBuildNature(fProject);
}
@Override
protected void tearDown() throws Exception {
ManagedBuildTestHelper.removeProject(fProject.getName());
}
/**
* Basic testing of Config based ScannerConfigProfile management.
*
* This test runs through some of the funcationality used by the DiscoveryTab
* @throws CoreException
*/
public void testBasicCfgScannerConfigProfileChanges() throws CoreException {
ICProjectDescription prjDesc = CoreModel.getDefault().getProjectDescription(fProject);
ICConfigurationDescription[] cfgDescs = prjDesc.getConfigurations();
assertTrue(cfgDescs.length > 0);
IConfiguration cfg0 = ManagedBuildManager.getConfigurationForDescription(cfgDescs[0]);
ICfgScannerConfigBuilderInfo2Set scbis = CfgScannerConfigProfileManager.getCfgScannerConfigBuildInfo(cfg0);
// Test changing ICfgScannerConfigBuilderInfo2Set settings
boolean resCfgTypeDiscovery = scbis.isPerRcTypeDiscovery();
scbis.setPerRcTypeDiscovery(!resCfgTypeDiscovery);
// Test changing settings on one of the ScannerConfigBuilderInfos
Map<CfgInfoContext, IScannerConfigBuilderInfo2> infoMap = scbis.getInfoMap();
CfgInfoContext cic = infoMap.entrySet().iterator().next().getKey();
IScannerConfigBuilderInfo2 scbi = infoMap.entrySet().iterator().next().getValue();
// Get all the settings and invert them
boolean autoDiscovery = scbi.isAutoDiscoveryEnabled();
scbi.setAutoDiscoveryEnabled(!autoDiscovery);
boolean problemReport = scbi.isProblemReportingEnabled();
scbi.setProblemReportingEnabled(!problemReport);
boolean buildOutputParser = scbi.isBuildOutputParserEnabled();
scbi.setBuildOutputParserEnabled(!buildOutputParser);
boolean buildOutputFileAction = scbi.isBuildOutputFileActionEnabled();
scbi.setBuildOutputFileActionEnabled(!buildOutputFileAction);
String buildOutputFilePath = scbi.getBuildOutputFilePath();
scbi.setBuildOutputFilePath("dummyFile");
// Persist the changes
scbis.applyInfo(cic, scbi);
// Save the project description
CoreModel.getDefault().setProjectDescription(fProject, prjDesc);
fProject.close(null);
fProject.open(null);
// Check that the changes have persisted
prjDesc = CoreModel.getDefault().getProjectDescription(fProject);
cfg0 = ManagedBuildManager.getConfigurationForDescription(prjDesc.getConfigurations()[0]);
scbis = CfgScannerConfigProfileManager.getCfgScannerConfigBuildInfo(cfg0);
assertTrue(scbis.isPerRcTypeDiscovery() != resCfgTypeDiscovery);
scbi = scbis.getInfo(cic);
// Check that the changes have persisted
Assert.isTrue(autoDiscovery != scbi.isAutoDiscoveryEnabled());
Assert.isTrue(problemReport != scbi.isProblemReportingEnabled());
Assert.isTrue(buildOutputParser != scbi.isBuildOutputParserEnabled());
Assert.isTrue(buildOutputFileAction != scbi.isBuildOutputFileActionEnabled());
Assert.isTrue("dummyFile".equals(scbi.getBuildOutputFilePath()));
// Test restore defaults
scbis.applyInfo(cic, null);
// Save the project description
CoreModel.getDefault().setProjectDescription(fProject, prjDesc);
fProject.close(null);
fProject.open(null);
// Check settings are back to original
prjDesc = CoreModel.getDefault().getProjectDescription(fProject);
cfg0 = ManagedBuildManager.getConfigurationForDescription(prjDesc.getConfigurations()[0]);
scbis = CfgScannerConfigProfileManager.getCfgScannerConfigBuildInfo(cfg0);
scbi = scbis.getInfo(cic);
Assert.isTrue(autoDiscovery == scbi.isAutoDiscoveryEnabled());
Assert.isTrue(problemReport == scbi.isProblemReportingEnabled());
Assert.isTrue(buildOutputParser == scbi.isBuildOutputParserEnabled());
Assert.isTrue(buildOutputFileAction == scbi.isBuildOutputFileActionEnabled());
Assert.isTrue(buildOutputFilePath.equals(buildOutputFilePath));
}
}

View file

@ -15,10 +15,13 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.make.core.MakeCorePlugin;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.core.IProjectType;
@ -32,6 +35,8 @@ import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
/**
* Creates a project in a loop and checks that it is created with appropriate number
* of build configurations
@ -139,4 +144,66 @@ public class CProjectDescriptionSerializationTests extends TestCase {
}
}
}
/**
* This test is intended to check persistentProperties after a project is created.
* @throws Exception
*/
public void testPersistentProperties() throws Exception {
CoreModel coreModel = CoreModel.getDefault();
ICProjectDescriptionManager mngr = coreModel.getProjectDescriptionManager();
String pluginProjectTypeId = "cdt.managedbuild.target.gnu.cygwin.exe";
final String projectName = "testPersistentProperties";
{
// Create model project and accompanied descriptions
IProject project = BuildSystemTestHelper.createProject(projectName);
ICProjectDescription des = coreModel.createProjectDescription(project, false);
Assert.assertNotNull("createDescription returned null!", des);
{
ManagedBuildInfo info = ManagedBuildManager.createBuildInfo(project);
IProjectType type = ManagedBuildManager.getProjectType(pluginProjectTypeId);
Assert.assertNotNull("project type not found", type);
ManagedProject mProj = new ManagedProject(project, type);
info.setManagedProject(mProj);
IConfiguration cfgs[] = type.getConfigurations();
Assert.assertNotNull("configurations not found", cfgs);
Assert.assertTrue("no configurations found in the project type",cfgs.length>0);
for (IConfiguration configuration : cfgs) {
String id = ManagedBuildManager.calculateChildId(configuration.getId(), null);
Configuration config = new Configuration(mProj, (Configuration)configuration, id, false, true, false);
CConfigurationData data = config.getConfigurationData();
Assert.assertNotNull("data is null for created configuration", data);
ICConfigurationDescription cfgDes = des.createConfiguration(ManagedBuildManager.CFG_DATA_PROVIDER_ID, data);
}
Assert.assertEquals(2, des.getConfigurations().length);
}
coreModel.setProjectDescription(project, des);
Assert.assertEquals(project, des.getProject());
Thread.sleep(1000); // let scanner discovery participate
try {
QualifiedName pdomName = new QualifiedName(CCorePlugin.PLUGIN_ID, "pdomName");
QualifiedName activeCfg = new QualifiedName(CCorePlugin.PLUGIN_ID, "activeConfiguration");
QualifiedName settingCfg = new QualifiedName(CCorePlugin.PLUGIN_ID, "settingConfiguration");
QualifiedName discoveredScannerConfigFileName = new QualifiedName(MakeCorePlugin.PLUGIN_ID, "discoveredScannerConfigFileName");
assertTrue("pdomName", project.getPersistentProperties().containsKey(pdomName));
assertTrue("activeCfg", project.getPersistentProperties().containsKey(activeCfg));
assertTrue("discoveredScannerConfigFileName", project.getPersistentProperties().containsKey(discoveredScannerConfigFileName));
assertTrue("settingCfg", project.getPersistentProperties().containsKey(settingCfg));
} catch (CoreException e) {
Assert.fail(e.getMessage());
}
project.close(null);
}
}
}

View file

@ -59,8 +59,8 @@ import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICMultiConfigDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.settings.model.XmlStorageUtil;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.core.settings.model.util.XmlStorageElement;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildProperty;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyManager;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentBuildPathsChangeListener;
@ -2153,7 +2153,7 @@ public class ManagedBuildManager extends AbstractCExtension {
Node node = nodes.item(0);
// Create the internal representation of the project's MBS information
buildInfo = new ManagedBuildInfo(project, new XmlStorageElement((Element)node), true, fileVersion);
buildInfo = new ManagedBuildInfo(project, XmlStorageUtil.createCStorageTree((Element)node), true, fileVersion);
if (fileVersion != null) {
// buildInfo.setVersion(fileVersion);
PluginVersionIdentifier version = new PluginVersionIdentifier(fileVersion);

View file

@ -29,7 +29,7 @@ import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.WriteAccessException;
import org.eclipse.cdt.core.settings.model.util.XmlStorageElement;
import org.eclipse.cdt.core.settings.model.XmlStorageUtil;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.IBuilder;
@ -743,7 +743,7 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo {
if(managedProject != null){
Element projElement = doc.createElement(IManagedProject.MANAGED_PROJECT_ELEMENT_NAME);
element.appendChild(projElement);
((ManagedProject)managedProject).serialize(new XmlStorageElement(projElement), true);
((ManagedProject)managedProject).serialize(XmlStorageUtil.createCStorageTree(projElement), true);
}
else{
Iterator iter = getTargets().listIterator();

View file

@ -7,6 +7,7 @@
*
* Contributors:
* Intel Corporation - initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.internal.core;
@ -17,10 +18,11 @@ import java.util.List;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.WriteAccessException;
import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement;
import org.eclipse.core.runtime.CoreException;
public class ManagedConfigStorageElement implements ICStorageElement {
private IManagedConfigElement fElement;
private List fChildList;
private List<IManagedConfigElement> fChildList;
private ManagedConfigStorageElement fParent;
public ManagedConfigStorageElement(IManagedConfigElement el){
this(el, null);
@ -42,21 +44,37 @@ public class ManagedConfigStorageElement implements ICStorageElement {
public String getAttribute(String name) {
return fElement.getAttribute(name);
}
public boolean hasAttribute(String name) {
return fElement.getAttribute(name) != null;
}
public ICStorageElement[] getChildren() {
List list = getChildList(true);
return (ManagedConfigStorageElement[])list.toArray(new ManagedConfigStorageElement[list.size()]);
List<IManagedConfigElement> list = getChildList(true);
return list.toArray(new ManagedConfigStorageElement[list.size()]);
}
private List getChildList(boolean create){
private List<IManagedConfigElement> getChildList(boolean create){
if(fChildList == null && create){
IManagedConfigElement children[] = fElement.getChildren();
fChildList = new ArrayList(children.length);
fChildList = new ArrayList<IManagedConfigElement>(children.length);
fChildList.addAll(Arrays.asList(children));
}
return fChildList;
}
public ICStorageElement[] getChildrenByName(String name) {
List<ICStorageElement> children = new ArrayList<ICStorageElement>();
for (ICStorageElement child : getChildren())
if (name.equals(child.getName()))
children.add(child);
return children.toArray(new ICStorageElement[children.size()]);
}
public boolean hasChildren() {
return getChildList(true).isEmpty();
}
public String getName() {
return fElement.getName();
@ -94,4 +112,12 @@ public class ManagedConfigStorageElement implements ICStorageElement {
public String[] getAttributeNames() {
throw new UnsupportedOperationException();
}
public ICStorageElement createCopy() throws UnsupportedOperationException, CoreException {
throw new UnsupportedOperationException();
}
public boolean equals(ICStorageElement other) {
throw new UnsupportedOperationException();
}
}

View file

@ -7,6 +7,7 @@
*
* Contributors:
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.internal.core;
@ -18,36 +19,37 @@ import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.core.runtime.CoreException;
public class MapStorageElement implements ICStorageElement {
private HashMap fMap;
private HashMap<String, String> fMap;
private String fName;
private MapStorageElement fParent;
private static final String CHILDREN_KEY = "?children?"; //$NON-NLS-1$
private static final String NAME_KEY = "?name?"; //$NON-NLS-1$
private static final String VALUE_KEY = "?value?"; //$NON-NLS-1$
private List fChildren = new ArrayList();
private List<MapStorageElement> fChildren = new ArrayList<MapStorageElement>();
private String fValue;
public MapStorageElement(String name, MapStorageElement parent){
fName = name;
fParent = parent;
fMap = new HashMap();
fMap = new HashMap<String, String>();
}
public MapStorageElement(Map map, MapStorageElement parent){
fName = (String)map.get(getMapKey(NAME_KEY));
fValue = (String)map.get(getMapKey(VALUE_KEY));
fMap = new HashMap(map);
public MapStorageElement(Map<String, String> map, MapStorageElement parent){
fName = map.get(getMapKey(NAME_KEY));
fValue = map.get(getMapKey(VALUE_KEY));
fMap = new HashMap<String, String>(map);
fParent = parent;
String children = (String)map.get(getMapKey(CHILDREN_KEY));
String children = map.get(getMapKey(CHILDREN_KEY));
if(children != null){
List childrenStrList = decodeList(children);
List<String> childrenStrList = decodeList(children);
int size = childrenStrList.size();
if(size != 0){
for(int i = 0; i < size; i++){
Map childMap = decodeMap((String)childrenStrList.get(i));
Map<String, String> childMap = decodeMap(childrenStrList.get(i));
MapStorageElement child = createChildElement(childMap);
fChildren.add(child);
}
@ -55,7 +57,7 @@ public class MapStorageElement implements ICStorageElement {
}
}
protected MapStorageElement createChildElement(Map childMap){
protected MapStorageElement createChildElement(Map<String, String> childMap){
return new MapStorageElement(childMap, this);
}
@ -63,8 +65,8 @@ public class MapStorageElement implements ICStorageElement {
return name;
}
public Map toStringMap(){
Map map = (Map)fMap.clone();
public Map<String, String> toStringMap(){
Map<String, String> map = (Map<String, String>)fMap.clone();
if(fName != null)
map.put(getMapKey(NAME_KEY), fName);
else
@ -77,10 +79,10 @@ public class MapStorageElement implements ICStorageElement {
int size = fChildren.size();
if(size != 0){
List childrenStrList = new ArrayList(size);
List<String> childrenStrList = new ArrayList<String>(size);
for(int i = 0; i < size; i++){
MapStorageElement child = (MapStorageElement)fChildren.get(i);
Map childStrMap = child.toStringMap();
MapStorageElement child = fChildren.get(i);
Map<String, String> childStrMap = child.toStringMap();
String str = encodeMap(childStrMap);
childrenStrList.add(str);
}
@ -118,9 +120,25 @@ public class MapStorageElement implements ICStorageElement {
return (String)o;
return null;
}
public boolean hasAttribute(String name) {
return fMap.containsKey(getMapKey(name));
}
public ICStorageElement[] getChildren() {
return (MapStorageElement[])fChildren.toArray(new MapStorageElement[fChildren.size()]);
return fChildren.toArray(new MapStorageElement[fChildren.size()]);
}
public ICStorageElement[] getChildrenByName(String name) {
List<ICStorageElement> children = new ArrayList<ICStorageElement>();
for (ICStorageElement child : fChildren)
if (name.equals(child.getName()))
children.add(child);
return new ICStorageElement[children.size()];
}
public boolean hasChildren() {
return !fChildren.isEmpty();
}
public String getName() {
@ -150,13 +168,13 @@ public class MapStorageElement implements ICStorageElement {
fMap.put(getMapKey(name), value);
}
public static Map decodeMap(String value) {
List list = decodeList(value);
Map map = new HashMap();
public static Map<String, String> decodeMap(String value) {
List<String> list = decodeList(value);
Map<String, String> map = new HashMap<String, String>();
char escapeChar = '\\';
for(int i = 0; i < list.size(); i++){
StringBuffer line = new StringBuffer((String)list.get(i));
StringBuffer line = new StringBuffer(list.get(i));
int lndx = 0;
while (lndx < line.length()) {
if (line.charAt(lndx) == '=') {
@ -176,8 +194,8 @@ public class MapStorageElement implements ICStorageElement {
}
public static List decodeList(String value) {
List list = new ArrayList();
public static List<String> decodeList(String value) {
List<String> list = new ArrayList<String>();
if (value != null) {
StringBuffer envStr = new StringBuffer(value);
String escapeChars = "|\\"; //$NON-NLS-1$
@ -222,8 +240,8 @@ public class MapStorageElement implements ICStorageElement {
return list;
}
public static String encodeMap(Map values) {
List list = new ArrayList();
public static String encodeMap(Map<String, String> values) {
List<String> list = new ArrayList<String>();
Iterator entries = values.entrySet().iterator();
StringBuffer str = new StringBuffer();
while (entries.hasNext()) {
@ -237,11 +255,11 @@ public class MapStorageElement implements ICStorageElement {
return encodeList(list);
}
public static String encodeList(List values) {
public static String encodeList(List<String> values) {
StringBuffer str = new StringBuffer();
Iterator entries = values.iterator();
Iterator<String> entries = values.iterator();
while (entries.hasNext()) {
String entry = (String)entries.next();
String entry = entries.next();
str.append(escapeChars(entry, "|\\", '\\')); //$NON-NLS-1$
// str.append("="); //$NON-NLS-1$
// str.append(escapeChars((String)entry.getValue(), "|\\", '\\')); //$NON-NLS-1$
@ -276,7 +294,7 @@ public class MapStorageElement implements ICStorageElement {
}
public String[] getAttributeNames() {
List list = new ArrayList(fMap.size());
List<String> list = new ArrayList<String>(fMap.size());
for(Iterator iter = fMap.entrySet().iterator(); iter.hasNext();){
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
@ -285,6 +303,14 @@ public class MapStorageElement implements ICStorageElement {
}
}
return (String[])list.toArray(new String[list.size()]);
return list.toArray(new String[list.size()]);
}
public ICStorageElement createCopy() throws UnsupportedOperationException, CoreException {
throw new UnsupportedOperationException();
}
public boolean equals(ICStorageElement other) {
throw new UnsupportedOperationException();
}
}

View file

@ -108,6 +108,8 @@ public class ConfigurationDataProvider extends CConfigurationDataProvider implem
ICStorageElement cfgElemen = rootElement.createChild(IConfiguration.CONFIGURATION_ELEMENT_NAME);
Configuration cfg = (Configuration)appliedCfg.getConfiguration();
Builder b = (Builder)cfg.getEditableBuilder();
// Need to ensure that build macro supplier can get the description for this configuration during the write...
cfg.setConfigurationDescription(des);
if(b != null && b.isManagedBuildOn() && b.getBuildPathAttribute(false) == null){
String bPath = b.getDefaultBuildPath();
b.setBuildPathAttribute(bPath);

View file

@ -17,7 +17,7 @@ import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector;
import org.eclipse.core.resources.IProject;
/**
* Interface that a colelctor of compiler information must implement.
* Interface that a collector of compiler information must implement.
* @since 2.0
*/
public interface IManagedScannerInfoCollector extends IScannerInfoCollector {
@ -31,7 +31,7 @@ public interface IManagedScannerInfoCollector extends IScannerInfoCollector {
*
* @return a <code>Map</code> of defined symbols and values
*/
public Map getDefinedSymbols();
public Map<String, String> getDefinedSymbols();
/**

View file

@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.newmake.core;
@ -26,6 +27,7 @@ import org.eclipse.cdt.core.model.IMacroEntry;
import org.eclipse.cdt.core.model.IPathEntry;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.resources.ScannerProvider;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@ -35,8 +37,6 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* @deprecated @author DInglis
@ -114,18 +114,17 @@ public class MakeScannerProvider extends ScannerProvider {
*/
private MakeScannerInfo loadScannerInfo(IProject project) throws CoreException {
ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(project);
Node child = descriptor.getProjectData(CDESCRIPTOR_ID).getFirstChild();
ICStorageElement root = descriptor.getProjectStorageElement(CDESCRIPTOR_ID);
ArrayList includes = new ArrayList();
ArrayList symbols = new ArrayList();
while (child != null) {
if (child.getNodeName().equals(INCLUDE_PATH)) {
for (ICStorageElement child : root.getChildren()) {
if (child.getName().equals(INCLUDE_PATH)) {
// Add the path to the property list
includes.add( ((Element)child).getAttribute(PATH));
} else if (child.getNodeName().equals(DEFINED_SYMBOL)) {
includes.add(child.getAttribute(PATH));
} else if (child.getName().equals(DEFINED_SYMBOL)) {
// Add the symbol to the symbol list
symbols.add( ((Element)child).getAttribute(SYMBOL));
symbols.add(child.getAttribute(SYMBOL));
}
child = child.getNextSibling();
}
MakeScannerInfo info = new MakeScannerInfo(project);
info.setIncludePaths((String[])includes.toArray(new String[includes.size()]));
@ -194,15 +193,11 @@ public class MakeScannerProvider extends ScannerProvider {
ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(project);
Element rootElement = descriptor.getProjectData(CDESCRIPTOR_ID);
ICStorageElement rootElement = descriptor.getProjectStorageElement(CDESCRIPTOR_ID);
// Clear out all current children
// Note: Probably would be a better idea to merge in the data
Node child = rootElement.getFirstChild();
while (child != null) {
rootElement.removeChild(child);
child = rootElement.getFirstChild();
}
rootElement.clear();
descriptor.saveProjectData();
migrateToCPathEntries(scannerInfo);

View file

@ -8,14 +8,20 @@
* Contributors:
* QNX Software Systems Ltd - initial API and implementation
* Anton Leherbauer (Wind River Systems)
* James Blackburn (Broadcom Corp.)
***********************************************************************/
package org.eclipse.cdt.core.cdescriptor.tests;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Method;
import junit.extensions.TestSetup;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.CCorePlugin;
@ -26,8 +32,12 @@ import org.eclipse.cdt.core.ICDescriptorListener;
import org.eclipse.cdt.core.ICDescriptorOperation;
import org.eclipse.cdt.core.ICExtensionReference;
import org.eclipse.cdt.core.ICOwnerInfo;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.internal.core.pdom.PDOMManager;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
@ -35,9 +45,7 @@ import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
* @author David
@ -45,12 +53,12 @@ import org.w3c.dom.NodeList;
* To change the template for this generated type comment go to
* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
*/
public class CDescriptorTests extends TestCase {
public class CDescriptorTests extends BaseTestCase {
static String projectId = CTestPlugin.PLUGIN_ID + ".TestProject";
static IProject fProject;
static CDescriptorListener listener = new CDescriptorListener();
static CDescriptorEvent fLastEvent;
static volatile CDescriptorEvent fLastEvent;
/**
* Constructor for CDescriptorTest.
@ -64,18 +72,11 @@ public class CDescriptorTests extends TestCase {
public static Test suite() {
TestSuite suite = new TestSuite(CDescriptorTests.class.getName());
suite.addTest(new CDescriptorTests("testDescriptorCreation"));
suite.addTest(new CDescriptorTests("testDescriptorOwner"));
suite.addTest(new CDescriptorTests("testExtensionCreation"));
suite.addTest(new CDescriptorTests("testExtensionGet"));
suite.addTest(new CDescriptorTests("testExtensionData"));
suite.addTest(new CDescriptorTests("testExtensionRemove"));
suite.addTest(new CDescriptorTests("testProjectDataCreate"));
suite.addTest(new CDescriptorTests("testProjectDataDelete"));
suite.addTest(new CDescriptorTests("testConcurrentDescriptorCreation"));
suite.addTest(new CDescriptorTests("testConcurrentDescriptorCreation2"));
suite.addTest(new CDescriptorTests("testDeadlockDuringProjectCreation"));
// Add all the tests in this class
for (Method m : CDescriptorTests.class.getMethods())
if (m.getName().startsWith("test"))
suite.addTest(new CDescriptorTests(m.getName()));
TestSetup wrapper = new TestSetup(suite) {
@Override
@ -91,7 +92,16 @@ public class CDescriptorTests extends TestCase {
};
return wrapper;
}
@Override
protected void setUp() throws Exception {
fProject.open(new NullProgressMonitor());
}
@Override
protected void tearDown() throws Exception {
}
private static void addNatureToProject(IProject proj, String natureId, IProgressMonitor monitor) throws CoreException {
IProjectDescription description = proj.getDescription();
String[] prevNatures = description.getNatureIds();
@ -155,44 +165,59 @@ public class CDescriptorTests extends TestCase {
Assert.assertEquals("*", desc.getPlatform());
}
public void testDescriptorOwner() throws Exception {
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
ICOwnerInfo owner = desc.getProjectOwner();
Assert.assertEquals(projectId, owner.getID());
Assert.assertEquals("*", owner.getPlatform());
Assert.assertEquals("C/C++ Test Project", owner.getName());
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185930
public void testConcurrentDescriptorCreation() throws Exception {
fProject.close(null);
fProject.open(null);
Thread t= new Thread() {
@Override
public void run() {
try {
CCorePlugin.getDefault().getCProjectDescription(fProject, true);
} catch (CoreException exc) {
for (int i = 0; i < 100 ; i++) {
fProject.close(null);
fProject.open(null);
Thread t= new Thread() {
public void run() {
try {
CCorePlugin.getDefault().getCProjectDescription(fProject, true);
} catch (CoreException exc) {
fail();
}
}
}
};
t.start();
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
t.join();
Element data = desc.getProjectData("testElement0");
data.appendChild(data.getOwnerDocument().createElement("test"));
desc.saveProjectData();
fLastEvent = null;
};
t.start();
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
t.join();
ICStorageElement data = desc.getProjectStorageElement("testElement0");
data.createChild("test");
desc.saveProjectData();
fLastEvent = null;
}
}
/*
* This tests concurrent descriptor modification inside of a ICDescriptor operation run
* with
* CConfigBasedDescriptorManager.runDescriptorOperation(IProject project, ICDescriptorOperation op, IProgressMonitor monitor)
*/
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185930
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=193503
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=196118
public void testConcurrentDescriptorCreation2() throws Exception {
public void testConcurrentDescriptorModification() throws Exception {
int lastLength = 0;
for (int i=0; i<200; ++i) {
for (int i=0; i<100; ++i) {
final int indexi = i;
PDOMManager pdomMgr= (PDOMManager)CCorePlugin.getIndexManager();
pdomMgr.shutdown();
fProject.close(null);
fProject.open(null);
pdomMgr.startup().schedule();
ICDescriptor desc= CCorePlugin.getDefault().getCProjectDescription(fProject, true);
final ICDescriptor fdesc= CCorePlugin.getDefault().getCProjectDescription(fProject, true);
if (lastLength == 0)
lastLength = countChildElements(desc.getProjectData("testElement"));
lastLength = fdesc.getProjectStorageElement("testElement").getChildren().length;
final Throwable[] exception= new Throwable[10];
Thread[] threads= new Thread[10];
for (int j = 0; j < 10; j++) {
@ -203,22 +228,15 @@ public class CDescriptorTests extends TestCase {
try {
ICDescriptorOperation operation= new ICDescriptorOperation() {
public void execute(ICDescriptor descriptor, IProgressMonitor monitor) throws CoreException {
assertFalse(descriptor.getConfigurationDescription().isReadOnly());
Element data = descriptor.getProjectData("testElement");
// assertFalse(descriptor.getConfigurationDescription().isReadOnly());
ICStorageElement data = fdesc.getProjectStorageElement("testElement");
String test = "test"+(indexi*10 + indexj);
data.appendChild(data.getOwnerDocument().createElement(test));
assertFalse(descriptor.getConfigurationDescription().isReadOnly());
// BUG196118 the model cached in memory doesn't reflect the contents of .cproject
//
// descriptor.saveProjectData() doesn't actually save despite what the API says
// see CConfigBasedDescriptor.fApplyOnChange
// ((CConfigBasedDescriptor)descriptor).apply(false);
data.createChild(test);
// assertFalse(descriptor.getConfigurationDescription().isReadOnly());
descriptor.saveProjectData();
// System.out.println("Saved " + test);
}};
CCorePlugin.getDefault().getCDescriptorManager().runDescriptorOperation(fProject, operation, null);
ICDescriptor descriptor = CCorePlugin.getDefault().getCDescriptorManager().getDescriptor(fProject);
// perform apply outside descriptor operation to avoid deadlock - http://bugs.eclipse.org/241288
descriptor.saveProjectData();
} catch (Throwable exc) {
exception[indexj]= exc;
exc.printStackTrace();
@ -234,8 +252,8 @@ public class CDescriptorTests extends TestCase {
}
assertNull("Exception occurred: "+exception[j], exception[j]);
}
desc= CCorePlugin.getDefault().getCProjectDescription(fProject, true);
int lengthAfter = countChildElements(desc.getProjectData("testElement"));
ICDescriptor desc= CCorePlugin.getDefault().getCProjectDescription(fProject, true);
int lengthAfter = desc.getProjectStorageElement("testElement").getChildren().length;
lastLength += threads.length; // Update last lengths to what we expect
assertEquals("Iteration count: " + i, lastLength, lengthAfter);
@ -243,43 +261,92 @@ public class CDescriptorTests extends TestCase {
}
}
/**
* Count the number of Node.ELEMENT_NODE elements which are a
* direct descendent of the parent Element.
* Other nodes (e.g. Text) are ignored
* @param parent
* @return
/*
* This test should pass as two threads, operating on the
* different storage elements (outside of an operation) should be safe
*/
private int countChildElements(Element parent) {
int numElements = 0;
NodeList childNodes = parent.getChildNodes();
for (int k = 0 ; k < childNodes.getLength() ; k++)
if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE)
numElements ++;
return numElements;
}
public void testDeadlockDuringProjectCreation() throws Exception {
for (int i=0; i < 10; ++i) {
oneTimeTearDown();
oneTimeSetUp();
public void testConcurrentDifferentStorageElementModification() throws Exception {
for (int i=0; i < 100; ++i) {
Thread t= new Thread() {
@Override
public void run() {
try {
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
Element data = desc.getProjectData("testElement0");
data.appendChild(data.getOwnerDocument().createElement("test"));
ICStorageElement data = desc.getProjectStorageElement("testElement4");
data.createChild("test");
desc.saveProjectData();
} catch (CoreException exc) {
fail(exc.getMessage());
}
}
};
t.start();
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
Element data = desc.getProjectData("testElement0");
data.appendChild(data.getOwnerDocument().createElement("test"));
ICStorageElement data = desc.getProjectStorageElement("testElement5");
data.createChild("test");
desc.saveProjectData();
t.join();
fLastEvent = null;
}
Assert.assertEquals(100, CCorePlugin.getDefault().getCProjectDescription(fProject, false).getProjectStorageElement("testElement4").getChildren().length);
Assert.assertEquals(100, CCorePlugin.getDefault().getCProjectDescription(fProject, false).getProjectStorageElement("testElement5").getChildren().length);
}
/*
* Test that (non-structural) changes to the storage element tree
* work as expected.
*/
public void testConcurrentSameStorageElementModification() throws Exception {
for (int i=0; i < 100; ++i) {
Thread t= new Thread() {
public void run() {
try {
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
ICStorageElement data = desc.getProjectStorageElement("testElement6");
data.createChild("test");
desc.saveProjectData();
} catch (CoreException exc) {
fail(exc.getMessage());
}
}
};
t.start();
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
ICStorageElement data = desc.getProjectStorageElement("testElement6");
data.createChild("test");
desc.saveProjectData();
t.join();
fLastEvent = null;
}
Assert.assertEquals(200, CCorePlugin.getDefault().getCProjectDescription(fProject, false).getProjectStorageElement("testElement6").getChildren().length);
}
/*
* Tests deadlock when accessing c project description concurrently from two threads
*/
public void testDeadlockDuringProjectCreation() throws Exception {
for (int i=0; i < 10; ++i) {
oneTimeTearDown();
oneTimeSetUp();
Thread t= new Thread() {
public void run() {
try {
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
ICStorageElement data = desc.getProjectStorageElement("testElement0");
data.createChild("test");
desc.saveProjectData();
} catch (Exception exc) {
}
}
};
t.start();
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
ICStorageElement data = desc.getProjectStorageElement("testElement0");
data.createChild("test");
desc.saveProjectData();
t.join();
@ -287,14 +354,6 @@ public class CDescriptorTests extends TestCase {
}
}
public void testDescriptorOwner() throws Exception {
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
ICOwnerInfo owner = desc.getProjectOwner();
Assert.assertEquals(projectId, owner.getID());
Assert.assertEquals("*", owner.getPlatform());
Assert.assertEquals("C/C++ Test Project", owner.getName());
}
public void testDescriptorConversion() {
}
@ -352,8 +411,8 @@ public class CDescriptorTests extends TestCase {
public void testProjectDataCreate() throws Exception {
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
Element data = desc.getProjectData("testElement");
data.appendChild(data.getOwnerDocument().createElement("test"));
ICStorageElement data = desc.getProjectStorageElement("testElement");
data.createChild("test");
desc.saveProjectData();
Assert.assertNotNull(fLastEvent);
@ -365,10 +424,10 @@ public class CDescriptorTests extends TestCase {
public void testProjectDataDelete() throws Exception {
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
Element data = desc.getProjectData("testElement");
NodeList list = data.getElementsByTagName("test");
Assert.assertEquals(1, list.getLength());
data.removeChild(data.getFirstChild());
ICStorageElement data = desc.getProjectStorageElement("testElement");
ICStorageElement[] list = data.getChildrenByName("test");
Assert.assertEquals(1, list.length);
data.removeChild(list[0]);
desc.saveProjectData();
Assert.assertNotNull(fLastEvent);
@ -378,4 +437,103 @@ public class CDescriptorTests extends TestCase {
fLastEvent = null;
}
public void testCProjectDescriptionDescriptorInteraction() throws Exception {
for (int i = 1; i < 100 ; i++) {
// Create a descriptor with some test data
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
ICStorageElement data = desc.getProjectStorageElement("descDescInteraction");
data.createChild("dataItem1");
// Get the CProjectDescription
ICProjectDescription projDesc = CCorePlugin.getDefault().getProjectDescription(fProject);
data = desc.getProjectStorageElement("descDescInteraction");
data.createChild("dataItem2");
data = desc.getProjectStorageElement("descDescInteraction2");
data.createChild("dataItem3");
// save the descriptor
desc.saveProjectData();
// save the project description
CCorePlugin.getDefault().setProjectDescription(fProject, projDesc);
fProject.close(null);
assertTrue(CCorePlugin.getDefault().getCProjectDescription(fProject, false) == null);
fProject.open(null);
// Check that the descriptor added data is still there
desc = CCorePlugin.getDefault().getCProjectDescription(fProject, false);
data = desc.getProjectStorageElement("descDescInteraction");
assertEquals(2 * i, data.getChildren().length);
data = desc.getProjectStorageElement("descDescInteraction2");
assertEquals(1 * i, data.getChildren().length);
}
}
public void testAccumulatingBlankLinesInProjectData() throws Exception {
ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
ICStorageElement data = desc.getProjectStorageElement("testElement");
data.createChild("test");
desc.saveProjectData();
fProject.close(null);
fProject.open(null);
String dotCProject1 = readDotCProjectFile(fProject);
long mtime1 = fProject.getFile(".cproject").getLocalTimeStamp();
desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
data = desc.getProjectStorageElement("testElement");
for (ICStorageElement child : data.getChildren()) {
data.removeChild(child);
}
data.createChild("test");
desc.saveProjectData();
String dotCProject2 = readDotCProjectFile(fProject);
long mtime2 = fProject.getFile(".cproject").getLocalTimeStamp();
assertEquals("Difference in .cproject file", dotCProject1, dotCProject2);
assertTrue(".cproject file has been written", mtime1 == mtime2);
// do it a second time - just to be sure
fProject.close(null);
fProject.open(null);
desc = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
data = desc.getProjectStorageElement("testElement");
for (ICStorageElement child : data.getChildren()) {
data.removeChild(child);
}
data.createChild("test");
desc.saveProjectData();
String dotCProject3 = readDotCProjectFile(fProject);
long mtime3 = fProject.getFile(".cproject").getLocalTimeStamp();
assertEquals("Difference in .cproject file", dotCProject2, dotCProject3);
assertTrue(".cproject file has been written", mtime2 == mtime3);
}
/**
* Read .cproject file.
*
* @param project
* @return content of .cproject file
* @throws CoreException
* @throws IOException
*/
private static String readDotCProjectFile(IProject project) throws CoreException, IOException {
IFile cProjectFile = project.getFile(".cproject");
InputStream in = cProjectFile.getContents();
try {
Reader reader = new InputStreamReader(in, "UTF-8");
StringBuilder sb = new StringBuilder();
char[] b = new char[4096];
int n;
while ((n = reader.read(b)) > 0) {
sb.append(b, 0, n);
}
return sb.toString();
} finally {
in.close();
}
}
}

View file

@ -29,7 +29,7 @@ public class AllCProjectDescriptionTests {
suite.addTest(ProjectCreationStateTests.suite());
suite.addTest(BackwardCompatibilityTests.suite());
suite.addTest(CProjectDescriptionBasicTests.suite());
suite.addTest(CProjectDescriptionStorageTests.suite());
return suite;
}
}

View file

@ -219,8 +219,7 @@ public class BackwardCompatibilityTests extends BaseTestCase {
private void doTestRm(IProject proj) throws CoreException{
final String DATA_ID = "testICDescriptorGetProjectData";
ICDescriptor dr = CCorePlugin.getDefault().getCProjectDescription(proj, false);
Element dataEl = dr.getProjectData(DATA_ID);
dataEl.getParentNode().removeChild(dataEl);
dr.removeProjectStorageElement(DATA_ID);
dr.saveProjectData();
}

View file

@ -10,8 +10,11 @@
*******************************************************************************/
package org.eclipse.cdt.core.settings.model;
import java.util.Map;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CProjectNature;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.model.CoreModel;
@ -189,6 +192,7 @@ public class CProjectDescriptionBasicTests extends BaseTestCase{
assertTrue(failed);
}
public void testBug242955() throws Exception {
CoreModel coreModel = CoreModel.getDefault();

View file

@ -0,0 +1,358 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.settings.model;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
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.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
/**
* Testsuite for the project description storage. This
* currently tests some of the features of the built-in
* XmlProjectDescriptionStorage(2)
*/
public class CProjectDescriptionStorageTests extends BaseTestCase {
/** CProject on which these tests are based */
ICProject cProj;
public static TestSuite suite() {
return suite(CProjectDescriptionStorageTests.class, "_");
}
// resource change listener that will listen for file changes interesting to the tests
OurResourceChangeListener resListener;
@Override
protected void setUp() throws Exception {
cProj = CProjectHelper.createNewStileCProject("CProjDescStorage", IPDOMManager.ID_FAST_INDEXER);
resListener = new OurResourceChangeListener();
ResourcesPlugin.getWorkspace().addResourceChangeListener(resListener);
}
@Override
protected void tearDown() throws Exception {
// Remover our resource change listener
ResourcesPlugin.getWorkspace().removeResourceChangeListener(resListener);
// Make the project files writable so they can be deleted...
cProj.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
cProj.getProject().getFile(".cproject").setReadOnly(false);
if (cProj.getProject().getFolder(".csettings").exists()) {
cProj.getProject().getFolder(".csettings").setReadOnly(false);
for (IResource child : cProj.getProject().getFolder(".csettings").members())
child.setReadOnly(false);
}
// Delete the project
CProjectHelper.delete(cProj);
}
/**
* Tests that external modifications to the CProjectDescription file are picked up
* @throws Exception
*/
public void testExternalCProjDescModification() throws Exception {
// Create auto-refresh Thread
Job refreshJob = new Job("Auto-Refresh") {
@Override
protected IStatus run(IProgressMonitor monitor) {
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
try {
ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
fail("Error during refresh: " + e.getMessage());
}
schedule(500);
return Status.OK_STATUS;
}
};
refreshJob.schedule();
// Backup the CProjectFile
final String initial = "initial";
final String testingStorage = "testingStorage";
final String testChildInStorage = "testChildInStorage";
// Backup the original storage file
backUpCProjectFile(initial);
IProject project = cProj.getProject();
ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(project, true);
projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, true).createChild(testChildInStorage);
CoreModel.getDefault().setProjectDescription(project, projDesc);
// backup this project_desc
backUpCProjectFile(testingStorage);
// Close and open project
project.close(null);
project.open(null);
// verify changes are in read-only description
projDesc = CoreModel.getDefault().getProjectDescription(project, false);
assertNotNull(projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, false));
project.refreshLocal(IResource.DEPTH_INFINITE, null);
// Restore from backup
resListener.reset();
resListener.addFileToWatch(cProj.getProject().getFile(".cproject").getFullPath());
restoreCProjectFile(initial);
resListener.waitForChange();
// Fetch what should be the initial project description
projDesc = CoreModel.getDefault().getProjectDescription(project, false);
assertNull(projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, false));
// Test XmlProjectDescriptionStorage2:
// Test that updating the contents of a storage module leads to a reload of the project description
// (In XmlProjectDescriptionStorage2 configuration storage modules are stored in different files...)
restoreCProjectFile(testingStorage);
project.close(null);
project.open(null);
// create testChildInStorage
projDesc = CoreModel.getDefault().getProjectDescription(project, true);
ICStorageElement[] children = projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, false).getChildrenByName(testChildInStorage);
assertTrue(children.length == 1);
projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, false).removeChild(children[0]);
CoreModel.getDefault().setProjectDescription(project, projDesc);
projDesc = CoreModel.getDefault().getProjectDescription(project, false);
assertTrue(projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, false).getChildrenByName(testChildInStorage).length == 0);
project.refreshLocal(IResource.DEPTH_INFINITE, null);
// Restore from backup
resListener.reset();
resListener.addFileToWatch(cProj.getProject().getFolder(".csettings").getFullPath());
restoreCProjectFile(testingStorage);
resListener.waitForChange();
// Check that the project description no longer contains the testChildInStorage
projDesc = CoreModel.getDefault().getProjectDescription(project, false);
assertTrue(projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, false).getChildrenByName(testChildInStorage).length == 1);
refreshJob.cancel();
}
/**
* Tests that a read-only project description file is picked up
* @throws Exception
*/
public void testReadOnlyProjectDescription() throws Exception {
makeDescriptionReadOnly();
IProject project = cProj.getProject();
ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(project, true);
projDesc.getDefaultSettingConfiguration().getStorage("Temp_testing_storage", true);
CoreModel.getDefault().setProjectDescription(project, projDesc);
project.close(null);
project.open(null);
projDesc = CoreModel.getDefault().getProjectDescription(project, false);
assertNotNull(projDesc.getDefaultSettingConfiguration().getStorage("Temp_testing_storage", false));
projDesc = CoreModel.getDefault().getProjectDescription(project, true);
makeDescriptionReadOnly();
projDesc.getDefaultSettingConfiguration().removeStorage("Temp_testing_storage");
CoreModel.getDefault().setProjectDescription(project, projDesc);
project.close(null);
project.open(null);
projDesc = CoreModel.getDefault().getProjectDescription(project, false);
assertNull(projDesc.getDefaultSettingConfiguration().getStorage("Temp_testing_storage", false));
}
/*
*
* Helper methods for external modifications
*
*/
/**
* makes the project description (as stored by the XmlProjectDescriptionStorage &
* XmlProjectDescriptionStorage2) read-only. Does this using java.io.File deliberately.
*/
private void makeDescriptionReadOnly() throws Exception {
File cproj = cProj.getProject().getFile(".cproject").getLocation().toFile();
if (!cproj.exists())
throw new FileNotFoundException();
cproj.setReadOnly();
// XmlProjectDescription2 stores settings in a .csettings directory, look for it
File csettDir = cProj.getProject().getFile(".csettings").getLocation().toFile();
if (csettDir.exists()) {
for (File child : csettDir.listFiles())
child.setReadOnly();
csettDir.setReadOnly();
}
}
/**
* Restore the file from the backup. Only does so if the contents of the file
* have changed (to prevent updating the modification stamp on the file...)
* @param uniqueKey
*/
private void restoreCProjectFile(String uniqueKey) {
File cproj = cProj.getProject().getFile(".cproject").getLocation().toFile();
File cprojback = cProj.getProject().getFile(".cproject_" + uniqueKey).getLocation().toFile();
if (diff(cprojback, cproj))
copyFile(cprojback, cproj);
File csettings = cProj.getProject().getFile(".csettings").getLocation().toFile();
File csettingsback = cProj.getProject().getFile(".csettings_" + uniqueKey).getLocation().toFile();
if (csettingsback.exists()) {
for (File f : csettingsback.listFiles()) {
File orig = new File(csettings, f.getName());
if (diff(f, orig))
copyFile(f, orig);
}
}
}
private void backUpCProjectFile(String uniqueKey) {
File cproj = cProj.getProject().getFile(".cproject").getLocation().toFile();
File cprojback = cProj.getProject().getFile(".cproject_" + uniqueKey).getLocation().toFile();
copyFile(cproj, cprojback);
// backup .csettings as well
File csettings = cProj.getProject().getFile(".csettings").getLocation().toFile();
if (csettings.exists() && csettings.isDirectory()) {
File csettingsback = cProj.getProject().getFile(".csettings_" + uniqueKey).getLocation().toFile();
if (!csettingsback.exists())
csettingsback.mkdir();
for (File f : csettings.listFiles())
copyFile(f, new File(csettingsback, f.getName()));
}
}
/**
* Return boolean indicating whether two files are different
* @param src1
* @param src2
* @return
*/
private boolean diff(File src1, File src2) {
if (!src1.exists() || !src2.exists())
return true;
FileInputStream in1 = null;
FileInputStream in2 = null;
try {
in1 = new FileInputStream(src1);
in2 = new FileInputStream(src2);
while (true) {
int byteRead1 = in1.read();
int byteRead2 = in2.read();
if (byteRead1 == -1 && byteRead2 == -1)
return false;
if (byteRead1 != byteRead2)
return true;
}
} catch (Exception e) {
fail("Exception diffingFiles: " + src1.getAbsolutePath() + " ; " + src2.getAbsolutePath());
return true;
} finally {
if (in1 != null)
try {in1.close();} catch (Exception e) {/*Don't care*/}
if (in2 != null)
try {in2.close();} catch (Exception e) {/*Don't care*/}
}
}
private void copyFile(File src, File dst) {
long initModificationTime = dst.lastModified();
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dst);
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1)
out.write(buffer, 0, bytesRead);
} catch (Exception e) {
fail("Exception copyingFile: " + src.getAbsolutePath() + " -> " + dst.getAbsolutePath());
} finally {
if (in != null)
try {in.close();} catch (Exception e) {/*Don't care*/}
if (out != null)
try {out.close();} catch (Exception e) {/*Don't care*/}
}
while (dst.lastModified() - initModificationTime == 0) {
// Unix stat doesn't return granularity < 1000ms :(
// If we don't sleep here, and the unit test goes too quickly, we're scuppered.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Don't care
}
dst.setLastModified(System.currentTimeMillis());
}
}
/**
* Our resource change listener which notified us when a file has been detected as changed
* Users add files to the files to watch. Reset the listener and block waiting for the change to
* be noticed.
*/
private static class OurResourceChangeListener implements IResourceChangeListener {
boolean changeDetected;
private Set<IPath> filesToWatch = new HashSet<IPath>();
public synchronized void resourceChanged(IResourceChangeEvent event) {
IResourceDelta delta = event.getDelta();
if (delta == null)
return;
for (IPath f : filesToWatch)
if (delta.findMember(f) != null) {
changeDetected = true;
notifyAll();
break;
}
}
public synchronized void addFileToWatch(IPath file) {
filesToWatch.add(file);
}
public synchronized void reset() {
changeDetected = false;
}
public synchronized void waitForChange() {
try {
if (!changeDetected)
wait(20000);
if (!changeDetected)
CCorePlugin.log("No Change detected in 20s!");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}

View file

@ -652,7 +652,7 @@ class MockConfig implements ICConfigurationDescription {
CConfigurationData data) throws WriteAccessException {}
public void setDescription(String des) throws WriteAccessException {}
public void setName(String name) throws WriteAccessException {}
public void setReferenceInfo(Map refs) throws WriteAccessException {}
public void setReferenceInfo(Map<String, String> refs) throws WriteAccessException {}
public void setSessionProperty(QualifiedName name, Object value) {}
public void setSourceEntries(ICSourceEntry[] entries) throws CoreException,
WriteAccessException {}
@ -663,8 +663,10 @@ class MockConfig implements ICConfigurationDescription {
public int getType() {return 0;}
public boolean isReadOnly() {return false;}
public boolean isValid() {return false;}
public ICStorageElement getStorage(String id, boolean create)
throws CoreException {
public ICStorageElement getStorage(String id, boolean create) throws CoreException {
return null;
}
public ICStorageElement importStorage(String id, ICStorageElement storage) {
return null;
}
@ -690,6 +692,8 @@ class MockConfig implements ICConfigurationDescription {
public CConfigurationStatus getConfigurationStatus() {
return CConfigurationStatus.CFG_STATUS_OK;
}
public void setReadOnly(boolean readOnly, boolean keepModify) {}
}
/*

View file

@ -14,6 +14,14 @@ import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionDelta;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.core.resources.IProject;
/**
* Events fired for the project delats.
*
* FIXME JBB: Should work out the difference between DATA_APPLIED AND APPLIED events
* current DATA_APPLIED occurs first and fNewDescription is modified. Need to clearly define
* the project description state transitions
*/
public final class CProjectDescriptionEvent {
public static final int LOADED = 1;
public static final int ABOUT_TO_APPLY = 1 << 1;
@ -23,7 +31,9 @@ public final class CProjectDescriptionEvent {
public static final int ALL = LOADED | ABOUT_TO_APPLY | APPLIED | COPY_CREATED | DATA_APPLIED;
private int fType;
/** A *writable* new description */
private ICProjectDescription fNewDescription;
/** The previous description should be read-only */
private ICProjectDescription fOldDescription;
private ICProjectDescription fAppliedDescription;
private ICDescriptionDelta fProjDelta;
@ -138,6 +148,10 @@ public final class CProjectDescriptionEvent {
return fOldDescription;
}
/**
* Return the new description which is writeable
* @return writable new description
*/
public ICProjectDescription getNewCProjectDescription() {
return fNewDescription;
}

View file

@ -10,8 +10,16 @@
*******************************************************************************/
package org.eclipse.cdt.core.settings.model;
import org.eclipse.cdt.core.ICExtensionReference;
import org.eclipse.core.runtime.CoreException;
/**
* Holds executable extension information in the
* project configuration. Like ICExtensionReference
* but has knowledge of its ICConfigurationDescription
*
* @see ICExtensionReference
*/
public interface ICConfigExtensionReference {
/**
* Return the extension point of this reference.
@ -40,7 +48,7 @@ public interface ICConfigExtensionReference {
/**
* Returns the project descriptor which this extension reference belongs to.
* @return the ICDescriptor
* @return the {@link ICConfigurationDescription}
*/
public ICConfigurationDescription getConfiguration();

View file

@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.cdt.core.settings.model;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
@ -127,7 +128,7 @@ public interface ICProjectDescription extends ICSettingContainer,
* the get/setSettionsProperty methods allow to associate the session properties with the given project description
* session properties are not persisted and are not restored on the next eclipse session
* the scope of project description session properties is the current project description,
* i.e. modifications to the properties are not applied untill the setProjectDescription call
* i.e. modifications to the properties are not applied until the setProjectDescription call
*
* @param name
*/
@ -137,7 +138,7 @@ public interface ICProjectDescription extends ICSettingContainer,
* the get/setSettionsProperty methods allow to associate the session properties with the given project description
* session properties are not persisted and are not restored on the next eclipse session
* the scope of project description session properties is the current project description,
* i.e. modifications to the properties are not applied untill the setProjectDescription call
* i.e. modifications to the properties are not applied until the setProjectDescription call
*
* @param name
* @param value

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007 Intel Corporation and others.
* Copyright (c) 2007, 2008 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
*
* Contributors:
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.core.settings.model;
@ -14,16 +15,58 @@ import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* This interface represents the manager of CDT Project descriptions.
*/
public interface ICProjectDescriptionManager {
/*
* setProjectDescription flags
*/
/** Flag indicating that the description should be serialized even
* if the ProjectDescription isn't marked as modified.
* @see ICProjectDescriptionManager#setProjectDescription(IProject, ICProjectDescription, int, IProgressMonitor) */
public static final int SET_FORCE = 1;
/** Flag indicating that the project description shouldn't be serialized.
* @see ICProjectDescriptionManager#setProjectDescription(IProject, ICProjectDescription, int, IProgressMonitor) */
public static final int SET_NO_SERIALIZE = 1 << 1;
/*
* getProjectDescription flags
*/
/** Flag indicating writable project description is required
* @see ICProjectDescriptionManager#getProjectDescription(IProject, int) */
public static final int GET_WRITABLE = 1 << 2;
/** Return the project description <b>only</b> if it's already loaded */
public static final int GET_IF_LOADDED = 1 << 3;
/**
* Flag indicating that a new empty ICProjectDescription should be created and returned
* (irrespective of whether one already exists)
*/
public static final int GET_EMPTY_PROJECT_DESCRIPTION = 1 << 4;
/**
* Flag indicating that the user has called createProjectDescription.
* i.e. a description should be returned irrespective of whether one already exists.
* If the project already has a description and !{@link #GET_EMPTY_PROJECT_DESCRIPTION}
* the existing description will be returned, otherwise a new description is returned
*/
public static final int GET_CREATE_DESCRIPTION = 1 << 5;
/**
* Flag indicating that the Project is in the process of being created (i.e.
* the user is working through the new project dialog...) This flag doesn't
* affect whether a description should or shouldn't be created.
*
* @see #GET_CREATE_DESCRIPTION
* @see ICProjectDescription#isCdtProjectCreating()
*/
public static final int PROJECT_CREATING = 1 << 6;
/**
* this method is a full equivalent to {@link #createProjectDescription(IProject, boolean, false)}
*
* This method is a full equivalent to: <br />
* - <code> createProjectDescription(IProject, boolean, false) </code> <br />
* - <code> getProjectDescription(IProject, GET_WRITABLE | loadIfExists ? 0 : GET_EMPTY_PROJECT_DESCRIPTION) </code> <br />
* and returns a writable project description which is either empty or a copy of the previous configuration description
* if loadIfExists == true.
* @see #createProjectDescription(IProject, boolean, boolean)
*/
ICProjectDescription createProjectDescription(IProject project, boolean loadIfExists) throws CoreException;
@ -44,8 +87,45 @@ public interface ICProjectDescriptionManager {
* @throws CoreException
*/
ICProjectDescription createProjectDescription(IProject project, boolean loadIfExists, boolean creating) throws CoreException;
/**
* This method is called to save/apply the project description
* the method should be called to apply changes made to the project description
* returned by the {@link #getProjectDescription(IProject, boolean)} or {@link #createProjectDescription(IProject, boolean)}
*
* Note that having persisted changes to the description, the passed in ICProjectDescription is read-only
* and shouldn't be used. If the user wishes to continue editing the ICProjectDescription they must ensure
* they getProjectDescription again.
*
* @param project
* @param des
* @throws CoreException
*
* @see {@link #getProjectDescription(IProject, boolean)}
* @see #createProjectDescription(IProject, boolean)
*/
void setProjectDescription(IProject project, ICProjectDescription des) throws CoreException;
/**
* This method is called to
* @param project
* @param des
* @param force
* @param monitor
* @throws CoreException
*/
void setProjectDescription(IProject project, ICProjectDescription des, boolean force, IProgressMonitor monitor) throws CoreException;
/**
*
* @param project
* @param des
* @param flags
* @param monitor
* @throws CoreException
*/
void setProjectDescription(IProject project, ICProjectDescription des, int flags, IProgressMonitor monitor) throws CoreException;
/**
* returns the project description associated with this project or null if the project does not contain the
* CDT data associated with it.
@ -61,24 +141,6 @@ public interface ICProjectDescriptionManager {
* @see #getProjectDescription(IProject, boolean)
*/
ICProjectDescription getProjectDescription(IProject project);
/**
* this method is called to save/apply the project description
* the method should be called to apply changes made to the project description
* returned by the {@link #getProjectDescription(IProject, boolean)} or {@link #createProjectDescription(IProject, boolean)}
*
* @param project
* @param des
* @throws CoreException
*
* @see {@link #getProjectDescription(IProject, boolean)}
* @see #createProjectDescription(IProject, boolean)
*/
void setProjectDescription(IProject project, ICProjectDescription des) throws CoreException;
void setProjectDescription(IProject project, ICProjectDescription des, boolean force, IProgressMonitor monitor) throws CoreException;
void setProjectDescription(IProject project, ICProjectDescription des, int flags, IProgressMonitor monitor) throws CoreException;
/**
* returns the project description associated with this project or null if the project does not contain the
@ -94,12 +156,12 @@ public interface ICProjectDescriptionManager {
* All set* calls to the read-only description result in the {@link WriteAccessException}
*
* When the writable description is requested, the description copy is created.
* Changes to this description will not be reflected/used by the core and Build System untill the
* Changes to this description will not be reflected/used by the core and Build System until the
* {@link #setProjectDescription(IProject, ICProjectDescription)} is called
*
* Each getProjectDescription(project, true) returns a new copy of the project description
*
* The writable description uses the cached data untill the first set call
* The writable description uses the cached data until the first set call
* after that the description communicates directly to the Build System
* i.e. the implementer of the org.eclipse.cdt.core.CConfigurationDataProvider extension
* This ensures the Core<->Build System settings integrity
@ -108,12 +170,18 @@ public interface ICProjectDescriptionManager {
* CDT data associated with it.
*/
ICProjectDescription getProjectDescription(IProject project, boolean write);
/**
* @see ICProjectDescriptionManager#createProjectDescription(IProject, boolean)
* @param project
* @param flags
* @return
*/
ICProjectDescription getProjectDescription(IProject project, int flags);
/**
* forces the cached data of the specified projects to be re-calculated.
* if the <code>projects</code> argument is <code>null</code> al projects
* forces the cached data of the specified projects to be re-loaded.
* if the <code>projects</code> argument is <code>null</code> all projects
* within the workspace are updated
*
* @param projects
@ -136,8 +204,25 @@ public interface ICProjectDescriptionManager {
*/
boolean isNewStyleProject(ICProjectDescription des);
/**
* Register a listener for changes on the set of known ICProjectDescriptions for the specified set
* of events
*
* @param listener
* @param eventTypes see the eventTypes in {@link CProjectDescriptionEvent}
* @see CProjectDescriptionEvent#ABOUT_TO_APPLY
* @see CProjectDescriptionEvent#APPLIED
* @see CProjectDescriptionEvent#COPY_CREATED
* @see CProjectDescriptionEvent#DATA_APPLIED
* @see CProjectDescriptionEvent#LOADED
* @see CProjectDescriptionEvent#ALL
*/
void addCProjectDescriptionListener(ICProjectDescriptionListener listener, int eventTypes);
/**
* Remove the listener from the set of ICProjecctDescriptionListeners
* @param listener
*/
void removeCProjectDescriptionListener(ICProjectDescriptionListener listener);
/**

View file

@ -7,30 +7,48 @@
*
* Contributors:
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.core.settings.model;
import java.util.Map;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationDataProvider;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* this interface represents the settings storage that can be used for storing
* data in the tree-like format of name-value holder elements
*
* This interface represents the settings storage that can be used as the root
* of a settings tree of name-attribute-value holder elements ({@link ICStorageElement}s).
* <br /><br />
* In real terms this is a specialised node in the project description tree. It is specialised
* in that it can only contain ICStorageElements as children and has no associated attributes or
* value. The Xml model implements this as an element called 'storageModule' which contains
* other arbitrary Xml ICStorageElements.
* <br /><br />
* Both {@link ICProjectDescription} and {@link ICConfigurationDescription} implement this
* interface thus providing the capabilities to store custom project-wide and configuration-specific
* data in the storage file (.cproject)
*
* These capabilities could be used, e.g. by the Build System
* (org.eclipse.cdt.core.CConfigurationDataProvider extension implementer)
* for loadding/storing data on the {@link CConfigurationDataProvider#loadConfiguration(ICConfigurationDescription)}
* and {@link CConfigurationDataProvider#applyConfiguration(ICConfigurationDescription, org.eclipse.cdt.core.settings.model.extension.CConfigurationData)}
* requests
* data in the storage file
* <br /><br />
* The format of the storage file is left up to the implementor. It may be an XML file
* (.cproject) a relational database (.cprojectdb) or any other format of the extenders choosing.
* <br /><br />
* These capabilities are used by the build system for persisting build configuration data
* as well as by the CoreModel {@link ICDescriptor} storage trees. See
* {@link CConfigurationDataProvider#loadConfiguration(ICConfigurationDescription, IProgressMonitor)}
* and {@link CConfigurationDataProvider#applyConfiguration(ICConfigurationDescription, ICConfigurationDescription, CConfigurationData, IProgressMonitor)}
*
* @see ICStorageElement
* @see ICProjectDescription
* @see ICConfigurationDescription
* @see ICDescriptor
*/
public interface ICSettingsStorage {
/**
* returns the storage of the specified id
* @param id any custom string value uniquely representing the storage
* @param id any custom string value uniquely representing the storage
* @return {@link ICStorageElement} if the settings storage does not contain the information of
* the specified id an empty storage is created and returned
* @throws CoreException
@ -39,13 +57,50 @@ public interface ICSettingsStorage {
*/
ICStorageElement getStorage(String id, boolean create) throws CoreException;
// /**
// *
// * @param id any custom string value uniquely representing the storage
// * @return true if the setting storage contains storage of the specified id and false - otherwise
// * @throws CoreException
// */
// boolean containsStorage(String id) throws CoreException;
/**
* Return a Map of StorageID -> ICStorageElement
* @return
*/
// Map<String, ICStorageElement> getStorages();
/**
* Remove the storage module with the given ID from this ICSettingsStorage
* @param id
* @throws CoreException
*/
void removeStorage(String id) throws CoreException;
/**
* Import an existing ICStorageElement storage module into the ICSettingsStorage
* Returns a handle on the newly imported ICSettingsStorage
*
* NB Storage IDs are unique in an ICSettingsStorage. Importing a storage
* will replace any other storage with equivalent id
* @param id name of the storage to be imported
* @param el ICStorageElement to be imported
* @return ICStorageElement representing the imported storage
* @throws UnsupportedOperationException
*/
public ICStorageElement importStorage(String id, ICStorageElement el) throws UnsupportedOperationException, CoreException;
/**
* Returns whether any non-persisted changes exist in this tree
* @return boolean indicating whether any elements in this tree have been modified
*/
public boolean isModified();
/**
* Return whether this Settings Storage is currently read only
* @return whether this storage is readonly
*/
public boolean isReadOnly();
/**
* Mark this Settings Storage as read only. If keepModify is set
* then modified flag will not be reset
* @param readOnly
* @param keepModify
*/
void setReadOnly(boolean readOnly, boolean keepModify);
}

View file

@ -7,49 +7,174 @@
*
* Contributors:
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.core.settings.model;
import org.eclipse.core.runtime.CoreException;
/**
*
* this interface represents the abstract storage that can be used for storing
* data in the tree-like format of name-value holder elements
* This interface represents an generic element in a storage tree. These trees are rooted at
* @link{ICSettingsStorage}Elements.
*
* This abstract storage mechanism is used, e.g. with the {@link ICProjectDescription} and {@link ICConfigurationDescription}
* for storing custom data in the settings file (.cproject)
*
* for storing custom data in the settings file (.cproject) or in a database
*
* @see ICSettingsStorage
* @see ICProjectDescription
* @see ICConfigurationDescription
*
*/
public interface ICStorageElement {
ICStorageElement[] getChildren();
/**
* Return the String of attribute value for name.
* If attribute is not found (hasAttribute(name) is false)
* this method returns null
* @param name
* @return String value or null if hasAttribute is false
*/
String getAttribute(String name);
/**
* Return whether this ICStorageElement contains an attribute value
* for name
* @param name
* @return boolean indicating existence of attribute with name name
* @since 5.1
*/
boolean hasAttribute(String name);
/**
* Returns a string array of attribute names
* @return String[]
*/
String[] getAttributeNames();
/**
* Return the parent IStorageElement or null if this
* ICStorageElement doesn't have a parent
* @return ICStorageElement parent or null
*/
ICStorageElement getParent();
/**
* Set an attribute on this ICStorageElement
* @param name
* @param value
*/
void setAttribute(String name, String value);
/**
* Remove an attribute from this ICStorageElement
* @param name
*/
void removeAttribute(String name);
/**
* Create a child ICStorageElement with the given name.
* @param name
* @return new ICStorageElement representing the child
*/
ICStorageElement createChild(String name);
/**
* Returns an array of the ICStorageElement children of this
* ICStorageElement or an empty array if no children were found
* @return ICStorageElement[] of children or empty array
*/
ICStorageElement[] getChildren();
/**
* Returns the children ICStorageElements with name name
* @param name String name of children to be returned
* @return ICStorageElement[] of children may be the empty list if no children with name found
* @since 5.1
*/
ICStorageElement[] getChildrenByName(String name);
/**
* Returns true if this storage element has child ICStorageElements
* @return boolean indicating whether this ICStorageElement has children
*/
boolean hasChildren();
/**
* Erase all children, attributes and any value set on this ICStorageElement
*/
void clear();
/**
* Get the name of this ICStorageElement
* @return String name
*/
String getName();
// void remove();
/**
* Remove the ICStorageElement from the set of child ICSotrageElements
* @param el
*/
void removeChild(ICStorageElement el);
/**
* Get the String value of this element or null if there is
* no String value set.
*
* NB a pure whitespace value is considered to be null
* @return String or null
*/
String getValue();
void setValue(String value);
/**
* Set a String value on the ICStorageElement
* @param value
*/
void setValue(String value);
/**
* Import an existing ICStorageElemtn as a child of this ICStorageElement
* @param el
* @return ICStorageElement a Handle on the newly imported ICStorageElement
* @throws UnsupportedOperationException
*/
ICStorageElement importChild(ICStorageElement el) throws UnsupportedOperationException;
/**
* Create a deep copy of the current ICStorageElement such that name, children, attributes and value
* are the same.
* <br />
* However this is implemented it should appear to the user that a deep copy of
* the elements within has occurred. [ Though the implementation may be copy-on-write
* if the underlying data structure is suitable. ]
* <br /><br />
* getParent() of the clone should be equal to the original element.getParent().
* However the clone() doesn't appear in the parent's getChildren() array.
* @return ICStorageElement deep copy of this ICStorageElement
*/
ICStorageElement createCopy() throws UnsupportedOperationException, CoreException;
/**
* Returns an ICSettingsStorage from this storage element.
*
* A setting storage is like a storage element except it represents the root of a tree.
* As such it can't contain a value or any children which are not storageModule
* ICStorageElements (otherwise they would not be accessible via the ICSettingsStorage interface)
*
* @param readOnly indicates whether the returned settings storage tree should be readonly
* @return ICSettingStorage which is this ICStorageElement as a storageModule root
* @throws CoreException if this ICStorageElement isn't a suitable root
* @throws UnsupportedOperationException if this hierarchy doesn't support ICSettingsStorage
*/
// ICSettingsStorage createSettingStorage(boolean readOnly) throws CoreException, UnsupportedOperationException;
/**
* Tests whether this storage element is exactly equal to other
* To be equal all name, children attributes and value must be
* equal between the two ICStorageElements
* @param other
* @return boolean indicating equality
*/
boolean equals(ICStorageElement other);
}

View file

@ -0,0 +1,67 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corp. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.settings.model;
import org.eclipse.cdt.internal.core.settings.model.xml.XmlStorageElement;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* This class serves as a bridge from Xml Document trees to
* ICStorageElement trees.
*
* This allows importing of old style Xml trees into ICStorageElement
* based project descriptions
*/
public class XmlStorageUtil {
/**
* Return an ICStorageElement tree based around the specified
* document
*
* N.B. the tree is backed by the passed in document
* so care should be taken to ensure that the tree is only
* subsequently through the ICStorageElement interface
*
* The ICStorageElement tree is based on the first Element
* found in the Document
* @param doc
* @return ICStorageElement tree or null if impossible
*/
public static ICStorageElement createCStorageTree(Document doc) {
NodeList list = doc.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i).getNodeType() == Node.ELEMENT_NODE) {
return createCStorageTree((Element)list.item(i));
}
}
return null;
}
/**
* Return an ICStorageElement tree based around the specified
* Element.
*
* NB the returned ICStorageElement is backed by the passed in
* Element which should only be modified via the ICStorageElement
* interface subsequent to this conversion.
*
* @param doc
* @return ICStorageElement tree
*/
public static ICStorageElement createCStorageTree(Element el) {
return new XmlStorageElement(el);
}
}

View file

@ -28,7 +28,7 @@ public abstract class CConfigurationDataProvider {
/**
* requests the Configuration Data to be created for the given ConfigurationDescription
* The method can be called in several caces:
* The method can be called in several cases:
* 1. When the new configuration is being created based upon the already existing one via
* theICProjectDescription.createConfiguration method call
* 2. When the configuration copy (clone) is being created for the copy description

View file

@ -42,7 +42,7 @@ public abstract class ResourceChangeHandlerBase implements IResourceChangeListen
private class DeltaVisitor implements IResourceDeltaVisitor{
// private IResourceDelta fRootDelta;
private Map fMoveMap = new HashMap();
private Map<IResource, IResource> fMoveMap = new HashMap<IResource, IResource>();
private IResourceMoveHandler fHandler;
public DeltaVisitor(IResourceMoveHandler handler, IResourceDelta rootDelta){
@ -126,7 +126,7 @@ public abstract class ResourceChangeHandlerBase implements IResourceChangeListen
public void resourceChanged(IResourceChangeEvent event) {
if (event.getSource() instanceof IWorkspace) {
IResourceMoveHandler handler = createResourceMoveHandler(event);
doHahdleResourceMove(event, handler);
doHandleResourceMove(event, handler);
}
}
@ -139,7 +139,7 @@ public abstract class ResourceChangeHandlerBase implements IResourceChangeListen
}
}
protected void doHahdleResourceMove(IResourceChangeEvent event, IResourceMoveHandler handler){
protected void doHandleResourceMove(IResourceChangeEvent event, IResourceMoveHandler handler){
switch (event.getType()) {
case IResourceChangeEvent.PRE_CLOSE:
IProject project = (IProject)event.getResource();

View file

@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.language;
@ -33,13 +34,13 @@ import org.eclipse.cdt.core.CCorePreferenceConstants;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.language.ProjectLanguageConfiguration;
import org.eclipse.cdt.core.language.WorkspaceLanguageConfiguration;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.Util;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Preferences;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@ -53,13 +54,13 @@ public class LanguageMappingStore {
private static final String PROJECT_MAPPINGS = "project-mappings"; //$NON-NLS-1$
private static final String WORKSPACE_MAPPINGS = "workspace-mappings"; //$NON-NLS-1$
private static final String CONTENT_TYPE_MAPPING = "content-type-mapping"; //$NON-NLS-1$
private static final String FILE_MAPPING = "file-mapping"; //$NON-NLS-1$
private static final String ATTRIBUTE_PATH = "path"; //$NON-NLS-1$
private static final String ATTRIBUTE_CONTENT_TYPE = "content-type"; //$NON-NLS-1$
private static final String ATTRIBUTE_LANGUAGE = "language"; //$NON-NLS-1$
@ -68,31 +69,31 @@ public class LanguageMappingStore {
public LanguageMappingStore() {
}
public ProjectLanguageConfiguration decodeMappings(IProject project) throws CoreException {
ProjectLanguageConfiguration config = new ProjectLanguageConfiguration();
ICDescriptor descriptor = getProjectDescription(project);
Element rootElement = descriptor.getProjectData(LANGUAGE_MAPPING_ID);
ICStorageElement rootElement = descriptor.getProjectStorageElement(LANGUAGE_MAPPING_ID);
if (rootElement == null) {
return config;
}
NodeList mappingElements = rootElement.getElementsByTagName(PROJECT_MAPPINGS);
if (mappingElements.getLength() > 0) {
Element element = (Element) mappingElements.item(0);
ICStorageElement[] mappingElements = rootElement.getChildrenByName(PROJECT_MAPPINGS);
if (mappingElements.length > 0) {
ICStorageElement element = mappingElements[0];
config.setContentTypeMappings(decodeProjectContentTypeMappings(element));
config.setFileMappings(decodeFileMappings(element));
}
return config;
}
private Map<String, Map<String, String>> decodeProjectContentTypeMappings(Element rootElement) {
private Map<String, Map<String, String>> decodeProjectContentTypeMappings(ICStorageElement rootElement) {
Map<String, Map<String, String>> decodedMappings = new TreeMap<String, Map<String, String>>();
NodeList mappingElements = rootElement.getElementsByTagName(CONTENT_TYPE_MAPPING);
for (int j = 0; j < mappingElements.getLength(); j++) {
Element mapping = (Element) mappingElements.item(j);
ICStorageElement[] mappingElements = rootElement.getChildrenByName(CONTENT_TYPE_MAPPING);
for (int j = 0; j < mappingElements.length; j++) {
ICStorageElement mapping = mappingElements[j];
String configuration = mapping.getAttribute(ATTRIBUTE_CONFIGURATION);
Map<String, String> contentTypeMappings = decodedMappings.get(configuration);
if (contentTypeMappings == null) {
contentTypeMappings = new TreeMap<String, String>();
@ -108,18 +109,18 @@ public class LanguageMappingStore {
protected ICDescriptor getProjectDescription(IProject project) throws CoreException {
return CCorePlugin.getDefault().getCProjectDescription(project, true);
}
private Map<String, String> decodeContentTypeMappings(Element rootElement) throws CoreException {
return decodeMappings(rootElement, CONTENT_TYPE_MAPPING, ATTRIBUTE_CONTENT_TYPE, ATTRIBUTE_LANGUAGE);
}
private Map<String, Map<String, String>> decodeFileMappings(Element rootElement) throws CoreException {
private Map<String, Map<String, String>> decodeFileMappings(ICStorageElement rootElement) throws CoreException {
Map<String, Map<String, String>> decodedMappings = new TreeMap<String, Map<String, String>>();
NodeList mappingElements = rootElement.getElementsByTagName(FILE_MAPPING);
for (int j = 0; j < mappingElements.getLength(); j++) {
Element mapping = (Element) mappingElements.item(j);
ICStorageElement[] mappingElements = rootElement.getChildrenByName(FILE_MAPPING);
for (int j = 0; j < mappingElements.length; j++) {
ICStorageElement mapping = mappingElements[j];
String path = mapping.getAttribute(ATTRIBUTE_PATH);
Map<String, String> configurationMappings = decodedMappings.get(path);
if (configurationMappings == null) {
configurationMappings = new TreeMap<String, String>();
@ -131,7 +132,7 @@ public class LanguageMappingStore {
}
return decodedMappings;
}
private Map<String, String> decodeMappings(Element rootElement, String category, String keyName, String valueName) {
Map<String, String> decodedMappings = new TreeMap<String, String>();
NodeList mappingElements = rootElement.getElementsByTagName(category);
@ -146,36 +147,33 @@ public class LanguageMappingStore {
public void storeMappings(IProject project, ProjectLanguageConfiguration config) throws CoreException {
ICDescriptor descriptor = getProjectDescription(project);
Element rootElement = descriptor.getProjectData(LANGUAGE_MAPPING_ID);
clearChildren(rootElement);
ICStorageElement rootElement = descriptor.getProjectStorageElement(LANGUAGE_MAPPING_ID);
// clear all children and settings
rootElement.clear();
ICStorageElement projectMappings = rootElement.createChild(PROJECT_MAPPINGS);
Document document = rootElement.getOwnerDocument();
Element projectMappings = document.createElement(PROJECT_MAPPINGS);
rootElement.appendChild(projectMappings);
addProjectContentTypeMappings(config.getContentTypeMappings(), projectMappings);
addFileMappings(config.getFileMappings(), projectMappings);
descriptor.saveProjectData();
}
private void addProjectContentTypeMappings(Map<String, Map<String, String>> contentTypeMappings, Element rootElement) {
Document document = rootElement.getOwnerDocument();
private void addProjectContentTypeMappings(Map<String, Map<String, String>> contentTypeMappings, ICStorageElement rootElement) {
Iterator<Entry<String, Map<String, String>>> entries = contentTypeMappings.entrySet().iterator();
while (entries.hasNext()) {
Entry<String, Map<String, String>> entry = entries.next();
String configuration = entry.getKey();
Iterator<Entry<String, String>> contentTypeEntries = entry.getValue().entrySet().iterator();
while (contentTypeEntries.hasNext()) {
Entry<String, String> configurationEntry = contentTypeEntries.next();
String contentType = configurationEntry.getKey();
String language = configurationEntry.getValue();
Element mapping = document.createElement(CONTENT_TYPE_MAPPING);
ICStorageElement mapping = rootElement.createChild(CONTENT_TYPE_MAPPING);
mapping.setAttribute(ATTRIBUTE_CONTENT_TYPE, contentType);
mapping.setAttribute(ATTRIBUTE_CONFIGURATION, configuration);
mapping.setAttribute(ATTRIBUTE_LANGUAGE, language);
rootElement.appendChild(mapping);
}
}
}
@ -193,7 +191,7 @@ public class LanguageMappingStore {
StreamResult result = new StreamResult(buffer);
serializer.transform(source, result);
String encodedMappings = buffer.getBuffer().toString();
Preferences node = CCorePlugin.getDefault().getPluginPreferences();
node.setValue(CCorePreferenceConstants.WORKSPACE_LANGUAGE_MAPPINGS, encodedMappings);
CCorePlugin.getDefault().savePluginPreferences();
@ -201,18 +199,18 @@ public class LanguageMappingStore {
throw new CoreException(Util.createStatus(e));
} catch (TransformerException e) {
throw new CoreException(Util.createStatus(e));
}
}
}
public WorkspaceLanguageConfiguration decodeWorkspaceMappings() throws CoreException {
Preferences node = CCorePlugin.getDefault().getPluginPreferences();
String encodedMappings = node.getString(CCorePreferenceConstants.WORKSPACE_LANGUAGE_MAPPINGS);
WorkspaceLanguageConfiguration config = new WorkspaceLanguageConfiguration();
if (encodedMappings == null || encodedMappings.length() == 0) {
return config;
}
// The mappings are encoded as XML in a String so we need to parse it.
InputSource input = new InputSource(new StringReader(encodedMappings));
try {
@ -227,7 +225,7 @@ public class LanguageMappingStore {
throw new CoreException(Util.createStatus(e));
}
}
private Transformer createSerializer() throws CoreException {
try {
return TransformerFactory.newInstance().newTransformer();
@ -238,14 +236,6 @@ public class LanguageMappingStore {
}
}
private void clearChildren(Element element) {
Node child = element.getFirstChild();
while (child != null) {
element.removeChild(child);
child = element.getFirstChild();
}
}
private void addMappings(Map<String, String> mappings, Element rootElement, String category, String keyName, String valueName) {
Document document = rootElement.getOwnerDocument();
Iterator<Entry<String, String>> entries = mappings.entrySet().iterator();
@ -257,29 +247,22 @@ public class LanguageMappingStore {
rootElement.appendChild(mapping);
}
}
private void addContentTypeMappings(Map<String, String> mappings, Element rootElement) {
addMappings(mappings, rootElement, CONTENT_TYPE_MAPPING, ATTRIBUTE_CONTENT_TYPE, ATTRIBUTE_LANGUAGE);
}
private void addFileMappings(Map<String, Map<String, String>> mappings, Element rootElement) {
Document document = rootElement.getOwnerDocument();
Iterator<Entry<String, Map<String, String>>> entries = mappings.entrySet().iterator();
while (entries.hasNext()) {
Entry<String, Map<String, String>> entry = entries.next();
Element mapping = document.createElement(FILE_MAPPING);
private void addFileMappings(Map<String, Map<String, String>> mappings, ICStorageElement rootElement) {
for (Map.Entry<String, Map<String, String>> entry : mappings.entrySet()) {
ICStorageElement mapping = rootElement.createChild(FILE_MAPPING);
String path = entry.getKey();
Iterator<Entry<String, String>> configurationEntries = entry.getValue().entrySet().iterator();
while (configurationEntries.hasNext()) {
Entry<String, String> configurationEntry = configurationEntries.next();
for (Entry<String, String> configurationEntry : entry.getValue().entrySet()) {
String configuration = configurationEntry.getKey();
String language = configurationEntry.getValue();
mapping.setAttribute(ATTRIBUTE_PATH, path);
mapping.setAttribute(ATTRIBUTE_CONFIGURATION, configuration);
mapping.setAttribute(ATTRIBUTE_LANGUAGE, language);
rootElement.appendChild(mapping);
}
}
}

View file

@ -12,6 +12,7 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.model;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@ -123,6 +124,16 @@ public abstract class APathEntry extends PathEntry {
}
return super.equals(obj);
}
@Override
public int hashCode() {
int hashCode = Arrays.hashCode(exclusionPatterns);
if (basePath != null)
hashCode += basePath.hashCode();
if (baseRef != null)
hashCode += baseRef.hashCode();
return hashCode + super.hashCode();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()

View file

@ -161,27 +161,32 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe
public static final IWorkingCopy[] NoWorkingCopy = new IWorkingCopy[0];
static CModelManager factory = null;
static volatile CModelManager factory = null;
private CModelManager() {
}
public static CModelManager getDefault() {
if (factory == null) {
factory = new CModelManager();
synchronized (CModelManager.class) {
if (factory != null)
return factory;
// Register to the workspace;
ResourcesPlugin.getWorkspace().addResourceChangeListener(factory,
IResourceChangeEvent.POST_CHANGE
| IResourceChangeEvent.PRE_DELETE
| IResourceChangeEvent.PRE_CLOSE);
factory = new CModelManager();
// Register the Core Model on the Descriptor
// Manager, it needs to know about changes.
CCorePlugin.getDefault().getCDescriptorManager().addDescriptorListener(factory);
// Register the Core Model on the ContentTypeManager
// it needs to know about changes.
Platform.getContentTypeManager().addContentTypeChangeListener(factory);
// Register to the workspace;
ResourcesPlugin.getWorkspace().addResourceChangeListener(factory,
IResourceChangeEvent.POST_CHANGE
| IResourceChangeEvent.PRE_DELETE
| IResourceChangeEvent.PRE_CLOSE);
// Register the Core Model on the Descriptor
// Manager, it needs to know about changes.
CCorePlugin.getDefault().getCDescriptorManager().addDescriptorListener(factory);
// Register the Core Model on the ContentTypeManager
// it needs to know about changes.
Platform.getContentTypeManager().addContentTypeChangeListener(factory);
}
}
return factory;
}
@ -1153,8 +1158,8 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe
}
}
for (ICElement element : newElements.keySet())
this.cache.putInfo(element, newElements.get(element));
for (Map.Entry<ICElement, CElementInfo> element : newElements.entrySet())
this.cache.putInfo(element.getKey(), element.getValue());
}
/**
@ -1212,10 +1217,10 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe
}
/**
*
*
*/
public void startup() {
// Do any initialization.
// Initialization is performed on the first getDefault()...
}
/**
@ -1234,6 +1239,9 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe
for (BinaryRunner runner : runners) {
runner.stop();
}
// Nullify the static factory
factory = null;
}
private void checkForProjectRename(IResourceDelta delta) {

View file

@ -13,6 +13,8 @@ package org.eclipse.cdt.internal.core.model;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ElementChangedEvent;
@ -64,7 +66,7 @@ public abstract class CModelOperation implements IWorkspaceRunnable, IProgressMo
* empty result if no elements are created, or if this
* operation is not actually executed.
*/
protected static ICElement[] fgEmptyResult= new ICElement[] {};
protected static final ICElement[] fgEmptyResult= new ICElement[] {};
/**
* Collection of <code>ICElementDelta</code>s created by this operation.
@ -73,7 +75,7 @@ public abstract class CModelOperation implements IWorkspaceRunnable, IProgressMo
* deltas. This collection is registered with the C Model notification
* manager if the operation completes successfully.
*/
protected ICElementDelta[] fDeltas= null;
protected List<ICElementDelta> fDeltas= null;
/**
* The elements created by this operation - empty
@ -105,7 +107,7 @@ public abstract class CModelOperation implements IWorkspaceRunnable, IProgressMo
/*
* A per thread stack of java model operations (PerThreadObject of ArrayList).
*/
protected static ThreadLocal<ArrayList<CModelOperation>> operationStacks = new ThreadLocal<ArrayList<CModelOperation>>();
protected final static ThreadLocal<ArrayList<CModelOperation>> operationStacks = new ThreadLocal<ArrayList<CModelOperation>>();
protected CModelOperation() {
}
@ -163,14 +165,9 @@ public abstract class CModelOperation implements IWorkspaceRunnable, IProgressMo
* when the operation completes.
*/
protected void addDelta(ICElementDelta delta) {
if (fDeltas == null) {
fDeltas= new ICElementDelta[] {delta};
} else {
ICElementDelta[] copy= new ICElementDelta[fDeltas.length + 1];
System.arraycopy(fDeltas, 0, copy, 0, fDeltas.length);
copy[fDeltas.length]= delta;
fDeltas= copy;
}
if (fDeltas == null)
fDeltas = new LinkedList<ICElementDelta>();
fDeltas.add(delta);
}
/*

View file

@ -324,15 +324,13 @@ public class CProject extends Openable implements ICProject {
setPreferences(preferences); // always reset (26255)
if (newOptions != null) {
Iterator<String> keys = newOptions.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
for (Map.Entry<String, String> e : newOptions.entrySet()) {
String key = e.getKey();
if (!CModelManager.OptionNames.contains(key))
continue; // unrecognized option
// no filtering for encoding (custom encoding for project is allowed)
String value = newOptions.get(key);
String value = e.getValue();
preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251)
preferences.setValue(key, value);
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 QNX Software Systems and others.
* Copyright (c) 2000, 2008 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.model;
@ -33,6 +34,8 @@ 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.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.CharOperation;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
@ -89,16 +92,9 @@ public class DefaultPathEntryStore implements IPathEntryStore, ICDescriptorListe
ICDescriptor cdesc = CCorePlugin.getDefault().getCProjectDescription(fProject, false);
if (cdesc != null) {
ArrayList<IPathEntry> pathEntries = new ArrayList<IPathEntry>();
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 != null && childNode.getNodeType() == Node.ELEMENT_NODE) {
if (childNode.getNodeName().equals(PATH_ENTRY)) {
pathEntries.add(decodePathEntry(fProject, (Element) childNode));
}
}
}
ICStorageElement entry = cdesc.getProjectStorageElement(PATH_ENTRY_ID);
for (ICStorageElement childNode : entry.getChildrenByName(PATH_ENTRY))
pathEntries.add(decodePathEntry(fProject, childNode));
IPathEntry[] entries = new IPathEntry[pathEntries.size()];
pathEntries.toArray(entries);
return entries;
@ -111,23 +107,18 @@ public class DefaultPathEntryStore implements IPathEntryStore, ICDescriptorListe
return;
}
ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(fProject, true);
Element rootElement = descriptor.getProjectData(PATH_ENTRY_ID);
ICStorageElement rootElement = descriptor.getProjectStorageElement(PATH_ENTRY_ID);
// Clear out all current children
Node child = rootElement.getFirstChild();
while (child != null) {
rootElement.removeChild(child);
child = rootElement.getFirstChild();
}
rootElement.clear();
// Save the entries
if (newRawEntries != null && newRawEntries.length > 0) {
// Serialize the include paths
Document doc = rootElement.getOwnerDocument();
encodePathEntries(fProject.getFullPath(), doc, rootElement, newRawEntries);
encodePathEntries(fProject.getFullPath(), rootElement, newRawEntries);
}
descriptor.saveProjectData();
}
static IPathEntry decodePathEntry(IProject project, Element element) throws CModelException {
static IPathEntry decodePathEntry(IProject project, ICStorageElement element) throws CModelException {
IPath projectPath = project.getFullPath();
// kind
@ -152,10 +143,10 @@ public class DefaultPathEntryStore implements IPathEntryStore, ICDescriptorListe
}
// check fo the base path
IPath basePath = new Path(element.getAttribute(ATTRIBUTE_BASE_PATH));
IPath basePath = new Path(element.hasAttribute(ATTRIBUTE_BASE_PATH) ? element.getAttribute(ATTRIBUTE_BASE_PATH) : "");
// get the base ref
IPath baseRef = new Path(element.getAttribute(ATTRIBUTE_BASE_REF));
IPath baseRef = new Path(element.hasAttribute(ATTRIBUTE_BASE_REF) ? element.getAttribute(ATTRIBUTE_BASE_REF) : "");
// exclusion patterns (optional)
String exclusion = element.getAttribute(ATTRIBUTE_EXCLUDING);
@ -245,12 +236,11 @@ public class DefaultPathEntryStore implements IPathEntryStore, ICDescriptorListe
}
}
static void encodePathEntries(IPath projectPath, Document doc, Element configRootElement, IPathEntry[] entries) {
Element element;
static void encodePathEntries(IPath projectPath, ICStorageElement configRootElement, IPathEntry[] entries) {
ICStorageElement element;
for (IPathEntry entrie : entries) {
element = doc.createElement(PATH_ENTRY);
configRootElement.appendChild(element);
element = configRootElement.createChild(PATH_ENTRY);
int kind = entrie.getEntryKind();
// Set the kind
element.setAttribute(ATTRIBUTE_KIND, PathEntry.kindToString(kind));

View file

@ -73,6 +73,11 @@ public class MacroEntry extends APathEntry implements IMacroEntry {
}
return super.equals(obj);
}
@Override
public int hashCode() {
return macroName.hashCode() + macroValue.hashCode() + super.hashCode();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()

View file

@ -180,9 +180,10 @@ public abstract class MultiOperation extends CModelOperation {
insertedTree = true;
}
}
if (insertedTree)
fDeltas = new ICElementDelta[] {rootDelta};
else
if (insertedTree) {
fDeltas.clear();
fDeltas.add(rootDelta);
} else
fDeltas = null;
}
}

View file

@ -70,6 +70,11 @@ public class PathEntry implements IPathEntry {
}
return super.equals(obj);
}
@Override
public int hashCode() {
return path.hashCode() + entryKind * 17 + (isExported ? 3 : 2);
}
/**
* Returns the kind from its <code>String</code> form.

View file

@ -0,0 +1,335 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
import java.text.MessageFormat;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent;
import org.eclipse.cdt.core.settings.model.ICDescriptionDelta;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.settings.model.ICSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.model.CModelManager;
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType.CProjectDescriptionStorageTypeProxy;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.osgi.framework.Version;
/**
* This abstract class provides an extension point for functionality for loading
* a CDT Project Description from some kind of backing store. This allows
* extenders to provide their own backing store for a CDT project description.
*
* This class provides the ICProjectDescription root of the project configuration tree in
* which is contained storage modules and other members of the storage element tree.
*
* It is the responsibility of the storage that access to the project storage are threadsafe
* i.e. return writable descriptions aren't shared between multiple threads (or if they
* are, they are suitable synchronized) and setProjectDescription must be aware that
* getProjectDescription may also be called concurrently
*
* <p>
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is no guarantee that this API will work or
* that it will remain the same. Please do not use this API without consulting
* with the CDT team.
* </p>
*
* @since 6.0
*/
public abstract class AbstractCProjectDescriptionStorage {
/** The {@link ICProjectDescriptionStorageType} extension parent of this */
public final CProjectDescriptionStorageTypeProxy type;
/** The version of the project description storage that was loaded */
public final Version version;
/** The project this project-storage is responsible for */
protected volatile IProject project;
/** Flag used to detect if setProjectDescription(...) is called by the thread already in a setProjectDescription(...) */
final private ThreadLocal<Boolean> setProjectDescriptionOperationRunning = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
/** Before the description is fully applied / loaded, consumers of CProjectDescriptionEvent and CProjectDescription.applyDatas()
* assume that getProjectDescription(...) will return the writable project description in the process of being created / modified...
* Cached temporarily in a thread local variable for this very purpose. */
final private ThreadLocal<ICProjectDescription> currentThreadProjectDescription = new ThreadLocal<ICProjectDescription>();
/**
* @param type CProjectDescriptionStorageTypeProxy
* @param project IProject
* @param version Version
*/
public AbstractCProjectDescriptionStorage(CProjectDescriptionStorageTypeProxy type, IProject project, Version version) {
this.type = type;
this.project = project;
this.version = version;
}
/**
* Returns the project associated with this storage
* @return the IProject associated with the current project
*/
public final IProject getProject() {
return project;
}
/**
* Called in response to a project move event
* @param newProject
* @param oldProject
*/
public void handleProjectMove(IProject newProject, IProject oldProject) {
project = newProject;
}
/**
* Return an ICSettingsStorage root for the given ICStorageElement
* @param element
* @return ICSettingsStorage based off of ICStorageElement
*/
public abstract ICSettingsStorage getStorageForElement(ICStorageElement element) throws CoreException;
/*
* T O C L E A N U P
*/
/*
* FIXME REMOVE
*
* We shouldn't have this in this interface, but SetCProjectDescription creates
* a new description based on an existing description for the delta event. It reconciles
* them later. But this will be non-optimal for most backends
*
* Returns a 'writable' ICStorageElement tree clone of el
*/
public ICStorageElement copyElement(ICStorageElement el, boolean writable) throws CoreException {
return null;
}
/*
* get/setProjectDescription methods
*/
/**
* Return the ICProjectDescription for the specified project.
*
* Use the ICProjectDescriptionManager flags to control the project
* description to be returned
*
* Implementors should call super.getProjectDescription(...) first
* so that current 'threadLocal' project description is returned
*
* @param flags Or of {@link ICProjectDescriptionManager} flags
* @param monitor
* @return an ICProjectDescription corresponding to the given
* @see ICProjectDescriptionManager#GET_WRITABLE
* @see ICProjectDescriptionManager#GET_IF_LOADDED
* @see ICProjectDescriptionManager#GET_EMPTY_PROJECT_DESCRIPTION
* @see ICProjectDescriptionManager#GET_CREATE_DESCRIPTION
* @see ICProjectDescriptionManager#PROJECT_CREATING
*/
public ICProjectDescription getProjectDescription(int flags, IProgressMonitor monitor) throws CoreException {
if (!project.isAccessible())
throw ExceptionFactory.createCoreException(MessageFormat.format(CCorePlugin.getResourceString("ProjectDescription.ProjectNotAccessible"), getProject().getName())); //$NON-NLS-1$
return currentThreadProjectDescription.get();
}
/**
* The method called by the CProjectDescriptionManager for serializing the project settings
* @param description the project description being set
* @param flags
* @param monitor
* @throws CoreException
*/
public void setProjectDescription(final ICProjectDescription description, final int flags, IProgressMonitor monitor) throws CoreException {
try {
if (monitor == null)
monitor = new NullProgressMonitor();
ICProject cproject = CModelManager.getDefault().create(project);
// The CProjectDescriptionOperation fires the appropriate CElementDeltas calling the callbacks
// below for actual project serialization
SetCProjectDescriptionOperation op = new SetCProjectDescriptionOperation(this, cproject, (CProjectDescription)description, flags);
// Safety: Verify that the listeners of the event call-backs don't recursively call setProjectDescription(...)
// While in the past this recursion hasn't been infinite, the behaviour is 'undefined'.
if (setProjectDescriptionOperationRunning.get()) {
CCorePlugin.log("API Error: setProjectDescription() shouldn't be called recursively.", new Exception()); //$NON-NLS-1$
Job j = new Job("setProjectDescription rescheduled") { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
setProjectDescription(description, flags, monitor);
} catch (CoreException e) {
CCorePlugin.log(e);
}
return Status.OK_STATUS;
}
};
j.setSystem(true);
j.schedule();
return;
}
try {
setProjectDescriptionOperationRunning.set(true);
op.runOperation(monitor);
} catch (IllegalArgumentException e) {
throw ExceptionFactory.createCoreException(e);
} finally {
setProjectDescriptionOperationRunning.set(false);
}
} finally {
monitor.done();
}
}
/*
* C A L L B A C K S
* Callbacks for the SetCProjectDescriptionOperation to allow AbstractCProjectDescriptionStorage overrides
*
*/
/**
* Callback
*
* - Actually set the current in memory ICProjectDescription to this
* - If this requires modification of workspace resources then don't serialize
*
* @param des
* @param overwriteIfExists
* @return boolean indicating whether existing read-only project description should be replaced
*/
public abstract boolean setCurrentDescription(ICProjectDescription des, boolean overwriteIfExists);
/**
* Callback
* - Return an IWorkspaceRunnable which will actually perform the serialization of the
* current project description or null if not required
* @return IWorkspaceRunnable that will perform the serialization
*/
public abstract IWorkspaceRunnable createDesSerializationRunnable() throws CoreException;
/*
* R E S O U R C E C H A N G E E V E N T S
*/
/**
* Event fired as a result of a project being moved
*/
public void projectMove(IProject newProject) {
project = newProject;
}
/**
* Event fired as a result of the project being closed or removed
* to allow cleanup of state
*/
public void projectCloseRemove() {
// NOP
}
/*
* C P R O J E C T D E L T A E V E N T S F I R E D
* Protected methods for notifying project description listeners of changes to the proj desc
*/
public static final void fireLoadedEvent(ICProjectDescription desc) {
CProjectDescriptionManager.getInstance().notifyListeners(new CProjectDescriptionEvent(CProjectDescriptionEvent.LOADED, null, desc, null, null));
}
/**
* Fire an event stating that a copy of a description has been created
*
* This is fired when:
* - New writable description is created from read-only store
* @param newDes The new description copy
* @param oldDes The old description
*/
public static final void fireCopyCreatedEvent(ICProjectDescription newDes, ICProjectDescription oldDes) {
CProjectDescriptionManager.getInstance().notifyListeners(new CProjectDescriptionEvent(CProjectDescriptionEvent.COPY_CREATED, null, newDes, oldDes, null));
}
public static final void fireAboutToApplyEvent(ICProjectDescription newDes, ICProjectDescription oldDes) {
CProjectDescriptionManager.getInstance().notifyListeners(new CProjectDescriptionEvent(CProjectDescriptionEvent.ABOUT_TO_APPLY, null, newDes, oldDes, null));
}
public static final CProjectDescriptionEvent createAppliedEvent(ICProjectDescription newDes, ICProjectDescription oldDes, ICProjectDescription appliedDes, ICDescriptionDelta delta) {
return new CProjectDescriptionEvent(CProjectDescriptionEvent.APPLIED, delta, newDes, oldDes, appliedDes);
}
public static final void fireAppliedEvent(ICProjectDescription newDes, ICProjectDescription oldDes, ICProjectDescription appliedDes, ICDescriptionDelta delta) {
CProjectDescriptionManager.getInstance().notifyListeners(createAppliedEvent(newDes, oldDes, appliedDes, delta));
}
/**
* @param newDes - a *writeable* description
* @param oldDes
* @param appliedDes - the description being applied
* @param delta
*/
public static final void fireDataAppliedEvent(ICProjectDescription newDes, ICProjectDescription oldDes, ICProjectDescription appliedDes, ICDescriptionDelta delta) {
CProjectDescriptionManager.getInstance().notifyListeners(new CProjectDescriptionEvent(CProjectDescriptionEvent.DATA_APPLIED, delta, newDes, oldDes, appliedDes));
}
/**
* Helper method to check whether the specified flags are set
* @param flags
* @param check
* @return boolean indicating whether flags are set
*/
protected static final boolean checkFlags(int flags, int check){
return (flags & check) == check;
}
/**
* Set the threadLocal project description
*
* Only intended to be used by implementors and package.
*
* This should be used in the following pattern:
* try {
* setThreadLocaProjectDesc(prjDesc);
* fireEvent();
* } finally {
* setThreadLocalProjectDesc(null);
* }
*
* @param currentDesc
* @return the previously set thread local project desc (or null)
*/
public ICProjectDescription setThreadLocalProjectDesc(ICProjectDescription currentDesc) {
ICProjectDescription current = currentThreadProjectDescription.get();
currentThreadProjectDescription.set(currentDesc);
return current;
}
}

View file

@ -38,7 +38,7 @@ public class CConfigurationDataProviderDescriptor {
private String[] fNatureIds;
private String[] fConflictingNatureIds;
CConfigurationDataProviderDescriptor(IExtension extension){
public CConfigurationDataProviderDescriptor(IExtension extension){
fId = extension.getUniqueIdentifier();
fExtension = extension;
fProviderElement = getProviderElement(extension);

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.core.settings.model.ICSettingBase;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICSourceEntry;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.ICTargetPlatformSetting;
@ -44,6 +45,7 @@ import org.eclipse.cdt.core.settings.model.extension.CResourceData;
import org.eclipse.cdt.core.settings.model.extension.CTargetPlatformData;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.settings.model.util.PathSettingsContainer;
import org.eclipse.cdt.internal.core.settings.model.xml.InternalXmlStorageElement;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
@ -333,12 +335,20 @@ public class CConfigurationDescription extends CDataProxyContainer implements IC
return getSpecSettings().getStorage(id, create);
}
public ICStorageElement importStorage(String id, ICStorageElement el) throws UnsupportedOperationException, CoreException {
return getSpecSettings().importStorage(id, el);
}
public void removeStorage(String id) throws CoreException {
getSpecSettings().removeStorage(id);
}
public boolean containsStorage(String id) throws CoreException {
return getSpecSettings().containsStorage(id);
public void setReadOnly(boolean readOnly, boolean keepModify) {
try {
getSpecSettings().setReadOnly(readOnly, keepModify);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
public CConfigurationSpecSettings getSpecSettings() throws CoreException{

View file

@ -58,7 +58,7 @@ public class CConfigurationDescriptionCache extends CDefaultConfigurationData
private CProjectDescription fParent;
private PathSettingsContainer fPathSettingContainer = PathSettingsContainer.createRootContainer();
private ResourceDescriptionHolder fRcHolder = new ResourceDescriptionHolder(fPathSettingContainer, true);
private List fChildList = new ArrayList();
private List<ICSettingObject> fChildList = new ArrayList<ICSettingObject>();
private CConfigurationSpecSettings fSpecSettings;
private CConfigurationData fData;
private CConfigurationDescriptionCache fBaseCache;
@ -270,7 +270,7 @@ public class CConfigurationDescriptionCache extends CDefaultConfigurationData
}
public ICSettingObject[] getChildSettings() {
return (ICSettingObject[])fChildList.toArray(new ICSettingObject[fChildList.size()]);
return fChildList.toArray(new ICSettingObject[fChildList.size()]);
}
public ICConfigurationDescription getConfiguration() {
@ -292,9 +292,9 @@ public class CConfigurationDescriptionCache extends CDefaultConfigurationData
public void removeStorage(String id) throws CoreException {
getSpecSettings().removeStorage(id);
}
public boolean containsStorage(String id) throws CoreException {
return getSpecSettings().containsStorage(id);
public ICStorageElement importStorage(String id, ICStorageElement el) throws UnsupportedOperationException, CoreException {
return getSpecSettings().importStorage(id, el);
}
public CConfigurationSpecSettings getSpecSettings() /*throws CoreException*/{
@ -349,6 +349,11 @@ public class CConfigurationDescriptionCache extends CDefaultConfigurationData
return !fInitializing;
}
public void setReadOnly(boolean readOnly, boolean keepModify) {
if (readOnly)
throw ExceptionFactory.createIsReadOnlyException();
}
public ICTargetPlatformSetting getTargetPlatformSetting() {
return (ICTargetPlatformSetting)getTargetPlatformData();
}

View file

@ -7,6 +7,7 @@
*
* Contributors:
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
@ -35,10 +36,19 @@ import org.eclipse.cdt.internal.core.CExtensionInfo;
import org.eclipse.cdt.internal.core.COwner;
import org.eclipse.cdt.internal.core.COwnerConfiguration;
import org.eclipse.cdt.internal.core.cdtvariables.StorableCdtVariables;
import org.eclipse.cdt.internal.core.settings.model.xml.InternalXmlStorageElement;
import org.eclipse.cdt.internal.core.settings.model.xml.XmlStorage;
import org.eclipse.cdt.utils.envvar.StorableEnvironment;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
/**
* CConfigurationSpecSettings impelements ICSettingsStorage
* to provide storage for ICStorageElements related to project settings
*
* This corresponds to the <cconfiguration id="....> elements within
* the org.eclipse.cdt.core.settings storageModule in the project xml file
*/
public class CConfigurationSpecSettings implements ICSettingsStorage{
static final String BUILD_SYSTEM_ID = "buildSystemId"; //$NON-NLS-1$
// private final static String ELEMENT_REFERENCES = "references"; //$NON-NLS-1$
@ -60,7 +70,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
private ICConfigurationDescription fCfg;
private ICStorageElement fRootStorageElement;
private ICStorageElement fSettingsStorageElement;
private CStorage fStorage;
private ICSettingsStorage fStorage;
private String fBuildSystemId;
private String fName;
private String fId;
@ -70,9 +80,9 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
private Map<String, String> fRefMapCache;
private CExternalSettingsHolder fExtSettingsProvider = new CExternalSettingsHolder();
private boolean fIsModified;
private HashMap fSessionPropertiesMap;
private HashMap fExtMap;
private HashMap fExtInfoMap = new HashMap();
private HashMap<QualifiedName, Object> fSessionPropertiesMap;
private HashMap<String, CConfigExtensionReference[]> fExtMap;
private HashMap<CConfigExtensionReference, CExtensionInfo> fExtInfoMap = new HashMap<CConfigExtensionReference, CExtensionInfo>();
private String fOwnerId;
private COwner fOwner;
// private CConfigBasedDescriptor fDescriptor;
@ -129,6 +139,12 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
this(des, base, null);
}
/**
* Create a new CConfigurationSpecSettings based on a base cfg spec settings
* @param des
* @param base
* @param rootEl
*/
public CConfigurationSpecSettings(ICConfigurationDescription des, CConfigurationSpecSettings base, ICStorageElement rootEl){
fCfg = des;
fRootStorageElement = rootEl;
@ -145,7 +161,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
fExtSettingsProvider = new CExternalSettingsHolder(base.fExtSettingsProvider);
if(base.fSessionPropertiesMap != null)
fSessionPropertiesMap = (HashMap)base.fSessionPropertiesMap.clone();
fSessionPropertiesMap = (HashMap<QualifiedName, Object>)base.fSessionPropertiesMap.clone();
if(base.fEnvironment != null)
fEnvironment = new StorableEnvironment(base.fEnvironment, des.isReadOnly());
@ -237,7 +253,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
private ICStorageElement getSettingsStorageElement() throws CoreException{
if(fSettingsStorageElement == null)
fSettingsStorageElement =getStorage(CProjectDescriptionManager.MODULE_ID, true);
fSettingsStorageElement = getStorage(CProjectDescriptionManager.MODULE_ID, true);
return fSettingsStorageElement;
}
@ -249,10 +265,6 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
getStorageBase().removeStorage(id);
}
public boolean containsStorage(String id) throws CoreException {
return getStorageBase().containsStorage(id);
}
ICStorageElement getRootStorageElement() throws CoreException{
if(fRootStorageElement == null){
if(fCfg.isPreferenceConfiguration()){
@ -267,24 +279,22 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
void removeConfiguration() throws CoreException{
CProjectDescriptionManager.getInstance().removeStorage(fCfg.getProjectDescription(), fCfg.getId());
}
private CStorage getStorageBase() throws CoreException{
if(fStorage == null){
fStorage = new CStorage((InternalXmlStorageElement)getRootStorageElement());
// if(fDescriptor != null)
// reconcileDescriptor(fStorage, fDescriptor);
}
private ICSettingsStorage getStorageBase() throws CoreException{
if(fStorage == null)
if (fCfg.isPreferenceConfiguration())
// Get a storage from the root storage element (in the case of a preferences element, getProject() will be null...
fStorage = CProjectDescriptionManager.getInstance().getStorageForElement(null, getRootStorageElement());
else
fStorage = CProjectDescriptionManager.getInstance().getStorageForElement(fCfg.getProjectDescription().getProject(), getRootStorageElement());
return fStorage;
}
void doneInitialization(){
if(isReadOnly()){
if(fRootStorageElement != null)
((InternalXmlStorageElement)fRootStorageElement).setReadOnly(true, false);
if(fSettingsStorageElement != null)
((InternalXmlStorageElement)fSettingsStorageElement).setReadOnly(true, false);
if(isReadOnly())
if(fStorage != null)
fStorage.setReadOnly(true, false);
}
}
public String getBuildSystemId(){
@ -372,7 +382,11 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
public boolean isReadOnly(){
return fCfg.isReadOnly();
}
public void setReadOnly(boolean readOnly, boolean keepModify) {
fCfg.setReadOnly(readOnly, keepModify);
}
public StorableCdtVariables getMacros(){
if(fMacros == null)
fMacros = new StorableCdtVariables(isReadOnly());
@ -506,21 +520,21 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
setModified(true);
}
private Map getSessionPropertiesMap(boolean create){
private Map<QualifiedName, Object> getSessionPropertiesMap(boolean create){
if(fSessionPropertiesMap == null && create)
fSessionPropertiesMap = new HashMap();
fSessionPropertiesMap = new HashMap<QualifiedName, Object>();
return fSessionPropertiesMap;
}
public Object getSettionProperty(QualifiedName name){
Map map = getSessionPropertiesMap(false);
Map<QualifiedName, Object> map = getSessionPropertiesMap(false);
return map != null ? map.get(name) : null;
}
public void setSettionProperty(QualifiedName name, Object value){
// if(isReadOnly())
// throw ExceptionFactory.createIsReadOnlyException();
Map map = getSessionPropertiesMap(true);
Map<QualifiedName, Object> map = getSessionPropertiesMap(true);
if(value != null)
map.put(name, value);
else
@ -530,18 +544,18 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
//extension reference info
private HashMap getExtMap(){
private HashMap<String, CConfigExtensionReference[]> getExtMap(){
if(fExtMap == null)
fExtMap = new HashMap();
fExtMap = new HashMap<String, CConfigExtensionReference[]>();
return fExtMap;
}
public Map getExtensionMapCopy(){
return (HashMap)getExtMap().clone();
public Map<String, CConfigExtensionReference[]> getExtensionMapCopy(){
return (HashMap<String, CConfigExtensionReference[]>)getExtMap().clone();
}
private ICConfigExtensionReference[] doGet(String extensionPointID){
return (CConfigExtensionReference[])getExtMap().get(extensionPointID);
return getExtMap().get(extensionPointID);
}
@ -634,7 +648,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
// }
private CConfigExtensionReference createRef(String extensionPoint, String extension) {
CConfigExtensionReference extensions[] = (CConfigExtensionReference[])getExtMap().get(extensionPoint);
CConfigExtensionReference extensions[] = getExtMap().get(extensionPoint);
if (extensions == null) {
extensions = new CConfigExtensionReference[1];
getExtMap().put(extensionPoint, extensions);
@ -680,7 +694,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
public void doRemove(ICConfigExtensionReference ext) throws CoreException {
// boolean fireEvent = false;
// synchronized (this) {
CConfigExtensionReference extensions[] = (CConfigExtensionReference[])getExtMap().get(ext.getExtensionPoint());
CConfigExtensionReference extensions[] = getExtMap().get(ext.getExtensionPoint());
for (int i = 0; i < extensions.length; i++) {
if (extensions[i] == ext) {
// System.arraycopy(extensions, i, extensions, i + 1, extensions.length - 1 - i);
@ -713,7 +727,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
private boolean doRemove(String extensionPoint) throws CoreException {
// boolean fireEvent = false;
// synchronized (this) {
CConfigExtensionReference extensions[] = (CConfigExtensionReference[])getExtMap().get(extensionPoint);
CConfigExtensionReference extensions[] = getExtMap().get(extensionPoint);
if (extensions != null) {
getExtMap().remove(extensionPoint);
return true;
@ -740,7 +754,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
}
CExtensionInfo getInfo(CConfigExtensionReference cProjectExtension) {
CExtensionInfo info = (CExtensionInfo)fExtInfoMap.get(cProjectExtension);
CExtensionInfo info = fExtInfoMap.get(cProjectExtension);
if (info == null) {
info = new CExtensionInfo();
fExtInfoMap.put(cProjectExtension, info);
@ -787,14 +801,14 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
private void encodeProjectExtensions(ICStorageElement configRootElement) {
ICStorageElement element;
Iterator extIterator = getExtMap().values().iterator();
Iterator<CConfigExtensionReference[]> extIterator = getExtMap().values().iterator();
while (extIterator.hasNext()) {
CConfigExtensionReference extension[] = (CConfigExtensionReference[])extIterator.next();
CConfigExtensionReference extension[] = extIterator.next();
for (int i = 0; i < extension.length; i++) {
element = configRootElement.createChild(PROJECT_EXTENSION);
element.setAttribute(PROJECT_EXTENSION_ATTR_POINT, extension[i].getExtensionPoint());
element.setAttribute(PROJECT_EXTENSION_ATTR_ID, extension[i].getID());
CExtensionInfo info = (CExtensionInfo)fExtInfoMap.get(extension[i]);
CExtensionInfo info = fExtInfoMap.get(extension[i]);
if (info != null) {
Iterator attribIterator = info.getAttributes().entrySet().iterator();
while (attribIterator.hasNext()) {
@ -824,20 +838,17 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
}
}
}
public void importStorage(String id, ICStorageElement el) throws CoreException{
CStorage storage = getStorageBase();
storage.importStorage(id, el);
public ICStorageElement importStorage(String id, ICStorageElement el) throws CoreException {
return getStorageBase().importStorage(id, el);
}
private void copyExtensionInfo(CConfigurationSpecSettings other){
other.reconcileExtensionSettings(true);
if(other.fExtMap != null && other.fExtMap.size() != 0){
fExtMap = (HashMap)other.fExtMap.clone();
for(Iterator iter = fExtMap.entrySet().iterator(); iter.hasNext();){
Map.Entry entry = (Map.Entry)iter.next();
CConfigExtensionReference refs[] = (CConfigExtensionReference[])entry.getValue();
fExtMap = (HashMap<String, CConfigExtensionReference[]>)other.fExtMap.clone();
for (Map.Entry<String, CConfigExtensionReference[]> entry : fExtMap.entrySet()) {
CConfigExtensionReference refs[] = entry.getValue();
refs = (CConfigExtensionReference[])refs.clone();
for(int i = 0; i < refs.length; i++){
refs[i] = new CConfigExtensionReference(this, refs[i]);
@ -847,10 +858,8 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
}
if(other.fExtInfoMap != null && other.fExtInfoMap.size() != 0){
fExtInfoMap = (HashMap)other.fExtInfoMap.clone();
for(Iterator iter = fExtInfoMap.entrySet().iterator(); iter.hasNext();){
Map.Entry entry = (Map.Entry)iter.next();
CExtensionInfo info = (CExtensionInfo)entry.getValue();
for (Map.Entry<CConfigExtensionReference, CExtensionInfo> entry : fExtInfoMap.entrySet()) {
CExtensionInfo info = entry.getValue();
info = new CExtensionInfo(info);
entry.setValue(info);
}
@ -898,26 +907,26 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
if(refs == null || refs.length == 0){
if(extIds == null || extIds.length == 0)
return null;
return new Set[]{null, new HashSet(Arrays.asList(extIds))};
return new Set[]{null, new HashSet<String>(Arrays.asList(extIds))};
} else if(extIds == null || extIds.length == 0){
Map map = createRefMap(refs);
return new Set[]{new HashSet(map.values()), null};
Map<String, ICConfigExtensionReference> map = createRefMap(refs);
return new Set[]{new HashSet<ICConfigExtensionReference>(map.values()), null};
}
Set idSet = new HashSet(Arrays.asList(extIds));
Set idSetCopy = new HashSet(idSet);
Map refsMap = createRefMap(refs);
Set<String> idSet = new HashSet<String>(Arrays.asList(extIds));
Set<String> idSetCopy = new HashSet<String>(idSet);
Map<String, ICConfigExtensionReference> refsMap = createRefMap(refs);
idSet.removeAll(refsMap.keySet());
refsMap.keySet().removeAll(idSetCopy);
Set extSet = new HashSet(refsMap.values());
Set<ICConfigExtensionReference> extSet = new HashSet<ICConfigExtensionReference>(refsMap.values());
return new Set[]{extSet, idSet};
}
private Map createRefMap(ICConfigExtensionReference refs[]){
Map refsMap = new HashMap(refs.length);
private Map<String, ICConfigExtensionReference> createRefMap(ICConfigExtensionReference refs[]){
Map<String, ICConfigExtensionReference> refsMap = new HashMap<String, ICConfigExtensionReference>(refs.length);
for(int i = 0; i < refs.length; i++){
refsMap.put(refs[i].getID(), refs[i]);
}
@ -936,13 +945,13 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
for(Iterator iter = fExtMap.entrySet().iterator(); iter.hasNext();){
Map.Entry entry = (Map.Entry)iter.next();
ICConfigExtensionReference[] thisRefs = (ICConfigExtensionReference[])entry.getValue();
ICConfigExtensionReference[] otherRefs = (ICConfigExtensionReference[])other.fExtMap.get(entry.getKey());
ICConfigExtensionReference[] otherRefs = other.fExtMap.get(entry.getKey());
if(otherRefs == null)
return thisRefs.length == 0;
if(thisRefs.length != otherRefs.length)
return false;
Map map = createRefMap(thisRefs);
Map<String, ICConfigExtensionReference> map = createRefMap(thisRefs);
map.entrySet().removeAll(createRefMap(otherRefs).entrySet());
if(map.size() != 0)
return false;

View file

@ -7,6 +7,7 @@
*
* Contributors:
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
@ -30,7 +31,7 @@ import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
public class CProjectDescription implements ICProjectDescription, ICDataProxyContainer {
public class CProjectDescription implements ICProjectDescription, ICDataProxyContainer {
private static final String ACTIVE_CFG = "activeConfiguration"; //$NON-NLS-1$
private static final QualifiedName ACTIVE_CFG_PROPERTY = new QualifiedName(CCorePlugin.PLUGIN_ID, ACTIVE_CFG);
private static final String SETTING_CFG = "settingConfiguration"; //$NON-NLS-1$
@ -43,15 +44,15 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
// private String fActiveCfgId;
// private ICConfigurationDescription fIndexCfg;
// private String fIndexCfgId;
private IProject fProject;
private ICSettingsStorage fStorage;
private ICStorageElement fRootStorageElement;
private LinkedHashMap fCfgMap = new LinkedHashMap();
private volatile IProject fProject;
private final ICSettingsStorage fStorage;
private final ICStorageElement fRootStorageElement;
private final HashMap<String, ICConfigurationDescription> fCfgMap = new LinkedHashMap<String, ICConfigurationDescription>();
private boolean fIsReadOnly;
private boolean fIsModified;
private HashMap fPropertiesMap;
private HashMap<QualifiedName, Object> fPropertiesMap;
// private boolean fNeedsActiveCfgIdPersistence;
private boolean fIsLoadding;
private boolean fIsLoading;
private boolean fIsApplying;
private boolean fIsCreating;
@ -151,24 +152,25 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
}
CProjectDescription(IProject project, ICStorageElement element, boolean loadding, boolean isCreating) throws CoreException {
public CProjectDescription(IProject project, ICSettingsStorage storage, ICStorageElement element, boolean loading, boolean isCreating) throws CoreException {
fProject = project;
fStorage = storage;
fRootStorageElement = element;
fIsReadOnly = loadding;
fIsLoadding = loadding;
fIsReadOnly = loading;
fIsLoading = loading;
fActiveCfgInfo = new CfgIdPair(ACTIVE_CFG_PROPERTY);
fSettingCfgInfo = new CfgIdPair(SETTING_CFG_PROPERTY);
fIsCreating = isCreating;
ICStorageElement el = null;
CProjectDescriptionManager mngr = CProjectDescriptionManager.getInstance();
if(loadding){
Map cfgStorMap = mngr.createCfgStorages(this);
for(Iterator iter = cfgStorMap.values().iterator(); iter.hasNext();){
CConfigurationDescriptionCache cache = new CConfigurationDescriptionCache((ICStorageElement)iter.next(), this);
if(loading){
Map<String, ICStorageElement> cfgStorMap = mngr.createCfgStorages(this);
for (ICStorageElement sel : cfgStorMap.values()) {
CConfigurationDescriptionCache cache = new CConfigurationDescriptionCache(sel, this);
configurationCreated(cache);
}
el = getStorage(CProjectDescriptionManager.MODULE_ID, false);
}
@ -176,19 +178,19 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
(CProjectDescriptionPreferences)mngr.getProjectDescriptionWorkspacePreferences(false),
false);
fPropertiesMap = new HashMap();
fPropertiesMap = new HashMap<QualifiedName, Object>();
}
void updateProject(IProject project){
public void updateProject(IProject project){
fProject = project;
}
void loadDatas(){
if(!fIsReadOnly || !fIsLoadding)
public void loadDatas(){
if(!fIsReadOnly || !fIsLoading)
return;
CSettingEntryFactory factory = new CSettingEntryFactory();
for(Iterator iter = fCfgMap.values().iterator(); iter.hasNext();){
for(Iterator<ICConfigurationDescription> iter = fCfgMap.values().iterator(); iter.hasNext();){
CConfigurationDescriptionCache cache = (CConfigurationDescriptionCache)iter.next();
try {
cache.loadData(factory);
@ -201,16 +203,16 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
// doneInitializing();
// fIsLoadding = false;
// fIsLoading = false;
}
boolean applyDatas(SettingsContext context){
public boolean applyDatas(SettingsContext context){
if(!fIsReadOnly || !fIsApplying)
return false;
CSettingEntryFactory factory = new CSettingEntryFactory();
boolean modified = false;
for(Iterator iter = fCfgMap.values().iterator(); iter.hasNext();){
for (Iterator<ICConfigurationDescription> iter = fCfgMap.values().iterator(); iter.hasNext();) {
CConfigurationDescriptionCache cache = (CConfigurationDescriptionCache)iter.next();
try {
if(cache.applyData(factory, context))
@ -230,58 +232,76 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
return modified;
}
void doneApplying(){
/**
* Called when the read-only project description has / is being set
* fIsApplying => false
* setModified (false)
* set the ICSettingsStorage to readonly
*/
public void doneApplying(){
doneInitializing();
fIsApplying = false;
try {
((InternalXmlStorageElement)getRootStorageElement()).setReadOnly(true, false);
getStorageBase().setReadOnly(true, false);
} catch (CoreException e1) {
CCorePlugin.log(e1);
}
setModified(false);
}
void doneLoadding(){
public void doneLoading(){
doneInitializing();
fIsLoadding = false;
fIsLoading = false;
}
void setLoadding(boolean loadding){
fIsLoadding = loadding;
public void setLoading(boolean loading){
fIsLoading = loading;
}
private void doneInitializing(){
for(Iterator iter = fCfgMap.values().iterator(); iter.hasNext();){
CConfigurationDescriptionCache cache = (CConfigurationDescriptionCache)iter.next();
for (ICConfigurationDescription cfg : fCfgMap.values()) {
// FIXME How and why are we down casting to a CConfigurationDescriptionCache. Comments, please!
CConfigurationDescriptionCache cache = (CConfigurationDescriptionCache)cfg;
cache.doneInitialization();
}
if(fIsReadOnly)
fPrefs.setReadOnly(true);
}
public boolean isLoadding(){
return fIsLoadding;
public boolean isLoading(){
return fIsLoading;
}
public boolean isApplying(){
return fIsApplying;
}
public CProjectDescription(CProjectDescription base, boolean saving, ICStorageElement el, boolean isCreating) {
/**
* Create a project description based on another project description
*
* @param base
* @param saving
* @param storage
* @param el
* @param isCreating
*/
public CProjectDescription(CProjectDescription base, boolean saving, ICSettingsStorage storage, ICStorageElement el, boolean isCreating) {
fActiveCfgInfo = new CfgIdPair(base.fActiveCfgInfo);
fSettingCfgInfo = new CfgIdPair(base.fSettingCfgInfo);
fProject = base.fProject;
fStorage = storage;
fRootStorageElement = el;
fIsReadOnly = saving;
fIsLoadding = base.fIsLoadding;
fIsLoading = base.fIsLoading;
fIsApplying = saving || base.fIsApplying;
fIsCreating = isCreating;
fPrefs = new CProjectDescriptionPreferences(base.fPrefs, (CProjectDescriptionPreferences)CProjectDescriptionManager.getInstance().getProjectDescriptionWorkspacePreferences(false), false);
for(Iterator iter = base.fCfgMap.values().iterator(); iter.hasNext();){
for(Iterator<ICConfigurationDescription> iter = base.fCfgMap.values().iterator(); iter.hasNext();){
try {
IInternalCCfgInfo cfgDes = (IInternalCCfgInfo)iter.next();
if(fIsReadOnly){
@ -303,7 +323,29 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
}
}
fPropertiesMap = (HashMap)base.fPropertiesMap.clone();
fPropertiesMap = (HashMap<QualifiedName, Object>)base.fPropertiesMap.clone();
}
/**
* Convert the current CConfigurationDescriptions to cached versions
* This occurs during the SetCProjectDescription Operation
*/
void switchToCachedConfigurationDescriptions() throws CoreException {
for (Map.Entry<String, ICConfigurationDescription> e : fCfgMap.entrySet()) {
if (e.getValue() instanceof CConfigurationDescription) {
CConfigurationDescription cfgDes = (CConfigurationDescription)e.getValue();
CConfigurationData baseData = ((IInternalCCfgInfo)cfgDes).getConfigurationData(false);
CConfigurationDescriptionCache baseCache = null;
if(baseData instanceof CConfigurationDescriptionCache){
baseCache = (CConfigurationDescriptionCache)baseData;
baseData = baseCache.getConfigurationData();
}
CConfigurationDescriptionCache cache = new CConfigurationDescriptionCache(cfgDes, baseData, baseCache,
cfgDes.getSpecSettings(), this, null);
e.setValue(cache);
}
}
}
void configurationCreated(ICConfigurationDescription des){
@ -325,18 +367,18 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
private String getFirstCfgId(){
if(!fCfgMap.isEmpty()){
return (String)fCfgMap.keySet().iterator().next();
return fCfgMap.keySet().iterator().next();
}
return null;
}
public ICConfigurationDescription getConfigurationById(String id) {
return (ICConfigurationDescription)fCfgMap.get(id);
return fCfgMap.get(id);
}
public ICConfigurationDescription getConfigurationByName(String name) {
for(Iterator iter = fCfgMap.values().iterator(); iter.hasNext();){
ICConfigurationDescription cfg = (ICConfigurationDescription)iter.next();
for(Iterator<ICConfigurationDescription> iter = fCfgMap.values().iterator(); iter.hasNext();){
ICConfigurationDescription cfg = iter.next();
if(name.equals(cfg.getName()))
return cfg;
}
@ -344,7 +386,7 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
}
public ICConfigurationDescription[] getConfigurations() {
return (ICConfigurationDescription[])fCfgMap.values().toArray(new ICConfigurationDescription[fCfgMap.size()]);
return fCfgMap.values().toArray(new ICConfigurationDescription[fCfgMap.size()]);
}
public void removeConfiguration(String name) throws WriteAccessException {
@ -395,7 +437,11 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
public ICStorageElement getStorage(String moduleId, boolean create) throws CoreException {
return getStorageBase().getStorage(moduleId, create);
}
public ICStorageElement importStorage(String id, ICStorageElement el) throws UnsupportedOperationException, CoreException {
return getStorageBase().importStorage(id, el);
}
// public boolean containsStorage(String id) throws CoreException {
// return getStorageBase().containsStorage(id);
// }
@ -449,20 +495,24 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
}
}
ICStorageElement getRootStorageElement() throws CoreException{
if(fRootStorageElement == null){
fRootStorageElement = CProjectDescriptionManager.getInstance().createStorage(fProject, true, true, isReadOnly());
}
public ICStorageElement getRootStorageElement() throws CoreException {
if (fRootStorageElement == null)
throw ExceptionFactory.createCoreException("CProjectDescription ICStorageElement == null");
// if(fRootStorageElement == null){
// fRootStorageElement = CProjectDescriptionManager.getInstance().createStorage(fProject, true, true, isReadOnly());
// }
return fRootStorageElement;
}
ICStorageElement doGetCachedRootStorageElement(){
return fRootStorageElement;
}
// ICStorageElement doGetCachedRootStorageElement(){
// return fRootStorageElement;
// }
ICSettingsStorage getStorageBase() throws CoreException{
if(fStorage == null)
fStorage = new CStorage((InternalXmlStorageElement)getRootStorageElement());
// fStorage = new CStorage((InternalXmlStorageElement)getRootStorageElement());
throw ExceptionFactory.createCoreException("CProjectDescription ICSettingsStorage == null");
return fStorage;
}
@ -494,15 +544,14 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
if(fPrefs.isModified())
return true;
if(fRootStorageElement != null
&& ((InternalXmlStorageElement)fRootStorageElement).isDirty())
if(fStorage.isModified())
return true;
for(Iterator iter = fCfgMap.values().iterator(); iter.hasNext();){
if(((ICConfigurationDescription)iter.next()).isModified())
for(ICConfigurationDescription cfgDes : fCfgMap.values())
if(cfgDes.isModified())
return true;
}
return false;
}
@ -521,7 +570,16 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
}
public boolean isReadOnly() {
return fIsReadOnly && !(fIsLoadding || fIsApplying);
return fIsReadOnly && !(fIsLoading || fIsApplying);
}
public void setReadOnly(boolean readOnly, boolean keepModify) {
fIsReadOnly = readOnly;
try {
getStorageBase().setReadOnly(readOnly, keepModify);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
public ICSettingObject getChildSettingById(String id) {
@ -563,7 +621,7 @@ public class CProjectDescription implements ICProjectDescription, ICDataProxyCon
public void removeStorage(String id) throws CoreException {
getStorageBase().removeStorage(id);
}
void switchToCachedAppliedData(CProjectDescription appliedCache){
if(fIsReadOnly)
return;

View file

@ -17,7 +17,7 @@ import org.eclipse.cdt.core.settings.model.ICDescriptionDelta;
import org.eclipse.cdt.core.settings.model.ICSettingObject;
public class CProjectDescriptionDelta implements ICDescriptionDelta {
private List fChildList = new ArrayList();
private List<CProjectDescriptionDelta> fChildList = new ArrayList<CProjectDescriptionDelta>();
private CProjectDescriptionDelta fParent;
private ICSettingObject fSetting;
private ICSettingObject fOldSetting;
@ -55,7 +55,7 @@ public class CProjectDescriptionDelta implements ICDescriptionDelta {
}
public ICDescriptionDelta[] getChildren() {
return (CProjectDescriptionDelta[])fChildList.toArray(new CProjectDescriptionDelta[fChildList.size()]);
return fChildList.toArray(new CProjectDescriptionDelta[fChildList.size()]);
}
public ICSettingObject getOldSetting() {

View file

@ -0,0 +1,402 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
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.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.internal.core.CConfigBasedDescriptorManager;
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType.CProjectDescriptionStorageTypeProxy;
import org.eclipse.cdt.internal.core.settings.model.xml.XmlProjectDescriptionStorage;
import org.eclipse.cdt.internal.core.settings.model.xml2.XmlProjectDescriptionStorage2;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ResourceAttributes;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
/**
* Class that marshals creation of AbstractCProjectDescriptionStorages
* for a given project.
*
* Persist Storage type ID in the .cproject file, and provides backwards compatibility
* for existing project descriptions which don't encode the storage type in the project
* description.
*/
public class CProjectDescriptionStorageManager {
/* Extension point data */
/** CProjectDescriptionStorage extension point ID */
private static final String CPROJ_DESC_STORAGE_EXT_ID = "CProjectDescriptionStorage"; //$NON-NLS-1$
/** storage type element ID */
private static final String CPROJ_STORAGE_TYPE = "CProjectStorageType"; //$NON-NLS-1$
// TODO provide some UI to select this
/** Default project description Storage type */
private static final String DEFAULT_STORAGE_TYPE = XmlProjectDescriptionStorage.STORAGE_TYPE_ID; // XmlProjectDescriptionStorage2.STORAGE_TYPE_ID;
/** Default project description Storage version */
private static final Version DEFAULT_STORAGE_VERSION = XmlProjectDescriptionStorage.STORAGE_DESCRIPTION_VERSION; // XmlProjectDescriptionStorage2.STORAGE_DESCRIPTION_VERSION;
/** Map of StorageType ID -> List of StorageTypes */
private volatile Map<String, List<CProjectDescriptionStorageTypeProxy>> storageTypeMap;
/** Map from IProject -> AbstractCProjectDescriptionStorage which is responsible for (de)serializing the project */
private Map<IProject, AbstractCProjectDescriptionStorage> fDescriptionStorageMap = Collections.synchronizedMap(new HashMap<IProject, AbstractCProjectDescriptionStorage>());
private volatile static CProjectDescriptionStorageManager instance;
private CProjectDescriptionStorageManager() {}
public static CProjectDescriptionStorageManager getInstance() {
if (instance == null) {
synchronized (CProjectDescriptionStorageManager.class) {
if (instance == null)
instance = new CProjectDescriptionStorageManager();
}
}
return instance;
}
/**
* Return a AbstractCProjectDescriptionStorage for a particular project or
* null if none were found and the default storage type wasn't found
* @param project
* @return project description storage or null
*/
public AbstractCProjectDescriptionStorage getProjectDescriptionStorage(IProject project) {
AbstractCProjectDescriptionStorage projStorage = fDescriptionStorageMap.get(project);
if (projStorage == null) {
projStorage = loadProjectStorage(project);
fDescriptionStorageMap.put(project, projStorage);
}
return projStorage;
}
/**
* Sets the Project description by delegating to the appropriate project storage type.
*
* If the storage type returns false on {@link ICProjectDescriptionStorageType#createsCProjectXMLFile()} then
* we create a .cproject file with type id and version.
*
* If no existing project storage is found then we throw a core exception (users should have called
* #getProjectDescriptionStorage(...) before calling this.
*
* @param project
* @param description
* @throws CoreException on failure
*/
public void setProjectDescription(IProject project, ICProjectDescription description, int flags, IProgressMonitor monitor) throws CoreException {
AbstractCProjectDescriptionStorage storage = fDescriptionStorageMap.get(project);
if (storage == null)
throw ExceptionFactory.createCoreException("Can't set ProjectDescription before getProjectDescriptionStorage!");
if (!storage.type.createsCProjectXMLFile())
writeProjectStorageType(project, storage.type);
storage.setProjectDescription(description, flags, monitor);
}
/**
* Persist the type and version of this particular project description storage type
* (for description storages that don't perform this job themselves).
* @param project
* @param type
*/
private void writeProjectStorageType(IProject project, CProjectDescriptionStorageTypeProxy type) throws CoreException{
Document doc;
try {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
// Set the version
ProcessingInstruction instruction = doc.createProcessingInstruction(ICProjectDescriptionStorageType.STORAGE_VERSION_NAME, type.version.toString());
doc.appendChild(instruction);
// Set the type id
Element el = doc.createElement(ICProjectDescriptionStorageType.STORAGE_ROOT_ELEMENT_NAME);
el.setAttribute(ICProjectDescriptionStorageType.STORAGE_TYPE_ATTRIBUTE, type.id);
doc.appendChild(el);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(stream);
transformer.transform(source, result);
InputStream input = new ByteArrayInputStream(stream.toByteArray());
// Set the project description storage type
IFile f = project.getFile(ICProjectDescriptionStorageType.STORAGE_FILE_NAME);
if (!f.exists())
f.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
ensureWritable(f);
if (!f.exists())
f.create(input, true, new NullProgressMonitor());
else
f.setContents(input, IResource.FORCE, new NullProgressMonitor());
} catch (ParserConfigurationException e) {
throw ExceptionFactory.createCoreException(e);
} catch (TransformerConfigurationException e) {
throw ExceptionFactory.createCoreException(e);
} catch (TransformerFactoryConfigurationError e) {
throw ExceptionFactory.createCoreException(e);
} catch (TransformerException e) {
throw ExceptionFactory.createCoreException(e);
}
}
/**
* Given a project, this method attempts to discover the type of the storage
* and return the AbstractCProjectDescriptionStorage responsible for loading it.
*
* @return AbstractCProjectDescription or null if not found
*/
private AbstractCProjectDescriptionStorage loadProjectStorage(IProject project) {
if (storageTypeMap == null)
initExtensionPoints();
// If no project description found, then use the default
Version version = DEFAULT_STORAGE_VERSION;
String storageTypeID = DEFAULT_STORAGE_TYPE;
InputStream stream = null;
try{
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
stream = getInputStreamForIFile(project, ICProjectDescriptionStorageType.STORAGE_FILE_NAME);
if(stream != null){
Document doc = builder.parse(stream);
// Get the first element in the project file
Node rootElement = doc.getFirstChild();
if (rootElement.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE)
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.7")); //$NON-NLS-1$
else
version = new Version(rootElement.getNodeValue());
// Now get the project root element (there should be only one)
NodeList nodes = doc.getElementsByTagName(ICProjectDescriptionStorageType.STORAGE_ROOT_ELEMENT_NAME);
if (nodes.getLength() == 0)
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.9")); //$NON-NLS-1$
Node node = nodes.item(0);
if(node.getNodeType() != Node.ELEMENT_NODE)
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.10")); //$NON-NLS-1$
// If we've got this far, then we're at least dealing with an old style project:
// as this didn't use to provide a type, specify one explicitly
// Choose new style -- separated out storage modules by default as this is backwards compatible...
storageTypeID = XmlProjectDescriptionStorage2.STORAGE_TYPE_ID;
if (((Element)node).hasAttribute(ICProjectDescriptionStorageType.STORAGE_TYPE_ATTRIBUTE))
storageTypeID = ((Element)node).getAttribute(ICProjectDescriptionStorageType.STORAGE_TYPE_ATTRIBUTE);
}
} catch (Exception e) {
// Catch all, if not found, we use the old-style defaults...
} finally {
if(stream != null){
try {
stream.close();
} catch (IOException e) {}
}
}
List<CProjectDescriptionStorageTypeProxy> types = storageTypeMap.get(storageTypeID);
if (types != null) {
for (CProjectDescriptionStorageTypeProxy type : types) {
if (type.isCompatible(version)) {
return type.getProjectDescriptionStorage(type, project, version);
}
}
}
// No type found!
CCorePlugin.log("CProjectDescriptionStorageType: " + storageTypeID + " for version: " + version + " not found!");
return null;
}
private InputStream getInputStreamForIFile(IProject project, String name) throws CoreException {
IFile f = project.getFile(name);
if (f.exists())
return f.getContents(true);
else {
URI location = f.getLocationURI();
if (location != null) {
IFileStore file = EFS.getStore(location);
IFileInfo info = null;
if (file != null) {
info = file.fetchInfo();
if (info != null && info.exists())
return file.openInputStream(EFS.NONE, null);
}
}
}
throw ExceptionFactory.createCoreException("No project des file found...");
}
/*
* Resource Change Callbacks
*/
/**
* Callback indicating that a project has moved
* @param fromProject
* @param toProject
*/
void projectMove(IProject fromProject, IProject toProject) {
AbstractCProjectDescriptionStorage projStorage = fDescriptionStorageMap.get(fromProject);
if (projStorage != null) {
fDescriptionStorageMap.put(toProject, projStorage);
projStorage.projectMove(toProject);
fDescriptionStorageMap.remove(fromProject);
}
// Notify the CConfigBasedDescriptorManager as well
CConfigBasedDescriptorManager.getInstance().projectMove(fromProject, toProject);
}
/**
* Callback indicating project has been closed or deleted
* @param project
*/
void projectClosedRemove(IProject project) {
AbstractCProjectDescriptionStorage projStorage = fDescriptionStorageMap.get(project);
if (projStorage != null)
projStorage.projectCloseRemove();
fDescriptionStorageMap.remove(project);
// Remove from ICDescriptorManager as well
CConfigBasedDescriptorManager.getInstance().projectClosedRemove(project);
}
/**
* Cleanup state
*/
public void shutdown() {
instance = null;
}
/**
* Initialize the project description storage types
*/
private synchronized void initExtensionPoints() {
if (storageTypeMap != null)
return;
Map<String, List<CProjectDescriptionStorageTypeProxy>> m = new HashMap<String, List<CProjectDescriptionStorageTypeProxy>>();
IExtensionPoint extpoint = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, CPROJ_DESC_STORAGE_EXT_ID);
for (IExtension extension : extpoint.getExtensions()) {
for (IConfigurationElement configEl : extension.getConfigurationElements()) {
if (configEl.getName().equalsIgnoreCase(CPROJ_STORAGE_TYPE)) {
CProjectDescriptionStorageTypeProxy type = initStorageType(configEl);
if (type != null) {
if (!m.containsKey(type.id))
m.put(type.id, new LinkedList<CProjectDescriptionStorageTypeProxy>());
m.get(type.id).add(type);
}
}
}
}
storageTypeMap = m;
}
/**
* Initialize a storage type from a configuration element
* @param el
* @return
*/
private static CProjectDescriptionStorageTypeProxy initStorageType(IConfigurationElement el) {
CProjectDescriptionStorageTypeProxy type = null;
try {
type = new CProjectDescriptionStorageTypeProxy(el);
} catch (CoreException e) {
CCorePlugin.log("Couldn't instantiate CProjectDescriptionStorageType " +
el.getDeclaringExtension().getNamespaceIdentifier() + " " + e.getMessage());
} catch (IllegalArgumentException e) {
CCorePlugin.log("Failed to load CProjectDescriptionStorageType " +
el.getDeclaringExtension().getNamespaceIdentifier() + " " + e.getMessage());
}
return type;
}
/**
* Helper method to ensure that a resource is writable. This means: <br/>
* - If the resource doesn't exist, it can be created (its parent is made writable) <br/>
* - If the resource exists and its a file, it's made writable <br/>
* - If the resource exists and its a directory, it and its children
* are made writable
* @param resource
* @throws CoreException on failure
*/
public static void ensureWritable(IResource resource) throws CoreException {
if (!resource.exists())
resource.refreshLocal(IResource.DEPTH_INFINITE, null);
if (!resource.exists()) {
// If resource doesn't exist, ensure it can be created.
ResourceAttributes parentAttr = resource.getParent().getResourceAttributes();
if (parentAttr.isReadOnly()) {
parentAttr.setReadOnly(false);
resource.getParent().setResourceAttributes(parentAttr);
}
} else {
// If resource exists, ensure it and children are writable
resource.accept(new IResourceVisitor() {
public boolean visit(IResource resource) throws CoreException {
ResourceAttributes resAttr = resource.getResourceAttributes();
if (resAttr.isReadOnly()) {
resAttr.setReadOnly(false);
resource.setResourceAttributes(resAttr);
}
return true;
}
});
}
}
}

View file

@ -1,192 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Intel Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.cdt.core.settings.model.ICSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.core.runtime.CoreException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class CStorage implements ICSettingsStorage{
private static final String MODULE_ELEMENT_NAME = "storageModule"; //$NON-NLS-1$
private static final String MODULE_ID_ATTRIBUTE = "moduleId"; //$NON-NLS-1$
Element fElement;
private Map fStorageElementMap = new HashMap();
private boolean fChildrenInited;
private boolean fIsReadOnly;
private boolean fIsDirty;
public CStorage(Element element, boolean isReadOnly){
fElement = element;
fIsReadOnly = isReadOnly;
}
public CStorage(InternalXmlStorageElement element){
fElement = element.fElement;
fIsReadOnly = element.isReadOnly();
element.storageCreated(this);
}
public boolean isReadOnly(){
return fIsReadOnly;
}
private void initChildren(){
if(fChildrenInited)
return;
fChildrenInited = true;
NodeList children = fElement.getChildNodes();
int size = children.getLength();
for(int i = 0; i < size; i++){
Node node = children.item(i);
if(node.getNodeType() != Node.ELEMENT_NODE)
continue;
if(!MODULE_ELEMENT_NAME.equals(node.getNodeName()))
continue;
Element element = (Element)node;
String moduleId = element.getAttribute(MODULE_ID_ATTRIBUTE).trim();
if(moduleId.length() == 0)
continue;
createAddStorageElement(moduleId, element);
}
}
private InternalXmlStorageElement createAddStorageElement(String id, Element element){
InternalXmlStorageElement se = createStorageElement(element, fIsReadOnly);
fStorageElementMap.put(id, se);
return se;
}
public static InternalXmlStorageElement createStorageElement(Element el, boolean isReadOnly){
return new InternalXmlStorageElement(el, null, false, new String[]{MODULE_ID_ATTRIBUTE}, null, isReadOnly);
}
// public ICStorageElement getStorage(String id){
// return getStorage(id, true);
// }
public boolean containsStorage(String id) throws CoreException {
return getStorage(id, false) != null;
}
public ICStorageElement importStorage(String id, ICStorageElement el) throws UnsupportedOperationException {
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
removeStorage(id);
InternalXmlStorageElement xmlStEl = (InternalXmlStorageElement)el;
Element xmlEl = xmlStEl.fElement;
Document thisDoc = fElement.getOwnerDocument();
Document otherDoc = xmlEl.getOwnerDocument();
if(!thisDoc.equals(otherDoc)){
xmlEl = (Element)thisDoc.importNode(xmlEl, true);
}
Element newEl = thisDoc.createElement(MODULE_ELEMENT_NAME);
NodeList nl = xmlEl.getChildNodes();
for(int i = 0; i < nl.getLength(); i++){
Node child = nl.item(i).cloneNode(true);
newEl.appendChild(child);
}
xmlEl = newEl;
xmlEl = (Element)fElement.appendChild(xmlEl);
xmlEl.setAttribute(MODULE_ID_ATTRIBUTE, id);
fIsDirty = true;
return createAddStorageElement(id, xmlEl);
}
public ICStorageElement getStorage(String id, boolean create){
initChildren();
InternalXmlStorageElement se = (InternalXmlStorageElement)fStorageElementMap.get(id);
if(se == null && create){
// if(fIsReadOnly)
// throw ExceptionFactory.createIsReadOnlyException();
fIsDirty = true;
Document doc = fElement.getOwnerDocument();
Element child = createStorageXmlElement(doc, id);
fElement.appendChild(child);
se = createAddStorageElement(id, child);
}
return se;
}
public static Element createStorageXmlElement(Document doc, String storageId){
Element child = doc.createElement(MODULE_ELEMENT_NAME);
child.setAttribute(MODULE_ID_ATTRIBUTE, storageId);
return child;
}
public void removeStorage(String id){
initChildren();
InternalXmlStorageElement se = (InternalXmlStorageElement)fStorageElementMap.remove(id);
if(se != null){
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
fIsDirty = true;
fElement.removeChild(se.fElement);
se.removed();
}
}
public boolean isDirty(){
if(fIsDirty)
return true;
for(Iterator iter = fStorageElementMap.values().iterator(); iter.hasNext();){
InternalXmlStorageElement el = (InternalXmlStorageElement)iter.next();
if(el.isDirty())
return true;
}
return false;
}
void setReadOnly(boolean readOnly, boolean keepModify){
fIsReadOnly = readOnly;
fIsDirty &= keepModify;
for(Iterator iter = fStorageElementMap.values().iterator(); iter.hasNext();){
InternalXmlStorageElement el = (InternalXmlStorageElement)iter.next();
el.setReadOnly(readOnly, keepModify);
}
}
public void setDirty(boolean isDirty){
fIsDirty = isDirty;
if(!fIsDirty){
for(Iterator iter = fStorageElementMap.values().iterator(); iter.hasNext();){
InternalXmlStorageElement el = (InternalXmlStorageElement)iter.next();
el.setDirty(false);
}
}
}
}

View file

@ -20,7 +20,7 @@ import org.eclipse.cdt.core.settings.model.util.PathSettingsContainer;
import org.eclipse.core.runtime.IPath;
public class CfgProxyCache implements IProxyCache {
private HashMap fProxyMap = new HashMap();
private HashMap<String, CDataProxy> fProxyMap = new HashMap<String, CDataProxy>();
private PathSettingsContainer fPathContainer;
CfgProxyCache(PathSettingsContainer pathDesContainer){
@ -69,21 +69,21 @@ public class CfgProxyCache implements IProxyCache {
}
public CDataProxy[] getCachedProxies() {
Collection c = fProxyMap.values();
return (CDataProxy[])c.toArray(new CDataProxy[c.size()]);
Collection<CDataProxy> c = fProxyMap.values();
return c.toArray(new CDataProxy[c.size()]);
}
public CDataProxy getCachedProxy(String id) {
return (CDataProxy)fProxyMap.get(id);
return fProxyMap.get(id);
}
public void removeCachedProxy(String id) {
CDataProxy proxy = (CDataProxy)fProxyMap.get(id);
CDataProxy proxy = fProxyMap.get(id);
removeCachedProxy(proxy);
}
public Map getCachedProxiesMap() {
return (Map)fProxyMap.clone();
public Map<String, CDataProxy> getCachedProxiesMap() {
return (Map<String, CDataProxy>)fProxyMap.clone();
}
public CDataProxy getCachedProxy(CDataObject data) {

View file

@ -0,0 +1,161 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corp. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.osgi.framework.Version;
/**
* Interface defining an ICProjectDescriptionStorageType
* used as a factory for creating project description storages
* for a give project
*/
public interface ICProjectDescriptionStorageType {
/** The file name in which the storage type and version are stored */
public static final String STORAGE_FILE_NAME = ".cproject"; //$NON-NLS-1$
/** The document version attribute */
public static final String STORAGE_VERSION_NAME = "fileVersion"; //$NON-NLS-1$
/** The root element in a .cproject file */
public static final String STORAGE_ROOT_ELEMENT_NAME = "cproject"; //$NON-NLS-1$
/** The document's storage type id attribute in the root element */
public static final String STORAGE_TYPE_ATTRIBUTE = "storage_type_id"; //$NON-NLS-1$
/**
* The type as defined in the CProjectDescriptionStorage extension point, wraps the
* implemented ICProjectDescriptionType to provide proxy object for use by CProjectDescriptionStorageManager
*/
public static final class CProjectDescriptionStorageTypeProxy implements ICProjectDescriptionStorageType {
private static final String ATTR_ID = "id"; //$NON-NLS-1$
private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
private static final String ATTR_NAME = "name"; //$NON-NLS-1$
private static final String ATTR_VERSION = "version"; //$NON-NLS-1$
private static final String ATTR_MAX_VERSION = "max_version"; //$NON-NLS-1$
private static final String ATTR_MIN_VERSION = "min_version"; //$NON-NLS-1$
public final String id;
public final String name;
public final ICProjectDescriptionStorageType storageType;
public final Version version;
public final Version max_version;
public final Version min_version;
/**
* CProjectDescription Proxy Type.
* @param el
* @throws CoreException
* @throws IllegalArgumentException
*/
public CProjectDescriptionStorageTypeProxy(IConfigurationElement el) throws CoreException, IllegalArgumentException {
this (el.getNamespaceIdentifier() + "." + getString(el, ATTR_ID, null), //$NON-NLS-1$
getString(el, ATTR_NAME, null),
(ICProjectDescriptionStorageType)el.createExecutableExtension(ATTR_CLASS),
getVersion(el, ATTR_VERSION, null),
getVersion(el, ATTR_MIN_VERSION, Version.emptyVersion),
getVersion(el, ATTR_MAX_VERSION, Version.emptyVersion));
}
/**
* Constructor verifies that version is in the range (min_version, max_version]
* @param name
* @param storageType
* @param version
* @param min_version
* @param max_version
*/
public CProjectDescriptionStorageTypeProxy(String id, String name, ICProjectDescriptionStorageType storageType, Version version,
Version min_version, Version max_version) {
this.id = id;
this.name = name;
this.storageType = storageType;
this.version = version;
this.min_version = min_version;
this.max_version = max_version == Version.emptyVersion ? version : max_version;
if (min_version != Version.emptyVersion && version.compareTo(min_version) <= 0)
throw new IllegalArgumentException("CProjectDescriptionStorageType Version: " + version +
" must be > that min_version: " + min_version);
if (max_version != Version.emptyVersion && version.compareTo(max_version) > 0)
throw new IllegalArgumentException("CProjectDescriptionStorageType Version: " + version +
" must be < that max_version: " + max_version);
}
/** Indicates if this type is compatible with the provided version */
public boolean isCompatible(Version version) {
if (version.compareTo(max_version) > 0)
return false;
if (version.compareTo(min_version) <= 0)
return false;
return true;
}
public boolean createsCProjectXMLFile() {
return storageType.createsCProjectXMLFile();
}
public AbstractCProjectDescriptionStorage getProjectDescriptionStorage(CProjectDescriptionStorageTypeProxy type, IProject project, Version version) {
return storageType.getProjectDescriptionStorage(type, project, version);
}
private static Version getVersion(IConfigurationElement element, String id, Version defaultValue) throws IllegalArgumentException{
if (defaultValue == null)
return new Version(element.getAttribute(id));
Version v = defaultValue;
try {
v = new Version(element.getAttribute(id));
} catch (Exception e) {
// If an exception occurred return the default value
}
return v;
}
private static String getString(IConfigurationElement element, String id, String defaultValue) throws IllegalArgumentException {
String val = element.getAttribute(id);
if (val != null)
return val;
if (defaultValue != null)
return defaultValue;
throw new IllegalArgumentException("Couldn't find value for extension attribute " + id);
}
}
/**
* Return a new storage instance to be for persisting / loading cproject descriptions
* from the passed in IProject
* @param type proxy which created this
* @param project - IProject
* @param version - Version number of the description as reported by the AbstractCProjectDescriptionStorage
* on last save
* @return AbstractCProjectDescriptionStorage
*/
public AbstractCProjectDescriptionStorage getProjectDescriptionStorage(CProjectDescriptionStorageTypeProxy type, IProject project, Version version);
/**
* Method indicating whether this project storage type writes a .cproject file.
*
* If this method returns true then you must ensure that the .cproject file is an
* xml file with a {@link #STORAGE_VERSION_NAME} tag and {@link #STORAGE_TYPE_ATTRIBUTE} id
* in the {@link #STORAGE_ROOT_ELEMENT_NAME} e.g.:
* <pre>
* &lt;?xml version="1.0" encoding="UTF-8"?&gt;
* &lt;?fileVersion 4.0.0?&gt;
* &lt;cproject storageType="storage_type_id"&gt; ....
* &lt;/cproject&gt;
* </pre>
*
* If this method returns false, then the CProjectDescriptionStorageType creates
* a '.cproject' containing this data
*
* @return boolean indicating whether this storage type writes a (compatible) .cproject file
* @see CProjectDescriptionStorageTypeProxy
*
*/
public boolean createsCProjectXMLFile();
}

View file

@ -520,6 +520,15 @@ public class MultiConfigDescription extends MultiItemsHolder implements
return true;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.core.settings.model.ICSettingsStorage#setReadOnly(boolean, boolean)
*/
public void setReadOnly(boolean readOnly, boolean keepModify) {
for (ICConfigurationDescription cfg : fCfgs)
cfg.setReadOnly(readOnly, keepModify);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.settings.model.ICSettingObject#isValid()
*/
@ -538,6 +547,14 @@ public class MultiConfigDescription extends MultiItemsHolder implements
System.out.println("Bad multi access: MultiConfigDescription.getStorage()");
return null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.settings.model.ICSettingsStorage#getStorage(java.lang.String, boolean)
*/
public ICStorageElement importStorage(String id, ICStorageElement el) throws UnsupportedOperationException, CoreException {
System.out.println("Bad multi access: MultiConfigDescription.importStorage()");
return null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.settings.model.ICSettingsStorage#removeStorage(java.lang.String)

View file

@ -40,15 +40,23 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
* This resource change handler notices external changes to the cdt projects
* and associated project storage metadata files, as well as changes to
* source folders
*
*
* delegates parts of it's functionality to CProjectDescriptio
*/
public class ResourceChangeHandler extends ResourceChangeHandlerBase implements ISaveParticipant {
CProjectDescriptionManager fMngr = CProjectDescriptionManager.getInstance();
class RcMoveHandler implements IResourceMoveHandler {
Map fProjDesMap = new HashMap();
Set fRemovedProjSet = new HashSet();
Map<IProject, ICProjectDescription> fProjDesMap = new HashMap<IProject, ICProjectDescription>();
Set<IProject> fRemovedProjSet = new HashSet<IProject>();
public void handleProjectClose(IProject project) {
fMngr.setLoaddedDescription(project, null, true);
fMngr.projectClosedRemove(project);
}
private ICExclusionPatternPathEntry[] checkMove(IPath fromFullPath, IPath toFullPath, ICExclusionPatternPathEntry[] entries){
@ -63,28 +71,17 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements
return modified ? entries : null;
}
@SuppressWarnings("fallthrough")
public boolean handleResourceMove(IResource fromRc, IResource toRc) {
boolean proceed = true;
IProject fromProject = fromRc.getProject();
IProject toProject = toRc.getProject();
switch(toRc.getType()){
case IResource.PROJECT:{
ICProjectDescription des = getProjectDescription(fromProject, false);
fMngr.projectMove(fromProject, toProject);
fRemovedProjSet.add(fromProject);
if(des != null){
((CProjectDescription)des).updateProject(toProject);
synchronized (fMngr) {
fMngr.setLoaddedDescription(fromProject, null, true);
fMngr.setLoaddedDescription(toProject, des, true);
}
fProjDesMap.put(toProject, des);
ICConfigurationDescription[] cfgs = des.getConfigurations();
for(int i = 0; i < cfgs.length; i++){
cfgs[i].getConfigurationData();
}
}
}
break;
break;
case IResource.FOLDER:{
IPath fromFullPath = fromRc.getFullPath();
IPath toFullPath = toRc.getFullPath();
@ -155,7 +152,7 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements
private ICProjectDescription getProjectDescription(IResource rc, boolean load){
IProject project = rc.getProject();
ICProjectDescription des = (ICProjectDescription)fProjDesMap.get(project);
ICProjectDescription des = fProjDesMap.get(project);
if(des == null && !fProjDesMap.containsKey(project)){
int flags = load ? 0 : CProjectDescriptionManager.GET_IF_LOADDED;
flags |= CProjectDescriptionManager.INTERNAL_GET_IGNORE_CLOSE;
@ -171,13 +168,13 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements
fProjDesMap.put(project, des);
}
private List checkRemove(IPath rcFullPath, ICExclusionPatternPathEntry[] entries){
List updatedList = null;
private List<ICExclusionPatternPathEntry> checkRemove(IPath rcFullPath, ICExclusionPatternPathEntry[] entries){
List<ICExclusionPatternPathEntry> updatedList = null;
int num = 0;
for(int k = 0; k < entries.length; k++){
if(entries[k].getFullPath().equals(rcFullPath)){
if(updatedList == null){
updatedList = new ArrayList(Arrays.asList(entries));
updatedList = new ArrayList<ICExclusionPatternPathEntry>(Arrays.asList(entries));
}
updatedList.remove(num);
} else {
@ -187,12 +184,13 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements
return updatedList;
}
@SuppressWarnings("fallthrough")
public boolean handleResourceRemove(IResource rc) {
boolean proceed = true;
IProject project = rc.getProject();
switch(rc.getType()){
case IResource.PROJECT:
fMngr.setLoaddedDescription(project, null, true);
fMngr.projectClosedRemove(project);
fRemovedProjSet.add(project);
proceed = false;
break;
@ -205,11 +203,11 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements
for(int i = 0; i < cfgDess.length; i++){
ICConfigurationDescription cfg = cfgDess[i];
ICExclusionPatternPathEntry[] entries = cfg.getSourceEntries();
List updatedList = checkRemove(rcFullPath, entries);
List<ICExclusionPatternPathEntry> updatedList = checkRemove(rcFullPath, entries);
if(updatedList != null){
try {
cfg.setSourceEntries((ICSourceEntry[])updatedList.toArray(new ICSourceEntry[updatedList.size()]));
cfg.setSourceEntries(updatedList.toArray(new ICSourceEntry[updatedList.size()]));
} catch (WriteAccessException e) {
CCorePlugin.log(e);
} catch (CoreException e) {
@ -241,7 +239,9 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements
try {
cfgDess[i].removeResourceDescription(rcDescription);
} catch (WriteAccessException e) {
CCorePlugin.log(e);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
}
@ -254,28 +254,28 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements
}
public void done() {
for(Iterator iter = fProjDesMap.entrySet().iterator(); iter.hasNext();){
Map.Entry entry = (Map.Entry)iter.next();
for(Iterator<Map.Entry<IProject, ICProjectDescription>> iter = fProjDesMap.entrySet().iterator(); iter.hasNext();){
Map.Entry<IProject, ICProjectDescription> entry = iter.next();
if(fRemovedProjSet.contains(entry.getKey())){
iter.remove();
} else {
ICProjectDescription des = (ICProjectDescription)entry.getValue();
ICProjectDescription des = entry.getValue();
if(des != null && !des.isModified())
iter.remove();
}
}
if(fProjDesMap.size() != 0){
fMngr.runWspModification(new IWorkspaceRunnable(){
if(!fProjDesMap.isEmpty()){
CProjectDescriptionManager.runWspModification(new IWorkspaceRunnable(){
public void run(IProgressMonitor monitor) throws CoreException {
for(Iterator iter = fProjDesMap.entrySet().iterator(); iter.hasNext();){
Map.Entry entry = (Map.Entry)iter.next();
IProject project = (IProject)entry.getKey();
for(Iterator<Map.Entry<IProject, ICProjectDescription>> iter = fProjDesMap.entrySet().iterator(); iter.hasNext();){
Map.Entry<IProject, ICProjectDescription> entry = iter.next();
IProject project = entry.getKey();
if(!project.isOpen())
continue;
ICProjectDescription des = (ICProjectDescription)entry.getValue();
ICProjectDescription des = entry.getValue();
try {
fMngr.setProjectDescription(project, des);
@ -328,7 +328,7 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements
}
@Override
protected void doHahdleResourceMove(IResourceChangeEvent event,
protected void doHandleResourceMove(IResourceChangeEvent event,
IResourceMoveHandler handler) {
switch(event.getType()){
case IResourceChangeEvent.POST_CHANGE:
@ -348,34 +348,13 @@ public class ResourceChangeHandler extends ResourceChangeHandlerBase implements
IResourceDelta child = children[k];
IResource rc = child.getResource();
if(rc.getType() != IResource.FILE)
continue;
if(!CProjectDescriptionManager.STORAGE_FILE_NAME.equals(rc.getName()))
continue;
//the .cproject file is changed
if((child.getKind() & IResourceDelta.REMOVED) == IResourceDelta.REMOVED){
//project file does not exist or corrupted, remove
((RcMoveHandler)handler).setProjectDescription(rc.getProject(), null);
continue;
}
try {
CProjectDescription des = CProjectDescriptionManager.getInstance().checkExternalProjectFileModification(rc);
if(des != null){
((RcMoveHandler)handler).setProjectDescription(rc.getProject(), des);
}
} catch (CoreException e) {
CCorePlugin.log(e);
//project file does not exist or corrupted, remove
((RcMoveHandler)handler).setProjectDescription(rc.getProject(), null);
}
continue;
}
}
}
break;
}
super.doHahdleResourceMove(event, handler);
super.doHandleResourceMove(event, handler);
}

View file

@ -7,6 +7,7 @@
*
* Contributors:
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
@ -17,85 +18,103 @@ import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICDescriptionDelta;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.settings.model.ICSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.model.CModelOperation;
import org.eclipse.cdt.internal.core.settings.model.xml.XmlProjectDescriptionStorage;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
* The operation which actually causes the CProjectDescription to be serialized
*
* This organizes the firing the {@link CProjectDescriptionEvent}s to all listeners
*/
public class SetCProjectDescriptionOperation extends CModelOperation {
private CProjectDescription fSetDescription;
private int fFlags;
/** The ProjectDescription Storage being used for this project description */
private final AbstractCProjectDescriptionStorage fPrjDescStorage;
private final CProjectDescription fSetDescription;
private final int fFlags;
SetCProjectDescriptionOperation(ICProject cProject, CProjectDescription description, int flags){
/**
* Operation used for persisting the new CProjectDescription
* @param prjDescStorage
* @param cProject
* @param description
* @param flags
*/
public SetCProjectDescriptionOperation(AbstractCProjectDescriptionStorage prjDescStorage, ICProject cProject, CProjectDescription description, int flags){
super(cProject);
this.fPrjDescStorage = prjDescStorage;
fFlags = flags;
fSetDescription = description;
}
@Override
protected void executeOperation() throws CModelException {
CProjectDescriptionManager mngr = CProjectDescriptionManager.getInstance();
ICProject cProject = (ICProject)getElementToProcess();
final IProject project = cProject.getProject();
CProjectDescription fOldDescriptionCache = (CProjectDescription)mngr.getProjectDescription(project, false);
CProjectDescriptionEvent event = mngr.createAboutToApplyEvent(fSetDescription, fOldDescriptionCache);
mngr.notifyListeners(event);
ICProjectDescription fOldDescriptionCache = mngr.getProjectDescription(project, false);
AbstractCProjectDescriptionStorage.fireAboutToApplyEvent(fSetDescription, fOldDescriptionCache);
CProjectDescription fNewDescriptionCache = null;
SettingsContext context = new SettingsContext(project);
boolean modified = false;
if(fSetDescription != null){
InternalXmlStorageElement el = null;
ICStorageElement newEl = null;
ICSettingsStorage newStorage = null;
try {
InternalXmlStorageElement base = (InternalXmlStorageElement)fSetDescription.getRootStorageElement();
modified = base.isDirty();
el = mngr.copyElement(base, false);
} catch (CoreException e2) {
ICStorageElement base = fSetDescription.getRootStorageElement();
modified = fSetDescription.isModified();
// el = base;
// FIXME JBB there is deep magic going on here. The project descriptions are being
// changed in non-obvious ways
newEl = fPrjDescStorage.copyElement(base, false);
newStorage = fPrjDescStorage.getStorageForElement(newEl);
} catch (CoreException e) {
CCorePlugin.log(e);
}
boolean creating = fOldDescriptionCache != null ? fOldDescriptionCache.isCdtProjectCreating() : true;
if(creating)
creating = fSetDescription.isCdtProjectCreating();
if(!fSetDescription.isValid() && (!mngr.isEmptyCreatingDescriptionAllowed() || !creating))
throw new CModelException(ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.17") + project.getName())); //$NON-NLS-1$
fNewDescriptionCache = new CProjectDescription(fSetDescription, true, el, creating);
fNewDescriptionCache = new CProjectDescription(fSetDescription, true, newStorage, newEl, creating);
boolean envStates[] = getEnvStates(fNewDescriptionCache);
try {
mngr.setDescriptionApplying(project, fNewDescriptionCache);
fPrjDescStorage.setThreadLocalProjectDesc(fNewDescriptionCache);
modified |= fNewDescriptionCache.applyDatas(context);
} finally {
mngr.clearDescriptionApplying(project);
fPrjDescStorage.setThreadLocalProjectDesc(null);
setEnvStates(fNewDescriptionCache, envStates);
}
} else {
modified = fOldDescriptionCache != null;
}
ICDescriptionDelta delta = mngr.createDelta(fNewDescriptionCache, fOldDescriptionCache);
mngr.checkRemovedConfigurations(delta);
// Generate the c element deltas
ICElementDelta cElementDeltas[] = mngr.generateCElementDeltas(cProject, delta);
for (ICElementDelta d : cElementDeltas)
addDelta(d);
if (cElementDeltas.length > 0) {
for (int i = 0; i < cElementDeltas.length; i++) {
addDelta(cElementDeltas[i]);
}
}
mngr.setLoaddedDescription(project, fNewDescriptionCache, true);
if(fSetDescription != null)
fSetDescription.switchToCachedAppliedData(fNewDescriptionCache);
try {
final IProjectDescription eDes = context.getEclipseProjectDescription();
if(mngr.checkHandleActiveCfgChange(fNewDescriptionCache, fOldDescriptionCache, eDes, new NullProgressMonitor())){
@ -104,58 +123,83 @@ public class SetCProjectDescriptionOperation extends CModelOperation {
} catch (CoreException e2) {
CCorePlugin.log(e2);
}
event = mngr.createDataAppliedEvent(fNewDescriptionCache, fOldDescriptionCache, fSetDescription, delta);
mngr.notifyListeners(event);
cProject.close();
// fNewDescriptionCache is still writable and may be written to at this point
AbstractCProjectDescriptionStorage.fireDataAppliedEvent(fNewDescriptionCache, fOldDescriptionCache, fSetDescription, delta);
cProject.close(); // Why?
// ExternalSettingsManager.getInstance().updateDepentents(delta);
if(fNewDescriptionCache != null){
fNewDescriptionCache.doneApplying();
}
event = mngr.createAppliedEvent(fNewDescriptionCache, fOldDescriptionCache, fSetDescription, delta);
// Set 'fSetProjectDescription' as the new read-only project description on the block
fPrjDescStorage.setCurrentDescription(fNewDescriptionCache, true);
CProjectDescriptionEvent event = AbstractCProjectDescriptionStorage.createAppliedEvent(fNewDescriptionCache, fOldDescriptionCache, fSetDescription, delta);
mngr.notifyListeners(event);
try {
IWorkspaceRunnable toRun = null;
if(fNewDescriptionCache != null && !CProjectDescriptionManager.checkFlags(fFlags, ICProjectDescriptionManager.SET_NO_SERIALIZE)){
if(modified || isPersistentCoreSettingChanged(event)){
context.addWorkspaceRunnable(mngr.createDesSerializationRunnable(fNewDescriptionCache));
toRun = fPrjDescStorage.createDesSerializationRunnable();
if (toRun != null)
context.addWorkspaceRunnable(toRun);
}
}
IWorkspaceRunnable toRun = context.createOperationRunnable();
toRun = context.createOperationRunnable();
if(toRun != null)
mngr.runWspModification(toRun, new NullProgressMonitor());
CProjectDescriptionManager.runWspModification(toRun, getSchedulingRule(), new NullProgressMonitor());
} catch (CoreException e) {
throw new CModelException(e);
}
}
// Can't use project scoped rule see CProjectDescriptionBasicTests...
// /*
// * Instead of using the workspace scheduling rule, use a more refined project scoped rule.
// * This must contain the rule in CConfigBasedDescriptor.setApply(...)
// * (non-Javadoc)
// * @see org.eclipse.cdt.internal.core.model.CModelOperation#getSchedulingRule()
// */
// @Override
// public ISchedulingRule getSchedulingRule() {
//// return null;
// return fPrjDescStorage.getProject();
// }
private static boolean isPersistentCoreSettingChanged(CProjectDescriptionEvent event){
ICDescriptionDelta delta = event.getProjectDelta();
if(delta == null)
return false;
if(delta.getDeltaKind() != ICDescriptionDelta.CHANGED)
return true;
if(delta.getChildren().length != 0)
return true;
int flags = delta.getChangeFlags();
int flags = delta.getChangeFlags();
if(flags != 0 && flags != ICDescriptionDelta.ACTIVE_CFG)
return true;
return false;
}
@Override
public boolean isReadOnly() {
return false;
}
/**
* Returns a boolean array corresponding to whether the environemnt is
* dirty on the configurations in the array returned by projDesc.getConfigurations()
* @param pd
* @return boolean[] indicating which configurations have a dirty environment
*/
private boolean[] getEnvStates(CProjectDescription pd) {
ICConfigurationDescription[] cfs = pd.getConfigurations();
boolean[] result = new boolean[cfs.length];
@ -165,19 +209,28 @@ public class SetCProjectDescriptionOperation extends CModelOperation {
CConfigurationSpecSettings ss = ((IInternalCCfgInfo)cfs[i]).getSpecSettings();
if (ss != null && ss.getEnvironment() != null)
result[i] = ss.getEnvironment().isDirty();
} catch (CoreException e) {};
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
}
return result;
}
/**
* Set
* @param pd
* @param data
*/
private void setEnvStates(CProjectDescription pd, boolean[] data) {
ICConfigurationDescription[] cfs = pd.getConfigurations();
if (cfs == null || data == null)
return;
for (int i=0; i<cfs.length; i++) {
if (data.length <= i)
break; // unprobable;
if (data.length <= i) {
CCorePlugin.log("Error: setEnvStates: different number of configurations as there are envDatas...", new Exception()); //$NON-NLS-1$
break;
}
if (!data[i])
continue; // write only TRUE values
if (cfs[i] instanceof IInternalCCfgInfo) {
@ -185,7 +238,9 @@ public class SetCProjectDescriptionOperation extends CModelOperation {
CConfigurationSpecSettings ss = ((IInternalCCfgInfo)cfs[i]).getSpecSettings();
if (ss != null && ss.getEnvironment() != null)
ss.getEnvironment().setDirty(true);
} catch (CoreException e) {};
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
}
}

View file

@ -28,7 +28,7 @@ public final class SettingsContext implements IModificationContext{
private int fFlags;
SettingsContext(IProject project){
public SettingsContext(IProject project){
fProject = project;
}
@ -76,7 +76,7 @@ public final class SettingsContext implements IModificationContext{
getCompositeWorkspaceRunnable(true).add(runnable);
}
IWorkspaceRunnable createOperationRunnable() {
public IWorkspaceRunnable createOperationRunnable() {
CompositeWorkspaceRunnable result = new CompositeWorkspaceRunnable(null);
IWorkspaceRunnable r = getSetEclipseProjectDescriptionRunnable();

View file

@ -0,0 +1,192 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.core.runtime.CoreException;
/**
* Implementation of ICStorageElement which wraps another ICStorageElement
* in synchronization. This is similar to the Collections.synchronized
* methods.
*
* If two threads structurally modify the same part of the tree,
* then this may still fail.
*
* This is used by CConfigBaseDescriptor to allow multiple threads
* to modify the same storage elements (mostly) safely. See the associated
* tests in the CDescriptor testsuite
*
* TODO best effort concurrent modification exception
*/
public class SynchronizedStorageElement implements ICStorageElement {
private final Object fLock;
private final ICStorageElement fEl;
private SynchronizedStorageElement(ICStorageElement el, Object lock) {
this.fEl = el;
this.fLock = lock;
}
private SynchronizedStorageElement(ICStorageElement el) {
this.fEl = el;
this.fLock = this;
}
/**
* Return the original ICStorageElement stored backing this Proxy
* ICStorageElement
* @return ICStorageElement original storage element
*/
public ICStorageElement getOriginalElement() {
synchronized (fLock) {
return fEl;
}
}
/**
* Create a synchronized storage element from an existing storage element
* All access to this ICStorageElement tree will be synchronized on the
* returned ICStorageElement object.
* @param el
* @return SynchronizedStorageElement wrapping the original ICStorageElement
*/
public static SynchronizedStorageElement synchronizedElement(ICStorageElement el) {
return new SynchronizedStorageElement(el);
}
public void clear() {
synchronized (fLock) {
fEl.clear();
}
}
public ICStorageElement createChild(String name) {
synchronized (fLock) {
return new SynchronizedStorageElement(fEl.createChild(name), fLock);
}
}
public ICStorageElement createCopy() throws UnsupportedOperationException,
CoreException {
synchronized (fLock) {
return synchronizedElement(fEl.createCopy());
}
}
public boolean equals(ICStorageElement other) {
synchronized (fLock) {
if (other instanceof SynchronizedStorageElement)
other = ((SynchronizedStorageElement)other).fEl;
return fEl.equals(other);
}
}
public String getAttribute(String name) {
synchronized (fLock) {
return fEl.getAttribute(name);
}
}
public String[] getAttributeNames() {
synchronized (fLock) {
return fEl.getAttributeNames();
}
}
public ICStorageElement[] getChildren() {
synchronized (fLock) {
return createSynchronizedChildren(fEl.getChildren());
}
}
public ICStorageElement[] getChildrenByName(String name) {
synchronized (fLock) {
return createSynchronizedChildren(fEl.getChildrenByName(name));
}
}
private ICStorageElement[] createSynchronizedChildren(ICStorageElement[] children) {
ICStorageElement[] synchChildren = new ICStorageElement[children.length];
for (int i = 0; i < children.length; i++)
synchChildren[i] = new SynchronizedStorageElement(children[i], fLock);
return synchChildren;
}
public String getName() {
synchronized (fLock) {
return fEl.getName();
}
}
public ICStorageElement getParent() {
synchronized (fLock) {
if (fEl.getParent() == null ||
fEl.getParent() instanceof SynchronizedStorageElement)
return fEl.getParent();
return new SynchronizedStorageElement(fEl.getParent(), fLock);
}
}
public String getValue() {
synchronized (fLock) {
return fEl.getValue();
}
}
public boolean hasAttribute(String name) {
synchronized (fLock) {
return fEl.hasAttribute(name);
}
}
public boolean hasChildren() {
synchronized (fLock) {
return fEl.hasChildren();
}
}
public ICStorageElement importChild(ICStorageElement el)
throws UnsupportedOperationException {
synchronized (fLock) {
return new SynchronizedStorageElement(el.importChild(el), fLock);
}
}
public void removeAttribute(String name) {
synchronized (fLock) {
fEl.removeAttribute(name);
}
}
public void removeChild(ICStorageElement el) {
synchronized (fLock) {
if (el instanceof SynchronizedStorageElement)
el = ((SynchronizedStorageElement)el).fEl;
fEl.removeChild(el);
}
}
public void setAttribute(String name, String value) {
synchronized (fLock) {
fEl.setAttribute(name, value);
}
}
public void setValue(String value) {
synchronized (fLock) {
fEl.setValue(value);
}
}
}

View file

@ -1,69 +1,61 @@
/*******************************************************************************
* Copyright (c) 2007 Intel Corporation and others.
* Copyright (c) 2007 2008 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Intel Corporation - Initial API and implementation
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
package org.eclipse.cdt.internal.core.settings.model.xml;
import org.eclipse.cdt.core.settings.model.ICSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.util.XmlStorageElement;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
import org.eclipse.core.runtime.CoreException;
import org.w3c.dom.Element;
/**
*
* Internal XmlStorageElement adds the following functionality
* - Dirty flag
* - Read-only flag
* - XmlStorage which corresponds to the Xml ICSettingsStorage
* if this ICStorageElement is root of a storage tree
*/
public class InternalXmlStorageElement extends XmlStorageElement {
boolean fIsDirty;
Element fElement;
private boolean fIsReadOnly;
private List fStorageList;
XmlStorage fStorage;
public InternalXmlStorageElement(Element element, ICStorageElement parent,
boolean alowReferencingParent, String[] attributeFilters,
String[] attributeFilters,
String[] childFilters, boolean readOnly) {
super(element, parent, alowReferencingParent, attributeFilters, childFilters);
fElement = element;
super(element, parent, attributeFilters, childFilters);
fIsReadOnly = readOnly;
}
public InternalXmlStorageElement(Element element, ICStorageElement parent,
boolean alowReferencingParent, boolean readOnly) {
super(element, parent, alowReferencingParent);
fElement = element;
fIsReadOnly = readOnly;
}
public InternalXmlStorageElement(Element element, boolean readOnly) {
super(element);
fElement = element;
fIsReadOnly = readOnly;
}
void storageCreated(CStorage storage){
List list = getStorageList(true);
list.add(storage);
}
private List getStorageList(boolean create){
if(fStorageList == null && create)
fStorageList = new ArrayList();
return fStorageList;
}
public boolean isReadOnly(){
return fIsReadOnly;
}
public void setReadOnly(boolean readOnly){
setReadOnly(readOnly, true);
}
public void setReadOnly(boolean readOnly, boolean keepModify){
fIsReadOnly = readOnly;
fIsDirty &= keepModify;
@ -74,40 +66,29 @@ public class InternalXmlStorageElement extends XmlStorageElement {
}
}
public boolean isDirty(){
public boolean isModified(){
if(fIsDirty)
return true;
List list = getStorageList(false);
if(list != null){
for(Iterator iter = list.iterator(); iter.hasNext();){
CStorage storage = (CStorage)iter.next();
if(storage.isDirty())
return true;
}
}
if (fStorage != null && fStorage.isModified())
return true;
ICStorageElement children[] = getChildren();
for(int i = 0; i < children.length; i++){
if(((InternalXmlStorageElement)children[i]).isDirty())
if(((InternalXmlStorageElement)children[i]).isModified())
return true;
}
return false;
}
public void setDirty(boolean dirty){
fIsDirty = dirty;
if(!dirty){
List list = getStorageList(false);
if(list != null){
for(Iterator iter = list.iterator(); iter.hasNext();){
CStorage storage = (CStorage)iter.next();
storage.setDirty(false);
}
}
if (fStorage != null)
fStorage.setDirty(false);
ICStorageElement children[] = getChildren();
for(int i = 0; i < children.length; i++){
@ -115,14 +96,16 @@ public class InternalXmlStorageElement extends XmlStorageElement {
}
}
}
public void storageCreated(XmlStorage storage) {
// Assert.isTrue(fStorage == null, "Storage created on an XmlStorageElement already exists");
fStorage = storage;
}
@Override
public void clear() {
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
makeModification();
super.clear();
fIsDirty = true;
}
@Override
@ -132,68 +115,70 @@ public class InternalXmlStorageElement extends XmlStorageElement {
/* if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
*/
return new InternalXmlStorageElement(element, this, alowReferencingParent, attributeFilters, childFilters, fIsReadOnly);
return new InternalXmlStorageElement(element, this, attributeFilters, childFilters, fIsReadOnly);
}
@Override
public ICStorageElement createChild(String name,
boolean alowReferencingParent, String[] attributeFilters,
String[] childFilters) {
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
fIsDirty = true;
return super.createChild(name, alowReferencingParent, attributeFilters,
childFilters);
makeModification();
return super.createChild(name, alowReferencingParent, attributeFilters, childFilters);
}
@Override
public ICStorageElement createChild(String name) {
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
fIsDirty = true;
makeModification();
return super.createChild(name);
}
@Override
public void removeAttribute(String name) {
fIsDirty = true;
makeModification();
super.removeAttribute(name);
}
@Override
public void setAttribute(String name, String value) {
fIsDirty = true;
makeModification();
super.setAttribute(name, value);
}
@Override
public void setValue(String value) {
fIsDirty = true;
makeModification();
super.setValue(value);
}
@Override
protected void removed() {
super.removed();
}
@Override
public ICStorageElement importChild(ICStorageElement el)
throws UnsupportedOperationException {
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
fIsDirty = true;
public ICStorageElement importChild(ICStorageElement el) throws UnsupportedOperationException {
makeModification();
return super.importChild(el);
}
@Override
public void removeChild(ICStorageElement el) {
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
fIsDirty = true;
makeModification();
super.removeChild(el);
}
@Override
public ICSettingsStorage createSettingStorage(boolean readOnly) throws CoreException, UnsupportedOperationException {
if (!isReadOnly() && readOnly)
return new XmlStorage(fElement, true);
return new XmlStorage(this);
}
/**
* - Check whether modifcation is allowed
* - Mark this element as dirty
*
* If modification is not allowed (fIsReadOnly == true)
* then throw write access exception.
*/
private void makeModification() {
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
fIsDirty = true;
}
}

View file

@ -0,0 +1,804 @@
/*******************************************************************************
* Copyright (c) 2007 2008 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Intel Corporation - Initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM Corporation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model.xml;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.net.URI;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.settings.model.ICSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.extension.ICProjectConverter;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.internal.core.envvar.ContributedEnvironment;
import org.eclipse.cdt.internal.core.settings.model.AbstractCProjectDescriptionStorage;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescription;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionStorageManager;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType;
import org.eclipse.cdt.internal.core.settings.model.SettingsContext;
import org.eclipse.cdt.internal.core.settings.model.SettingsModelMessages;
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType.CProjectDescriptionStorageTypeProxy;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
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.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.xml.sax.SAXException;
/**
* This class acts as the (de)serialization of the Xml Project model
*
* The read-only project description is referenced through a volatile reference
* which is updated atomically.
* The serializationLock is used to prevent concurrent read & write of the project
* description by Eclipse. All Scheduling rules _must_ be acquired before attempting
* to lock serializationLock (as it happens the setCProjectDescriptionOperation uses
* the Workspace scheduling rule).
*
* FIXME JBB we should use a more advanced overlay tree in the project
* description manager to allow safe concurrent access to the tree -- this will
* save both space (memory only needed for deltas) and provide easier access
* to the deltas. Having done this we should return a different ICDescriptor for
* each thread that requests it.
* @see AbstractCProjectDescriptionStorage
*/
public class XmlProjectDescriptionStorage extends AbstractCProjectDescriptionStorage {
public static final int INTERNAL_GET_IGNORE_CLOSE = 1 << 31;
private static final String OLD_PROJECT_DESCRIPTION = "cdtproject"; //$NON-NLS-1$
private static final String OLD_CDTPROJECT_FILE_NAME = ".cdtproject"; //$NON-NLS-1$
private static final String OLD_PROJECT_OWNER_ID = "id"; //$NON-NLS-1$
private static final String CONVERTED_CFG_NAME = "convertedConfig"; //$NON-NLS-1$
private static final String CONVERTED_CFG_ID_PREFIX = "converted.config"; //$NON-NLS-1$
/** The version of this project description storage */
public static final Version STORAGE_DESCRIPTION_VERSION = new Version("4.0"); //$NON-NLS-1$
/** The extension point ID of this description storage type */
public static final String STORAGE_TYPE_ID = CCorePlugin.PLUGIN_ID + ".XmlProjectDescriptionStorage"; //$NON-NLS-1$
final static String MODULE_ID = "org.eclipse.cdt.core.settings"; //$NON-NLS-1$
static final String CONFIGURATION = "cconfiguration"; //$NON-NLS-1$
private static final QualifiedName LOAD_FLAG = new QualifiedName(CCorePlugin.PLUGIN_ID, "descriptionLoadded"); //$NON-NLS-1$
public XmlProjectDescriptionStorage(CProjectDescriptionStorageTypeProxy type, IProject project, Version version) {
super(type, project, version);
}
/**
* The workspace runnable that actually goes about serializing the project description
*/
private class DesSerializationRunnable implements IWorkspaceRunnable {
private final ICProjectDescription fDes;
private final ICStorageElement fElement;
public DesSerializationRunnable(ICProjectDescription des, ICStorageElement el) {
fDes = des;
fElement = el;
}
public void run(IProgressMonitor monitor) throws CoreException {
try {
serializingLock.acquire();
projectModificaitonStamp = serialize(fDes.getProject(), ICProjectDescriptionStorageType.STORAGE_FILE_NAME, fElement);
((ContributedEnvironment) CCorePlugin.getDefault().getBuildEnvironmentManager().getContributedEnvironment()).serialize(fDes);
} finally {
serializingLock.release();
}
}
}
/** A soft reference to the read-only project description
* Volatile provides a memory barrier in Java 5+ */
private volatile Reference<ICProjectDescription> fProjectDescription = new SoftReference<ICProjectDescription>(null);
/** The last modification stamp of the .cproject project description file */
private volatile long projectModificaitonStamp = IResource.NULL_STAMP;
/** A lock that is held during project description serialization
* This lock is also head during load to prevent a load overlapping
* with a concurrent reply (as resource locks aren't used for load...)*/
private final ILock serializingLock = Job.getJobManager().newLock();
@Override
public ICSettingsStorage getStorageForElement(ICStorageElement element) throws CoreException {
return new XmlStorage((InternalXmlStorageElement)element);
}
@Override
public final ICProjectDescription getProjectDescription(int flags, IProgressMonitor monitor) throws CoreException {
ICProjectDescription des = null;
boolean write = checkFlags(flags, ICProjectDescriptionManager.GET_WRITABLE);
// Only 'load' if the caller hasn't explicitly requested currently loaded config
boolean load = !checkFlags(flags, ICProjectDescriptionManager.GET_IF_LOADDED);
// Create an empty configuration if the user has requested it
boolean empty = checkFlags(flags, ICProjectDescriptionManager.GET_EMPTY_PROJECT_DESCRIPTION);
boolean ignoreClose = checkFlags(flags, INTERNAL_GET_IGNORE_CLOSE);
boolean create = checkFlags(flags, ICProjectDescriptionManager.GET_CREATE_DESCRIPTION);
// set the PROJECT_CREATING flag on the project description
boolean creatingState = checkFlags(flags, ICProjectDescriptionManager.PROJECT_CREATING);
SettingsContext context = null;
des = super.getProjectDescription(flags, monitor);
// If no thread local project description then check for the previous loaded one
// or load from the .cproject file
if (des == null) {
boolean released = false;
try {
// If the description is already loaded and has been modified externally, reload it
load |= checkExternalModification();
// Acquire the (de)serializing lock
serializingLock.acquire();
if (ignoreClose || project.isOpen())
des = getLoadedDescription();
if (!empty && des == null && load && project.isOpen()) {
try {
des = loadProjectDescription(project);
} catch (CoreException e) {
// This isn't an issue as there may not be a project description
// file yet
}
if (des == null) {
// TODO: check if conversion needed
try {
context = new SettingsContext(project);
des = getConvertedDescription(context);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
if (des != null) {
if (setLoaddedDescriptionOnLoad(project, des)) {
// Current read-only description loaded, unlock the serializing lock
// (as saving conversion below will require acquiring resource scheduling rules...)
serializingLock.release();
released = true;
if (context != null)
saveConversion(project, context, (CProjectDescription) des, new NullProgressMonitor());
fireLoadedEvent(des);
des = getLoadedDescription();
}
}
}
} finally {
if (!released)
serializingLock.release();
}
}
// Only create a new empty configuration if the caller has requested an empty configuration
// or they're creating a configuration and there is no existing configuration found
if (empty || (des == null && create)) {
if (creatingState && des != null)
creatingState = des.isCdtProjectCreating();
try {
InternalXmlStorageElement element = createStorage(project, ICProjectDescriptionStorageType.STORAGE_FILE_NAME, false, true, false);
return new CProjectDescription(project, new XmlStorage(element), element, false, creatingState);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
if (des != null && write) {
des = createWritableDescription((CProjectDescription) des);
}
return des;
}
/**
* Method to check whether the description has been modified externally.
* If so the current read-only descriptor is nullified.
* @return boolean indicating whether reload is needed
*/
protected synchronized boolean checkExternalModification() {
ICProjectDescription desc = getLoadedDescription();
// If loaded, and we have cached the modification stamp, reload
if (desc != null && projectModificaitonStamp != IResource.NULL_STAMP) {
long currentModificationStamp = project.getFile(ICProjectDescriptionStorageType.STORAGE_FILE_NAME).getModificationStamp();
if (projectModificaitonStamp < currentModificationStamp) {
setCurrentDescription(null, true);
projectModificaitonStamp = currentModificationStamp;
return true;
}
}
return false;
}
/**
* Create a writable version of the description
*
* @param cache The base CProjectDescription on which the writable copy is to be created
* @return CProjectDescription of null on failure
*/
private CProjectDescription createWritableDescription(CProjectDescription cache) {
CProjectDescription des = null;
try {
InternalXmlStorageElement el = (InternalXmlStorageElement)cache.getRootStorageElement();
el = copyElement(el, false);
des = new CProjectDescription(cache, false, new XmlStorage(el), el, cache.isCdtProjectCreating());
fireCopyCreatedEvent(des, cache);
} catch (CoreException e) {
CCorePlugin.log(e);
}
return des;
}
/**
* @param project
* @param des
* @return
*/
private boolean setLoaddedDescriptionOnLoad(IProject project, ICProjectDescription des) {
des.setSessionProperty(LOAD_FLAG, Boolean.TRUE);
ICProjectDescription oldDes = getLoadedDescription();
setCurrentDescription(des, true);
if (oldDes == null)
return true;
return oldDes.getSessionProperty(LOAD_FLAG) == null;
}
/* Sets the current read-only descriptions -- uses the write lock
* (non-Javadoc)
* @see org.eclipse.cdt.core.settings.model.AbstractCProjectDescriptionStorage#setCurrentDescription(org.eclipse.cdt.core.settings.model.ICProjectDescription, boolean)
*/
@Override
public boolean setCurrentDescription(ICProjectDescription des, boolean overwriteIfExists) {
if (!overwriteIfExists && fProjectDescription.get() != null)
return false;
if (des != null) {
if (project.exists() && project.isOpen()) {
fProjectDescription = new SoftReference<ICProjectDescription>(des);
} else {
CCorePlugin.log(SettingsModelMessages.getString("CProjectDescriptionManager.16")); //$NON-NLS-1$
}
} else {
fProjectDescription = new SoftReference<ICProjectDescription>(null);
}
return true;
}
private Object[] loadProjectDescriptionFromOldstyleStorage() throws CoreException {
ICStorageElement rootEl = readOldCDTProjectFile(project);
if (rootEl != null) {
String ownerId = rootEl.getAttribute(OLD_PROJECT_OWNER_ID);
CProjectDescription des = (CProjectDescription) CProjectDescriptionManager.getInstance().createProjectDescription(project, false);
String id = CDataUtil.genId(CONVERTED_CFG_ID_PREFIX);
des.createConvertedConfiguration(id, CONVERTED_CFG_NAME, rootEl);
return new Object[] { ownerId, des };
}
return null;
}
/**
* Convert and Load a previous version of the Project Description
*
* @param project
* @param context
* @return
* @throws CoreException
*/
private ICProjectDescription getConvertedDescription(SettingsContext context) throws CoreException {
Object info[] = loadProjectDescriptionFromOldstyleStorage();
CProjectDescription des = null;
String ownerId = null;
try {
if (info != null) {
ownerId = (String) info[0];
des = (CProjectDescription) info[1];
setThreadLocalProjectDesc(des);
des.setLoading(true);
}
IProjectDescription eDes = context.getEclipseProjectDescription();
ICProjectConverter converter = CProjectDescriptionManager.getInstance().getConverter(project, ownerId, des);
if (converter != null) {
CProjectDescription convertedDes = (CProjectDescription) converter.convertProject(project, eDes, ownerId, des);
if (convertedDes != null) {
CProjectDescriptionManager.getInstance().checkHandleActiveCfgChange(convertedDes, null, eDes, new NullProgressMonitor());
des = convertedDes;
}
}
if (des != null && des.isValid()) {
// TODO: should be set via the CModel operation?
InternalXmlStorageElement el = null;
context.setEclipseProjectDescription(eDes);
try {
el = copyElement(des.getRootStorageElement(), false);
} catch (CoreException e2) {
}
des = new CProjectDescription(des, true, new XmlStorage(el), el, des.isCdtProjectCreating());
setThreadLocalProjectDesc(des);
des.applyDatas(context);
des.doneApplying();
}
} finally {
setThreadLocalProjectDesc(null);
if (des != null)
des.setLoading(false);
}
return des;
}
private void saveConversion(final IProject proj, final SettingsContext context, CProjectDescription des, IProgressMonitor monitor) {
try {
context.addWorkspaceRunnable(createDesSerializationRunnable());
} catch (CoreException e1) {
CCorePlugin.log(e1);
}
IWorkspaceRunnable toRun = context.createOperationRunnable();
if (toRun != null)
CProjectDescriptionManager.runWspModification(toRun, monitor);
}
/**
* Return the read-only ICProjectDescription
* in a thread-safe manner
*/
public ICProjectDescription getLoadedDescription() {
return fProjectDescription.get();
}
/**
* The internal method that actually causes the CProjectDescription to be created from an external storage.
* @param project
* @return the loaded ICProjectDescription
* @throws CoreException
*/
protected ICProjectDescription loadProjectDescription(IProject project) throws CoreException {
try {
// Ensure that there isn't a write to the project description occurring concurrently
serializingLock.acquire();
// Check if the description has already been loaded
if (!checkExternalModification() && getLoadedDescription() != null)
return getLoadedDescription();
// Don't log core exceptions caused by .cproject file not exists. Leave that to caller
InternalXmlStorageElement storage = createStorage(project, ICProjectDescriptionStorageType.STORAGE_FILE_NAME, true, false, false);
try {
// Update the modification stamp
projectModificaitonStamp = project.getFile(ICProjectDescriptionStorageType.STORAGE_FILE_NAME).getModificationStamp();
CProjectDescription des = new CProjectDescription(project, new XmlStorage(storage), storage, true, false);
try {
setThreadLocalProjectDesc(des);
des.loadDatas();
des.doneLoading();
} finally {
setThreadLocalProjectDesc(null);
}
return des;
} catch (CoreException e) {
// XmlStorage constructor does sanity checking of the project xml storage element, ensure that errors here are logged
CCorePlugin.log(e);
throw e;
}
} finally {
serializingLock.release();
}
}
@Override
public IWorkspaceRunnable createDesSerializationRunnable() throws CoreException {
CProjectDescription des = (CProjectDescription)getLoadedDescription();
if (des == null) // This won't happen because CModelOperation has a handle on the current read-only description
throw ExceptionFactory.createCoreException("No read-only Project Description found! Project: " + project.getName()); //$NON-NLS-1$
final ICStorageElement element = des.getRootStorageElement();
IWorkspaceRunnable r = new DesSerializationRunnable(des, element);
return r;
}
/**
* Convert an Xml based ICStorageElement to an ByteArrayOutputStream
*/
private ByteArrayOutputStream write(ICStorageElement element) throws CoreException {
Document doc = ((InternalXmlStorageElement) element).fElement.getOwnerDocument();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(stream);
transformer.transform(source, result);
return stream;
} catch (TransformerConfigurationException e) {
throw ExceptionFactory.createCoreException(e);
} catch (TransformerException e) {
throw ExceptionFactory.createCoreException(e);
}
}
/**
* The method that *actually* performs the serialization of the settings...
*
* @param container - the folder in which file is to be serialized
* @param file - the name of the file to serialize the storage element tree into
* @param element - read-only ICStorageElement tree to be serialized (no need to lock)
* @throws CoreException
* @return long modification stamp of the file in the container
*/
protected long serialize(IContainer container, String file, ICStorageElement element) throws CoreException {
try {
final IFile projectFile = container.getFile(new Path(file));
final ISchedulingRule rule = MultiRule.combine(new ISchedulingRule[] {
ResourcesPlugin.getWorkspace().getRuleFactory().modifyRule(projectFile),
ResourcesPlugin.getWorkspace().getRuleFactory().createRule(projectFile),
ResourcesPlugin.getWorkspace().getRuleFactory().deleteRule(projectFile)
});
String utfString;
ByteArrayOutputStream stream = null;
try {
// Get the ProjectDescription as a utf-8 string
stream = write(element);
utfString = stream.toString("UTF-8"); //$NON-NLS-1$
} finally {
if (stream != null)
stream.close(); // Cleanup the stream
}
try {
// Lock the projectFile
Job.getJobManager().beginRule(rule, null);
// Ensure the file is writable
CProjectDescriptionStorageManager.ensureWritable(projectFile);
if (projectFile.exists()) {
try {
projectFile.setContents(new ByteArrayInputStream(utfString.getBytes("UTF-8")), IResource.FORCE, new NullProgressMonitor()); //$NON-NLS-1$
} catch (CoreException e) {
if (projectFile.getLocation().toFile().isHidden()) {
String os = System.getProperty("os.name"); //$NON-NLS-1$
if (os != null && os.startsWith("Win")) { //$NON-NLS-1$
projectFile.delete(true, null);
projectFile.create(new ByteArrayInputStream(utfString.getBytes("UTF-8")), IResource.FORCE, new NullProgressMonitor()); //$NON-NLS-1$
CCorePlugin.log(e.getLocalizedMessage() + "\n** Error occured because of file status <hidden>." + //$NON-NLS-1$
"\n** This status is disabled now, to allow writing."); //$NON-NLS-1$
} else
throw (e);
} else
throw (e);
}
} else {
projectFile.create(new ByteArrayInputStream(utfString.getBytes("UTF-8")), IResource.FORCE, new NullProgressMonitor()); //$NON-NLS-1$
}
return projectFile.getModificationStamp();
} finally {
Job.getJobManager().endRule(rule);
}
} catch (IOException e) {
throw ExceptionFactory.createCoreException(e);
}
}
private ICStorageElement readOldCDTProjectFile(IProject project) throws CoreException {
ICStorageElement storage = null;
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = null;
InputStream stream = getSharedProperty(project, OLD_CDTPROJECT_FILE_NAME);
if (stream != null) {
doc = builder.parse(stream);
NodeList nodeList = doc.getElementsByTagName(OLD_PROJECT_DESCRIPTION);
if (nodeList != null && nodeList.getLength() > 0) {
Node node = nodeList.item(0);
storage = new InternalXmlStorageElement((Element) node, false);
}
}
} catch (ParserConfigurationException e) {
throw ExceptionFactory.createCoreException(e);
} catch (SAXException e) {
throw ExceptionFactory.createCoreException(e);
} catch (IOException e) {
throw ExceptionFactory.createCoreException(e);
}
return storage;
}
/**
* This method returns an ICStorageElement from a given Xml file filename in the container
* container
*
* @param container
* @param fileName
* @param reCreate
* @param createEmptyIfNotFound
* @param readOnly
* @return InternalXmlStorageElement representing the particular storage
* @throws CoreException
*/
protected InternalXmlStorageElement createStorage(IContainer container, String fileName, boolean reCreate, boolean createEmptyIfNotFound, boolean readOnly) throws CoreException{
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = null;
Element element = null;
InputStream stream = null;
if(reCreate){
try{
stream = getSharedProperty(container, fileName);
if(stream != null){
doc = builder.parse(stream);
// Get the first element in the project file
Node rootElement = doc.getFirstChild();
if (rootElement.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE) {
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.7")); //$NON-NLS-1$
} else {
// Make sure that the version is compatible with the manager
String fileVersion = rootElement.getNodeValue();
Version version = new Version(fileVersion);
if (getVersion().compareTo(version) < 0) {
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.8")); //$NON-NLS-1$
}
}
// Now get the project root element (there should be only one)
NodeList nodes = doc.getElementsByTagName(ICProjectDescriptionStorageType.STORAGE_ROOT_ELEMENT_NAME);
if (nodes.getLength() == 0)
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.9")); //$NON-NLS-1$
Node node = nodes.item(0);
if(node.getNodeType() != Node.ELEMENT_NODE)
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.10")); //$NON-NLS-1$
element = (Element)node;
} else if(!createEmptyIfNotFound){
throw ExceptionFactory.createCoreException(SettingsModelMessages.getString("CProjectDescriptionManager.11") + fileName); //$NON-NLS-1$
}
} catch (FactoryConfigurationError e) {
if(!createEmptyIfNotFound)
throw ExceptionFactory.createCoreException(e.getLocalizedMessage());
} catch (SAXException e) {
if(!createEmptyIfNotFound)
throw ExceptionFactory.createCoreException(e);
} catch (IOException e) {
if(!createEmptyIfNotFound)
throw ExceptionFactory.createCoreException(e);
} finally {
if(stream != null){
try {
stream.close();
} catch (IOException e) {
}
}
}
}
if(element == null) {
doc = builder.newDocument();
ProcessingInstruction instruction = doc.createProcessingInstruction(ICProjectDescriptionStorageType.STORAGE_VERSION_NAME, getVersion().toString());
doc.appendChild(instruction);
element = doc.createElement(ICProjectDescriptionStorageType.STORAGE_ROOT_ELEMENT_NAME);
element.setAttribute(ICProjectDescriptionStorageType.STORAGE_TYPE_ATTRIBUTE, getStorageTypeId());
doc.appendChild(element);
}
return new InternalXmlStorageElement(element, null, false, readOnly);
} catch (ParserConfigurationException e) {
throw ExceptionFactory.createCoreException(e);
}
}
/**
* @return the maximum version supported by this description storage
*/
protected Version getVersion() {
return STORAGE_DESCRIPTION_VERSION;
}
/**
* @return Return the storage type id for this storage
*/
protected String getStorageTypeId() {
return STORAGE_TYPE_ID;
}
/**
* Return an input stream for the given file in the provided container
* @param container
* @param key
* @return InputStream
* @throws CoreException on failure
*/
public InputStream getSharedProperty(IContainer container, String key) throws CoreException {
InputStream stream = null;
final IFile rscFile = container.getFile(new Path(key));
if (rscFile.exists()) {
try {
stream = rscFile.getContents(true);
} catch (CoreException e) {
// try refreshing
final Throwable[] t = new Throwable[1];
Job job = CProjectDescriptionManager.runWspModification(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
try {
rscFile.refreshLocal(IResource.DEPTH_ZERO, null);
} catch (Exception e) {
t[0] = e;
}
}
}, rscFile, new NullProgressMonitor());
// if refresh was performed "inline" without job scheduled
if (job == null) {
// if no exceptions occured
if (t[0] == null) {
// try get contents
stream = rscFile.getContents();
} else {
// refresh failed
if (t[0] instanceof CoreException)
throw (CoreException) t[0];
throw e;
}
} else {
throw e;
}
}
} else {
// FIXME JBB remove?
// when a project is imported, we get a first delta for the addition
// of the .project, but the .classpath is not accessible
// so default to using java.io.File
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96258
URI location = rscFile.getLocationURI();
if (location != null) {
IFileStore file = EFS.getStore(location);
IFileInfo info = null;
if (file != null) {
info = file.fetchInfo();
if (info != null && info.exists())
stream = file.openInputStream(EFS.NONE, null);
}
}
}
return stream;
}
@Override
public void projectCloseRemove() {
super.projectCloseRemove();
setCurrentDescription(null, true);
}
@Override
public void projectMove(IProject newProject) {
super.projectMove(newProject);
// FIXME JBB From ResourceChangeHandler.
// Why do the project description and configurations need to know
// their project? They should ask their ProjectDescriptionStorage
CProjectDescription desc = (CProjectDescription)fProjectDescription.get();
if (desc != null) {
desc.updateProject(newProject);
}
}
/**
* Return an Xml element copy based on a passed in InternalXmlStorageElement
*
* @param el
* @return Xml element based on a passed in xml ICStorageElement (InternalXmlStorageElement)
* @throws CoreException
*/
public Element createXmlElementCopy(InternalXmlStorageElement el) throws CoreException {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.newDocument();
Element newXmlEl = null;
if (el.fElement.getParentNode().getNodeType() == Node.DOCUMENT_NODE) {
Document baseDoc = el.fElement.getOwnerDocument();
NodeList list = baseDoc.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
node = importAddNode(doc, node);
if (node.getNodeType() == Node.ELEMENT_NODE && newXmlEl == null) {
newXmlEl = (Element) node;
}
}
} else {
newXmlEl = (Element) importAddNode(doc, el.fElement);
}
return newXmlEl;
} catch (ParserConfigurationException e) {
throw ExceptionFactory.createCoreException(e);
} catch (FactoryConfigurationError e) {
throw ExceptionFactory.createCoreException(e);
}
}
@Override
public InternalXmlStorageElement copyElement(ICStorageElement el, boolean readOnly) throws CoreException {
InternalXmlStorageElement internalEl = (InternalXmlStorageElement)el;
Element newXmlEl = createXmlElementCopy(internalEl);
return new InternalXmlStorageElement(newXmlEl, internalEl.getParent(), internalEl.getAttributeFilters(), internalEl.getChildFilters(), readOnly);
}
private Node importAddNode(Document doc, Node node) {
if (node.getOwnerDocument().equals(doc)) {
node = node.cloneNode(true);
} else {
node = doc.importNode(node, true);
}
return doc.appendChild(node);
}
}

View file

@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model.xml;
import org.eclipse.cdt.internal.core.settings.model.AbstractCProjectDescriptionStorage;
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType;
import org.eclipse.core.resources.IProject;
import org.osgi.framework.Version;
/**
* Concrete implementation of ICProjectDescriptionStorageType
* for instantiating XmlProjectDescriptionStorage
*/
public class XmlProjectDescriptionStorageFactory implements ICProjectDescriptionStorageType {
public AbstractCProjectDescriptionStorage getProjectDescriptionStorage(CProjectDescriptionStorageTypeProxy type, IProject project, Version version) {
return new XmlProjectDescriptionStorage(type, project, version);
}
public boolean createsCProjectXMLFile() {
return true;
}
}

View file

@ -0,0 +1,245 @@
/*******************************************************************************
* Copyright (c) 2007 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model.xml;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.cdt.core.settings.model.ICSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
import org.eclipse.core.runtime.CoreException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Concrete implementation of ICSettingsStorage backed by an XML document
*
* ICStorageElements are stored in the tree under a storageModule element.
* (This class was previously called CStorage)
* TODO JBB Make this independent of the Xml Element
*/
public class XmlStorage implements ICSettingsStorage {
public static final String MODULE_ELEMENT_NAME = "storageModule"; //$NON-NLS-1$
public static final String MODULE_ID_ATTRIBUTE = "moduleId"; //$NON-NLS-1$
public Element fElement;
private Map<String, InternalXmlStorageElement> fStorageElementMap = new HashMap<String, InternalXmlStorageElement>();
private boolean fChildrenInited;
private boolean fIsReadOnly;
private boolean fIsDirty;
public XmlStorage(Element element, boolean isReadOnly){
fElement = element;
fIsReadOnly = isReadOnly;
}
public XmlStorage(InternalXmlStorageElement element) throws CoreException {
fElement = element.fElement;
fIsReadOnly = element.isReadOnly();
element.storageCreated(this);
sanityCheck(element);
}
/**
* Check that the XmlStorageElement on which this SettingsStorage
* is based doesn't have any attributes, values or children which
* are invalid for a settings storage.
* @param element
* @throws CoreException
*/
public void sanityCheck(ICStorageElement element) throws CoreException {
if (element.getValue() != null && element.getValue().trim().length() > 0)
throw ExceptionFactory.createCoreException("XmlStorage '" + element.getName() + "' has unexpected child Value: " + element.getValue());
for (ICStorageElement child : element.getChildren()) {
if (!MODULE_ELEMENT_NAME.equals(child.getName()))
throw ExceptionFactory.createCoreException("XmlStorage '" + element.getName() + "' has unexpected child element: " + child.getName());
if (child.getAttribute(MODULE_ID_ATTRIBUTE) == null)
throw ExceptionFactory.createCoreException("XmlStorage '" + element.getName() + "' has storageModule child without moduleId");
}
}
public boolean isReadOnly(){
return fIsReadOnly;
}
/**
* Initialise the set of storageModules of this XmlStorage
*/
private void initChildren(){
if(fChildrenInited)
return;
fChildrenInited = true;
NodeList children = fElement.getChildNodes();
int size = children.getLength();
for(int i = 0; i < size; i++){
Node node = children.item(i);
if(node.getNodeType() != Node.ELEMENT_NODE)
continue;
if(!MODULE_ELEMENT_NAME.equals(node.getNodeName()))
continue;
Element element = (Element)node;
String moduleId = element.getAttribute(MODULE_ID_ATTRIBUTE).trim();
if(moduleId.length() == 0)
continue;
createAddStorageElement(moduleId, element);
}
}
private InternalXmlStorageElement createAddStorageElement(String id, Element element){
InternalXmlStorageElement se = createStorageElement(element, fIsReadOnly);
fStorageElementMap.put(id, se);
return se;
}
public static InternalXmlStorageElement createStorageElement(Element el, boolean isReadOnly){
return new InternalXmlStorageElement(el, null, new String[]{MODULE_ID_ATTRIBUTE}, null, isReadOnly);
}
// public ICStorageElement getStorage(String id){
// return getStorage(id, true);
// }
public boolean containsStorage(String id) throws CoreException {
return getStorage(id, false) != null;
}
public ICStorageElement importStorage(String id, ICStorageElement el) throws UnsupportedOperationException {
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
// Remove existing storage with this ID
removeStorage(id);
// Create the storage element for import
Document thisDoc = fElement.getOwnerDocument();
Element newEl = thisDoc.createElement(MODULE_ELEMENT_NAME);
fIsDirty = true;
if (el instanceof XmlStorageElement) {
// If we're importing an XmlStorageElement use XML methods
XmlStorageElement xmlStEl = (XmlStorageElement)el;
Element xmlEl = xmlStEl.fElement;
Document otherDoc = xmlEl.getOwnerDocument();
if(!thisDoc.equals(otherDoc)){
xmlEl = (Element)thisDoc.importNode(xmlEl, true);
}
NodeList nl = xmlEl.getChildNodes();
for(int i = 0; i < nl.getLength(); i++){
Node child = nl.item(i).cloneNode(true);
newEl.appendChild(child);
}
newEl = (Element)fElement.appendChild(newEl);
newEl.setAttribute(MODULE_ID_ATTRIBUTE, id);
return createAddStorageElement(id, newEl);
} else {
// Otherwise importing generic ICStorageElement
ICStorageElement storageEl = getStorage(id, true);
for (String attrName: el.getAttributeNames())
storageEl.setAttribute(attrName, el.getAttribute(attrName));
for (ICStorageElement child: el.getChildren())
storageEl.importChild(child);
return storageEl;
}
}
public ICStorageElement getStorage(String id, boolean create){
initChildren();
InternalXmlStorageElement se = fStorageElementMap.get(id);
if(se == null && create){
// if(fIsReadOnly)
// throw ExceptionFactory.createIsReadOnlyException();
fIsDirty = true;
Document doc = fElement.getOwnerDocument();
Element child = createStorageXmlElement(doc, id);
fElement.appendChild(child);
se = createAddStorageElement(id, child);
}
return se;
}
public static Element createStorageXmlElement(Document doc, String storageId){
Element child = doc.createElement(MODULE_ELEMENT_NAME);
child.setAttribute(MODULE_ID_ATTRIBUTE, storageId);
return child;
}
public void removeStorage(String id){
initChildren();
InternalXmlStorageElement se = fStorageElementMap.remove(id);
if(se != null){
if(fIsReadOnly)
throw ExceptionFactory.createIsReadOnlyException();
fIsDirty = true;
Node nextSibling = se.fElement.getNextSibling();
fElement.removeChild(se.fElement);
if (nextSibling != null && nextSibling.getNodeType() == Node.TEXT_NODE) {
String value = nextSibling.getNodeValue();
if (value != null && value.trim().length() == 0) {
// remove whitespace
fElement.removeChild(nextSibling);
}
}
}
}
public boolean isModified(){
if(fIsDirty)
return true;
for(Iterator<InternalXmlStorageElement> iter = fStorageElementMap.values().iterator(); iter.hasNext();){
InternalXmlStorageElement el = iter.next();
if(el.isModified())
return true;
}
return false;
}
public void setReadOnly(boolean readOnly, boolean keepModify){
fIsReadOnly = readOnly;
fIsDirty &= keepModify;
for(Iterator<InternalXmlStorageElement> iter = fStorageElementMap.values().iterator(); iter.hasNext();){
InternalXmlStorageElement el = iter.next();
el.setReadOnly(readOnly, keepModify);
}
}
public void setDirty(boolean isDirty){
fIsDirty = isDirty;
if(!fIsDirty){
for(Iterator<InternalXmlStorageElement> iter = fStorageElementMap.values().iterator(); iter.hasNext();){
InternalXmlStorageElement el = iter.next();
el.setDirty(false);
}
}
}
public void save() throws CoreException {
throw new UnsupportedOperationException();
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007 Intel Corporation and others.
* Copyright (c) 2007, 2008 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,16 +7,31 @@
*
* Contributors:
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.core.settings.model.util;
package org.eclipse.cdt.internal.core.settings.model.xml;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.cdt.core.settings.model.ICSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
import org.eclipse.core.runtime.CoreException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
@ -25,60 +40,47 @@ import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
public class XmlStorageElement implements ICStorageElement {
protected static final String[] emptyStringList = new String[0];
Element fElement;
public Element fElement;
private ICStorageElement fParent;
private List fChildList = new ArrayList();
protected List<ICStorageElement> fChildList = new ArrayList<ICStorageElement>();
private boolean fChildrenCreated;
private String[] fAttributeFilters;
private String[] fChildFilters;
private boolean fParentRefAlowed;
public XmlStorageElement(Element element){
this(element, null, false);
}
public XmlStorageElement(Element element, ICStorageElement parent, boolean alowReferencingParent){
this(element, parent, alowReferencingParent, null, null);
this(element, parent, null, null);
}
public XmlStorageElement(Element element,
ICStorageElement parent,
boolean alowReferencingParent,
String[] attributeFilters,
String[] childFilters){
fElement = element;
fParent = parent;
fParentRefAlowed = alowReferencingParent;
if(attributeFilters != null && attributeFilters.length != 0)
fAttributeFilters = (String[])attributeFilters.clone();
fAttributeFilters = attributeFilters.clone();
if(childFilters != null && childFilters.length != 0)
fChildFilters = (String[])childFilters.clone();
fChildFilters = childFilters.clone();
}
// public String[] getAttributeFilters(){
// if(fAttributeFilters != null)
// return (String[])fAttributeFilters.clone();
// return null;
// }
// public String[] getChildFilters(){
// if(fChildFilters != null)
// return (String[])fChildFilters.clone();
// return null;
// }
//
// public boolean isParentRefAlowed(){
// return fParentRefAlowed;
// }
/**
* Create ICStorageElement children from Xml tree
*/
private void createChildren(){
if(fChildrenCreated)
return;
fChildrenCreated = true;
fChildList.clear();
NodeList list = fElement.getChildNodes();
int size = list.getLength();
for(int i = 0; i < size; i++){
@ -103,14 +105,14 @@ public class XmlStorageElement implements ICStorageElement {
boolean alowReferencingParent,
String[] attributeFilters,
String[] childFilters){
return new XmlStorageElement(element, this, alowReferencingParent, attributeFilters, childFilters);
return new XmlStorageElement(element, this, attributeFilters, childFilters);
}
public ICStorageElement[] getChildren() {
return getChildren(XmlStorageElement.class);
}
protected ICStorageElement[] getChildren(Class clazz){
protected ICStorageElement[] getChildren(Class<XmlStorageElement> clazz){
return getChildren(clazz, true);
}
@ -118,18 +120,32 @@ public class XmlStorageElement implements ICStorageElement {
return getChildren(XmlStorageElement.class, load);
}
protected ICStorageElement[] getChildren(Class clazz, boolean load){
protected ICStorageElement[] getChildren(Class<XmlStorageElement> clazz, boolean load){
if(load)
createChildren();
ICStorageElement[] children = (ICStorageElement[])java.lang.reflect.Array.newInstance(
clazz, fChildList.size());
return (ICStorageElement[])fChildList.toArray(children);
return fChildList.toArray(children);
}
public ICStorageElement[] getChildrenByName(String name) {
createChildren();
ArrayList<ICStorageElement> children = new ArrayList<ICStorageElement>();
for (ICStorageElement child : fChildList)
if (name.equals(child.getName()))
children.add(child);
return children.toArray(new ICStorageElement[children.size()]);
}
public boolean hasChildren() {
createChildren();
return !fChildList.isEmpty();
}
public ICStorageElement getParent() {
return fParentRefAlowed ? fParent : null;
return fParent;
}
public String getAttribute(String name) {
@ -138,6 +154,10 @@ public class XmlStorageElement implements ICStorageElement {
return null;
}
public boolean hasAttribute(String name) {
return fElement.hasAttribute(name);
}
private boolean isPropertyAlowed(String name){
if(fAttributeFilters != null){
return checkString(name, fAttributeFilters);
@ -162,27 +182,22 @@ public class XmlStorageElement implements ICStorageElement {
return true;
}
// protected void childRemoved(ICStorageElement child) {
// fChildList.remove(child);
// }
protected void removed(){
// fElement.getParentNode().removeChild(fElement);
fElement = null;
// if(fParent != null)
// ((XmlStorageElement)fParent).childRemoved(this);
}
public void removeChild(ICStorageElement el) {
if(el instanceof XmlStorageElement){
ICStorageElement[] children = getChildren();
for(int i = 0; i < children.length; i++){
if(children[i] == el){
XmlStorageElement xmlEl = (XmlStorageElement)el;
Node nextSibling = xmlEl.fElement.getNextSibling();
fElement.removeChild(xmlEl.fElement);
if (nextSibling != null && nextSibling.getNodeType() == Node.TEXT_NODE) {
String value = nextSibling.getNodeValue();
if (value != null && value.trim().length() == 0) {
// remove whitespace
fElement.removeChild(nextSibling);
}
}
fChildList.remove(el);
xmlEl.removed();
}
}
}
@ -202,26 +217,28 @@ public class XmlStorageElement implements ICStorageElement {
public void clear(){
createChildren();
ICStorageElement children[] = (ICStorageElement[])fChildList.toArray(new ICStorageElement[fChildList.size()]);
ICStorageElement children[] = fChildList.toArray(new ICStorageElement[fChildList.size()]);
for(int i = 0; i < children.length; i++){
removeChild(children[i]);
}
NamedNodeMap map = fElement.getAttributes();
for(int i = 0; i < map.getLength(); i++){
Node attr = map.item(i);
if(isPropertyAlowed(attr.getNodeName()))
map.removeNamedItem(attr.getNodeName());
}
NodeList list = fElement.getChildNodes();
for(int i = 0; i < list.getLength(); i++){
Node node = list.item(i);
Node node = fElement.getFirstChild();
while (node != null) {
Node nextChildNode = node.getNextSibling();
if(node.getNodeType() == Node.TEXT_NODE)
fElement.removeChild(node);
// update the pointer
node = nextChildNode;
}
}
public ICStorageElement createChild(String name,
boolean alowReferencingParent,
String[] attributeFilters,
@ -304,37 +321,29 @@ public class XmlStorageElement implements ICStorageElement {
xmlEl = (Element)fElement.appendChild(xmlEl);
return createAddChild(xmlEl, alowReferencingParent, attributeFilters, childFilters);
} else {
// FIXME JBB allow import of other types of ICStorageElement
throw new UnsupportedOperationException();
}
}
public String[] getAttributeFilters(){
if(fAttributeFilters != null)
return (String[])fAttributeFilters.clone();
return new String[0];
return fAttributeFilters.clone();
return emptyStringList;
}
public String[] getChildFilters(){
if(fChildFilters != null)
return (String[])fChildFilters.clone();
return new String[0];
return fChildFilters.clone();
return emptyStringList;
}
public boolean isParentRefAlowed(){
return fParentRefAlowed;
}
public boolean matches(ICStorageElement el){
public boolean equals(ICStorageElement el){
if(!getName().equals(el.getName()))
return false;
String value = getValue();
if(value == null){
if(el.getValue() != null)
return false;
} else if(!value.equals(el.getValue()))
if (!valuesMatch(getValue(), el.getValue()))
return false;
String[] attrs = getAttributeNames();
String[] otherAttrs = el.getAttributeNames();
@ -342,7 +351,7 @@ public class XmlStorageElement implements ICStorageElement {
return false;
if(attrs.length != 0){
Set set = new HashSet(Arrays.asList(attrs));
Set<String> set = new HashSet<String>(Arrays.asList(attrs));
set.removeAll(Arrays.asList(otherAttrs));
if(set.size() != 0)
return false;
@ -363,7 +372,7 @@ public class XmlStorageElement implements ICStorageElement {
if(children.length != 0){
for(int i = 0; i < children.length; i++){
if(!children[i].matches(otherChildren[i]))
if(!children[i].equals(otherChildren[i]))
return false;
}
}
@ -371,17 +380,103 @@ public class XmlStorageElement implements ICStorageElement {
return true;
}
private static boolean valuesMatch(String value, String other) {
if(value == null) {
return other == null || other.trim().length() == 0;
} else if (other == null) {
return value.trim().length() == 0;
} else {
return value.trim().equals(other.trim());
}
}
public String[] getAttributeNames() {
NamedNodeMap nodeMap = fElement.getAttributes();
int length = nodeMap.getLength();
List list = new ArrayList(length);
List<String> list = new ArrayList<String>(length);
for(int i = 0; i < length; i++){
Node node = nodeMap.item(i);
String name = node.getNodeName();
if(isPropertyAlowed(name))
list.add(name);
}
return (String[])list.toArray(new String[list.size()]);
return list.toArray(new String[list.size()]);
}
public ICStorageElement createCopy() throws UnsupportedOperationException, CoreException {
Element newEl = createXmlElementCopy();
return new XmlStorageElement(newEl, null, fAttributeFilters, fChildFilters);
}
protected Element createXmlElementCopy() throws CoreException {
try {
Element newXmlEl = null;
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.newDocument();
if(fElement.getParentNode().getNodeType() == Node.DOCUMENT_NODE){
Document baseDoc = fElement.getOwnerDocument();
NodeList list = baseDoc.getChildNodes();
for(int i = 0; i < list.getLength(); i++){
Node node = list.item(i);
node = importAddNode(doc, node);
if(node.getNodeType() == Node.ELEMENT_NODE && newXmlEl == null){
newXmlEl = (Element)node;
}
}
} else {
newXmlEl = (Element)importAddNode(doc, fElement);
}
// Document baseDoc = el.fElement.getOwnerDocument();
// Element baseEl = baseDoc.getDocumentElement();
// Element newXmlEl = (Element)doc.importNode(baseEl, true);
// doc.appendChild(newXmlEl);
return newXmlEl;
} catch (ParserConfigurationException e) {
throw ExceptionFactory.createCoreException(e);
} catch (FactoryConfigurationError e) {
throw ExceptionFactory.createCoreException(e);
}
}
private Node importAddNode(Document doc, Node node){
if(node.getOwnerDocument().equals(doc)){
node = node.cloneNode(true);
} else {
node = doc.importNode(node, true);
}
return doc.appendChild(node);
}
public ICSettingsStorage createSettingStorage(boolean readOnly) throws CoreException, UnsupportedOperationException {
return new XmlStorage(fElement, readOnly);
}
/*
* toString() outputs XML tree -- useful for debugging
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
DOMSource source = new DOMSource(fElement);
StreamResult result = new StreamResult(stream);
transformer.transform(source, result);
builder.append(stream.toString());
} catch (Exception e){
return fElement.toString();
}
return builder.toString();
}
}

View file

@ -0,0 +1,243 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model.xml2;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionStorageManager;
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType;
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType.CProjectDescriptionStorageTypeProxy;
import org.eclipse.cdt.internal.core.settings.model.xml.InternalXmlStorageElement;
import org.eclipse.cdt.internal.core.settings.model.xml.XmlProjectDescriptionStorage;
import org.eclipse.cdt.internal.core.settings.model.xml.XmlStorage;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.osgi.framework.Version;
import org.w3c.dom.Element;
/**
* This class extends XmlProjectDescriptionStroage to provide the following
* functionality:
* - Configuration Description storage modules are persisted in separate XML
* files stored under .csettings in the project root directory. They
* are linked into the main .cproject file via "externalCElementFile" element
*
* It is backwards compatible with XmlProjectDescriptionStorage. If it finds a file
* with Version less than 5.0, it will delegate to the previous XmlProjectDescriptionStorage
*
* This allows users to more easily version control their CDT project descriptions
* @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=226457">Bug 226457</a>
*/
public class XmlProjectDescriptionStorage2 extends XmlProjectDescriptionStorage {
/** Folder Name for storing Project specific configuration settings */
static final String STORAGE_FOLDER_NAME = ".csettings"; //$NON-NLS-1$
/** Element providing the name of the external C Element file */
public static final String EXTERNAL_CELEMENT_KEY = "externalCElementFile"; //$NON-NLS-1$
private static final String ID = "id"; //$NON-NLS-1$
/** Override the description version, we support version '5.0' files */
@SuppressWarnings("hiding")
public static final Version STORAGE_DESCRIPTION_VERSION = new Version("5.0"); //$NON-NLS-1$
/** The storage type id of this extended project description type */
@SuppressWarnings("hiding")
public static final String STORAGE_TYPE_ID = CCorePlugin.PLUGIN_ID + ".XmlProjectDescriptionStorage2"; //$NON-NLS-1$
/** Map from storageModuleId to modification time stamp */
Map<String, Long> modificationMap = Collections.synchronizedMap(new HashMap<String, Long>());
public XmlProjectDescriptionStorage2(CProjectDescriptionStorageTypeProxy type, IProject project, Version version) {
super(type, project, version);
}
/*
* Check for external modification in the module files in the .csettings directory
* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.settings.model.xml.XmlProjectDescriptionStorage#checkExternalModification()
*/
@Override
protected synchronized boolean checkExternalModification() {
// Check if our parent thinks we need a reload
if (super.checkExternalModification())
return true;
// If not currently loaded, then nothing to do
if (getLoadedDescription() == null)
return false;
final boolean[] needReload = new boolean[] { false };
try {
project.getFolder(STORAGE_FOLDER_NAME).accept(new IResourceProxyVisitor() {
public boolean visit(IResourceProxy proxy) throws CoreException {
if (modificationMap.containsKey(proxy.getName()))
if (modificationMap.get(proxy.getName()) < proxy.getModificationStamp()) {
// There may be old storages in here, ensure we don't infinite reload...
modificationMap.put(proxy.getName(), proxy.getModificationStamp());
setCurrentDescription(null, true);
needReload[0] = true;
}
return true;
}
}, IResource.NONE);
} catch (CoreException e) {
// STORAGE_FOLDER_NAME doesn't exist... or something went wrong during reload
if (project.getFolder(STORAGE_FOLDER_NAME).exists())
CCorePlugin.log("XmlProjectDescriptionStorage2: Problem checking for external modification: " + e.getMessage());
}
return needReload[0];
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.settings.model.xml.XmlProjectDescriptionStorage#createStorage(org.eclipse.core.resources.IContainer, java.lang.String, boolean, boolean, boolean)
*/
@Override
protected final InternalXmlStorageElement createStorage(IContainer container, String fileName, boolean reCreate, boolean createEmptyIfNotFound, boolean readOnly) throws CoreException {
InternalXmlStorageElement el = super.createStorage(container, fileName, reCreate, createEmptyIfNotFound, readOnly);
Queue<ICStorageElement> nodesToCheck = new LinkedList<ICStorageElement>();
nodesToCheck.addAll(Arrays.asList(el.getChildren()));
while (!nodesToCheck.isEmpty()) {
ICStorageElement currEl = nodesToCheck.remove();
// If not a storageModule element or doesn't have EXTERNAL_CELEMENT_KEY, continue
if (!XmlStorage.MODULE_ELEMENT_NAME.equals(currEl.getName())
|| currEl.getAttribute(EXTERNAL_CELEMENT_KEY) == null) {
nodesToCheck.addAll(Arrays.asList(currEl.getChildren()));
continue;
}
try {
// Found -- load the Document pointed to (allows multiple layers of indirection if need be)
InternalXmlStorageElement el2 = createStorage(project.getFolder(STORAGE_FOLDER_NAME),
currEl.getAttribute(EXTERNAL_CELEMENT_KEY),
reCreate, createEmptyIfNotFound, readOnly);
// Update the modification stamp
modificationMap.put(currEl.getAttribute(EXTERNAL_CELEMENT_KEY), project.getFolder(STORAGE_FOLDER_NAME).getFile(currEl.getAttribute(EXTERNAL_CELEMENT_KEY)).getModificationStamp());
ICStorageElement currParent = currEl.getParent();
// Get the storageModule element in the new Document
ICStorageElement[] childStorages = el2.getChildrenByName(XmlStorage.MODULE_ELEMENT_NAME);
Assert.isTrue(childStorages.length == 1, "More than one storageModule in external Document!"); //$NON-NLS-1$
// Import the loaded element
currParent.importChild(childStorages[0]);
// Remove the placeholder
currParent.removeChild(currEl);
} catch (CoreException e) {
// If we're here there was a problem loading csettings when there is a .cproject file.
CCorePlugin.log(e);
throw e;
}
}
return el;
}
/*
* Serialize the Project Description:
* - The .cproject file contains the root XML Elements.
* - We serialize the storageModule children of the CConfiguration elements (in the org.eclipse.cdt.settings module)
* to separate files in the .csettings directory to prevent unmanageably large XML deltas
* Return the modification stamp of the main .cproject file as our super method does
* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.settings.model.xml.XmlProjectDescriptionStorage#serialize(org.eclipse.core.resources.IContainer, java.lang.String, org.eclipse.cdt.core.settings.model.ICStorageElement)
*/
@Override
protected long serialize(IContainer container, String file, ICStorageElement element) throws CoreException {
// If the current loaded version is less than our version, then delegate to parent to handle persisting
// i.e. don't auto-upgrade
if (version.compareTo(type.version) < 0)
return super.serialize(container, file, element);
// Copy the original passed in element, as we're going to re-write the children
InternalXmlStorageElement copy = copyElement(element, false);
// Map containing external CConfiguration elements to be serialized
Map<String, InternalXmlStorageElement> externalStorageElements = new HashMap<String, InternalXmlStorageElement>();
// Iterate through the initial children
for (ICStorageElement el : copy.getChildren()) {
// Only interested in root level org.eclipse.cdt.settings storageModules
if (!CProjectDescriptionManager.MODULE_ID.equals(el.getAttribute(XmlStorage.MODULE_ID_ATTRIBUTE)))
continue;
Queue<ICStorageElement> configStorages = new LinkedList<ICStorageElement>();
configStorages.addAll(Arrays.asList(el.getChildren()));
while (!configStorages.isEmpty()) {
InternalXmlStorageElement iEl = (InternalXmlStorageElement)configStorages.remove();
// If not a stroageModule element, the just add children ...
// e.g. configuration element...
if (iEl.getAttribute(XmlStorage.MODULE_ID_ATTRIBUTE) == null) {
configStorages.addAll(Arrays.asList(iEl.getChildren()));
continue;
}
// Persist this storage Element fileName = configurationID_moduleID
String storageId = ((Element)iEl.fElement.getParentNode()).getAttribute(ID) + "_" //$NON-NLS-1$
+ iEl.getAttribute(XmlStorage.MODULE_ID_ATTRIBUTE);
// create a dummy storage for the element <cproject> held
InternalXmlStorageElement newEl = createStorage(project.getFolder(STORAGE_FOLDER_NAME), storageId, false, true, false);
newEl.importChild(copyElement(iEl, false));
externalStorageElements.put(storageId, newEl);
// Clear other attributes and children
iEl.clear();
// Set the external c element key
iEl.fElement.setAttribute(EXTERNAL_CELEMENT_KEY, storageId);
}
}
// Serialize the Root XML document Element (.cproject)
long cproject_mod_time = super.serialize(project, ICProjectDescriptionStorageType.STORAGE_FILE_NAME, copy);
// Check that the .csettings directory exists and is writable
IFolder csettings = project.getFolder(STORAGE_FOLDER_NAME);
try {
CProjectDescriptionStorageManager.ensureWritable(csettings);
if (!csettings.exists())
csettings.create(true, true, new NullProgressMonitor());
} catch (CoreException e) {
if (!csettings.exists())
throw e;
}
// Serialize all the external elements
for (Map.Entry<String, InternalXmlStorageElement> e : externalStorageElements.entrySet())
modificationMap.put(e.getKey(), super.serialize(csettings, e.getKey(), e.getValue()));
return cproject_mod_time;
}
@Override
protected Version getVersion() {
return STORAGE_DESCRIPTION_VERSION;
}
@Override
protected String getStorageTypeId() {
return STORAGE_TYPE_ID;
}
}

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2008 Broadcom Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model.xml2;
import org.eclipse.cdt.internal.core.settings.model.AbstractCProjectDescriptionStorage;
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType;
import org.eclipse.core.resources.IProject;
import org.osgi.framework.Version;
/**
* Concrete implementation of ICProjectDescriptionStorageType
* for instantiating XmlProjectDescriptionStorage2
*/
public class XmlProjectDescriptionStorage2Factory implements ICProjectDescriptionStorageType {
public AbstractCProjectDescriptionStorage getProjectDescriptionStorage(CProjectDescriptionStorageTypeProxy type, IProject project, Version version) {
return new XmlProjectDescriptionStorage2(type, project, version);
}
public boolean createsCProjectXMLFile() {
return true;
}
}

View file

@ -95,4 +95,5 @@ GeneratePDOMApplication.name = GeneratePDOM
defaultProvider.name = Default Provider
templatesExtensionPoint.name = Templates Extension point
templateProcessTypes.name = Process Types Extension point
templateAssociations.name = Template Associations
templateAssociations.name = Template Associations
CProjectDescriptionStorage.name = Project Description Storage Extension point

View file

@ -43,6 +43,11 @@
<extension-point id="CIndex" name="%CIndex.name" schema="schema/CIndex.exsd"/>
<extension-point id="externalSettingsProvider" name="%externalSettingsProvider.name" schema="schema/externalSettingsProvider.exsd"/>
<!-- =================================================================================== -->
<!-- CProjectDescriptionStorage provides addition types of project description storage -->
<!-- =================================================================================== -->
<extension-point id="CProjectDescriptionStorage" name="%CProjectDescriptionStorage.name" schema="schema/CProjectDescriptionStorage.exsd"/>
<!-- =================================================================================== -->
<!-- Define the list of the Binary Parser provided by the CDT -->
<!-- =================================================================================== -->
<extension
@ -610,5 +615,22 @@
<simple name="appName"/>
</processType>
</extension>
<extension
point="org.eclipse.cdt.core.CProjectDescriptionStorage">
<CProjectStorageType
class="org.eclipse.cdt.internal.core.settings.model.xml.XmlProjectDescriptionStorageFactory"
id="XmlProjectDescriptionStorage"
max_version="4.0.0"
name="Xml Storage (single file)"
version="4.0.0">
</CProjectStorageType>
<CProjectStorageType
class="org.eclipse.cdt.internal.core.settings.model.xml2.XmlProjectDescriptionStorage2Factory"
id="XmlProjectDescriptionStorage2"
max_version="5.0.0"
name="Xml Storage (Separate Files)"
version="5.0.0">
</CProjectStorageType>
</extension>
</plugin>

View file

@ -0,0 +1,140 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<meta.schema plugin="org.eclipse.cdt.core" id="CProjectDescriptionStorage" name="%CProjectDescription.name"/>
</appinfo>
<documentation>
This extension point allows contributors to provide their own implementation of the CProjectDescriptionStorage backing store.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appinfo>
<meta.element />
</appinfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="CProjectStorageType"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute translatable="true"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="CProjectStorageType">
<annotation>
<documentation>
CProjectDescriptionStorageType is a concrete type of AbstractCProjectDescriptionStorage which is delegated to for persisting ICStorageElement trees
</documentation>
</annotation>
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
A factory class that implements ICProjectDescriptionStorageType to create AbstractCProjectDescriptionStorages for given IProjects
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType"/>
</appinfo>
</annotation>
</attribute>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
Id of this particular project description storage type
</documentation>
</annotation>
</attribute>
<attribute name="version" type="string" use="required">
<annotation>
<documentation>
Version number of this storage type if min_version and max_version are specified, this version must be in the range (min_version, max_version] i.e. min_version &lt; version &lt;= max_version
This String value must be compatible with org.eclipse.osgi.framework.version
</documentation>
</annotation>
</attribute>
<attribute name="min_version" type="string">
<annotation>
<documentation>
The minimum version of project description supported by this description storage type. If this value is not specified then a default Version.emptyVersion is used
This String value must be compatible with org.eclipse.osgi.framework.version
</documentation>
</annotation>
</attribute>
<attribute name="max_version" type="string">
<annotation>
<documentation>
The maximum version of project description supported by this description storage type. If this is not specified then a value equal to version is used.
This String value must be compatible with org.eclipse.osgi.framework.version
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
Human readable name of this project description type
</documentation>
<appinfo>
<meta.attribute translatable="true"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appinfo>
<meta.section type="since"/>
</appinfo>
<documentation>
6.0
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="apiinfo"/>
</appinfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="implementation"/>
</appinfo>
<documentation>
See the example XmlProjectDescriptionStorage &amp; XmlProjectDescriptionStorage2 in this plugin
</documentation>
</annotation>
</schema>

View file

@ -58,6 +58,7 @@ import org.eclipse.cdt.internal.core.model.WorkingCopy;
import org.eclipse.cdt.internal.core.pdom.PDOMManager;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
@ -683,13 +684,17 @@ public class CCorePlugin extends Plugin {
}
public void mapCProjectOwner(IProject project, String id, boolean override) throws CoreException {
try {
if (!override) {
fNewCProjectDescriptionManager.getDescriptorManager().configure(project, id);
} else {
fNewCProjectDescriptionManager.getDescriptorManager().convert(project, id);
}
} catch (Exception e) {
throw ExceptionFactory.createCoreException(e);
}
}
public ICDescriptorManager getCDescriptorManager() {
return fNewCProjectDescriptionManager.getDescriptorManager();
}

View file

@ -8,46 +8,126 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
* Andrew Ferguson (Symbian)
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.core;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.w3c.dom.Element;
/**
* Models meta-data stored with a CDT project
*
* Consumers should ensure that changes made to an ICDescriptor are done
* in the context of an {@link ICDescriptorOperation}
* via {@link ICDescriptorManager#runDescriptorOperation}
*
* @see ICDescriptorOperation
* @see ICDescriptorManager
*/
public interface ICDescriptor {
public ICOwnerInfo getProjectOwner();
public String getPlatform();
/**
* @return the associated project
*/
public IProject getProject();
public ICExtensionReference[] get(String extensionPoint);
public ICExtensionReference[] get(String extensionPoint, boolean update) throws CoreException;
public ICExtensionReference create(String extensionPoint, String id) throws CoreException;
public void remove(ICExtensionReference extension) throws CoreException;
public void remove(String extensionPoint) throws CoreException;
/**
* Returns an {@link ICExtensionReference}[] corresponding to a particular extensionPoint.
* This array contains all the ICExtensionReferences from all the ICConfigurationDescriptions
* in the project
* @param extensionPointID String extensionPointID
* @return ICExtensionReference[] ICExtensionReference array
* @deprecated
* @use {@link ICConfigurationDescription#get(String)}
*/
@Deprecated
public ICExtensionReference[] get(String extensionPointID);
/**
* Returns an {@link ICExtensionReference}[] corresponding to a particular extensionPoint.
* This array contains all the ICExtensionReferences from all the ICConfigurationDescriptions
* in the project
* @param extensionPointID String extensionPointID
* @param update updates the COwner
* @return ICExtensionReference[] ICExtensionReference array
* @deprecated
*/
@Deprecated
public ICExtensionReference[] get(String extensionPointID, boolean update) throws CoreException;
/**
* Create an ICExtensionReference for the given extensionPointId with id = id.
*
* This is not CConfigurationDescription aware and so is added to all configurations in the project.
* You should instead use:
* {@link ICConfigurationDescription#create(String, String)}
*
* @param extensionPointID
* @param id
* @return the create ICExtensionReference
* @throws CoreException
* @deprecated
* @use {@link ICConfigurationDescription#create(String, String)}
*/
@Deprecated
public ICExtensionReference create(String extensionPointID, String id) throws CoreException;
/**
* Remove a given ICExtensionReference from the project description.
* @param extension
* @throws CoreException
* @deprecated
* @use {@link ICConfigurationDescription#remove(org.eclipse.cdt.core.settings.model.ICConfigExtensionReference)}
*/
@Deprecated
public void remove(ICExtensionReference extension) throws CoreException;
/**
* Remove ICExtensionReferences with the given extensionPoint from
* this descriptor
* @param extensionPoint
* @throws CoreException
* @deprecated
* @use {@link ICConfigurationDescription#remove(String)}
*/
@Deprecated
public void remove(String extensionPoint) throws CoreException;
/**
* Return a storage element corresponding to the id in which
* client related metadata may be stored.
*
* @param id an identifier that uniquely identifies the client
* @return a non-null {@link Element} to which client specific meta-data may be attached
* @return a non-null {@link ICStorageElement} to which client specific meta-data may be attached
* @throws CoreException
* @since 5.1
*/
public ICStorageElement getProjectStorageElement(String id) throws CoreException;
/**
* Remove the storage element with the given ID from the tree
* @param id
* @throws CoreException
*/
public Element getProjectData(String id) throws CoreException;
public void removeProjectStorageElement(String id) throws CoreException;
/**
* Saves any changes made to {@link Element} objects obtained from {@link #getProjectData(String)}
* Saves any changes made to {@link ICStorageElement} objects obtained from {@link #getProjectStorageElement(String)}
* to a CDT defined project meta-data file.
* @throws CoreException
*/
public void saveProjectData() throws CoreException;
/**
* Returns the current settings configuration (which contains this descriptor) -- currently
* equivalent to {@link ICProjectDescription#getDefaultSettingConfiguration()}
* @return the current setting {@link ICConfigurationDescription}
*/
ICConfigurationDescription getConfigurationDescription();
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 QNX Software Systems and others.
* Copyright (c) 2000, 2008 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.core;
@ -20,19 +21,59 @@ public interface ICDescriptorManager {
public void configure(IProject project, String id) throws CoreException;
public void convert(IProject project, String id) throws CoreException;
/**
* Return the ICDescriptor for the project. If project doesn't contain
* an ICDescriptor then one is created.
* Equivalent to: {@link ICDescriptorManager#getDescriptor(IProject, true)}
*
* Users should consider batching changes in an ICDescriptorOperation
*
* @see ICDescriptorManager#getDescriptor(IProject, boolean)
* @param project
* @return ICDescriptor
* @throws CoreException
*/
public ICDescriptor getDescriptor(IProject project) throws CoreException;
/**
* Return the ICDescriptor for the project. If project doesn't contain
* an ICDescriptor and create == true, then one is created
*
* Users should consider batching changes in an ICDescriptorOperation
*
* @param project
* @param create
* @return ICDescriptor
* @throws CoreException
*/
public ICDescriptor getDescriptor(IProject project, boolean create) throws CoreException;
/**
* Atomically runs the descriptor operation on the current project's configuration
*
* The descriptor is automatically 'applied' after the CDescriptorOperation has been run
* @param project
* @param op
* @param monitor
* @throws CoreException
*/
public void runDescriptorOperation(IProject project, ICDescriptorOperation op, IProgressMonitor monitor) throws CoreException;
public void runDescriptorOperation(IProject project,
ICProjectDescription des,
ICDescriptorOperation op,
IProgressMonitor monitor)
throws CoreException;
/**
* Runs the ICDescriptorOperation on the provided ICProjectDescription. The changes are reconciled into
* the provided ICProjectDescription.
*
* Currently this project description may be different from the current project description
* @param project
* @param des
* @param op
* @param monitor
* @throws CoreException
*/
public void runDescriptorOperation(IProject project, ICProjectDescription des, ICDescriptorOperation op,
IProgressMonitor monitor) throws CoreException;
public void addDescriptorListener(ICDescriptorListener listener);
public void removeDescriptorListener(ICDescriptorListener listener);

View file

@ -10,11 +10,22 @@
*******************************************************************************/
package org.eclipse.cdt.core;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
public interface ICDescriptorOperation {
/**
* Call-back method executed atomically on a ICDescriptor in a runnable.
*
* @see ICDescriptorManager#runDescriptorOperation(IProject, ICDescriptorOperation, IProgressMonitor)
* @see ICDescriptorManager#runDescriptorOperation(IProject, ICProjectDescription, ICDescriptorOperation, IProgressMonitor)
* @param descriptor
* @param monitor
* @throws CoreException
*/
void execute(ICDescriptor descriptor, IProgressMonitor monitor) throws CoreException;
}

View file

@ -12,6 +12,9 @@ package org.eclipse.cdt.core;
import org.eclipse.core.resources.IProject;
/**
* This represents an executable extension in the cmodel hierarchy
*/
public interface ICExtension {
public IProject getProject();
public ICExtensionReference getExtensionReference();

View file

@ -4,27 +4,39 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core;
import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
/**
* This is reference to {@link ICExtension} elements as stored
* in the Project Description.
*
* This has no notion of the ICConfigurationDescription,
* for that see {@link ICConfigExtensionReference}
*
* @see ICConfigExtensionReference
* @see ICExtension
* @see ICDescriptor
*/
public interface ICExtensionReference {
/**
* Return the extension point of this reference.
*
*
* @return String
*/
public String getExtension();
/**
* Return the extension ID of this reference.
*
*
* @return String
*/
public String getID();
@ -45,19 +57,19 @@ public interface ICExtensionReference {
* @return the ICDescriptor
*/
public ICDescriptor getCDescriptor();
/**
* Creates and returns a new instance of the cextension executable
* Creates and returns a new instance of the cextension executable
* identified by the &lt;run&gt; attribute of the cextension.
* <p>
* The ICExtension is instantiated using its 0-argument public
* The ICExtension is instantiated using its 0-argument public
* constructor. If the class implements the
* <code>org.eclipse.core.runtime.IExecutableExtension</code> interface, the method
* <code>setInitializationData</code> is called, passing to the object
* the configuration information that was used to create it.
* the configuration information that was used to create it.
* </p>
* <p>
* Unlike other methods on this object, invoking this method may activate
* Unlike other methods on this object, invoking this method may activate
* the plug-in.
* </p>
*
@ -75,18 +87,18 @@ public interface ICExtensionReference {
* <p>
* Each child corresponds to a nested XML element in the configuration
* markup. For example, the configuration markup
*
*
* <pre>
* &lt;view&gt;
* &amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&lt;verticalHint&gt;top&lt;/verticalHint&gt;
* &amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&lt;horizontalHint&gt;left&lt;/horizontalHint&gt;
* &nbsp&nbsp&nbsp&nbsp&lt;verticalHint&gt;top&lt;/verticalHint&gt;
* &nbsp&nbsp&nbsp&nbsp&lt;horizontalHint&gt;left&lt;/horizontalHint&gt;
* &lt;/view&gt;
* </pre>
*
*
* corresponds to a configuration element, named <code>"view"</code>,
* with two children.
* </p>
*
*
* @return the child configuration elements
*/
public IConfigurationElement[] getExtensionElements() throws CoreException;

View file

@ -8,58 +8,143 @@
* Contributors:
* Intel Corporation - Initial API and implementation
* Anton Leherbauer (Wind River Systems)
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.internal.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CDescriptorEvent;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.ICDescriptorManager;
import org.eclipse.cdt.core.ICExtension;
import org.eclipse.cdt.core.ICExtensionReference;
import org.eclipse.cdt.core.ICOwnerInfo;
import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.settings.model.util.CExtensionUtil;
import org.eclipse.cdt.internal.core.settings.model.CConfigurationDescriptionCache;
import org.eclipse.cdt.internal.core.settings.model.CConfigurationSpecSettings;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.cdt.internal.core.settings.model.CStorage;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
import org.eclipse.cdt.internal.core.settings.model.IInternalCCfgInfo;
import org.eclipse.cdt.internal.core.settings.model.InternalXmlStorageElement;
import org.eclipse.cdt.internal.core.settings.model.SynchronizedStorageElement;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.core.runtime.jobs.Job;
public class CConfigBasedDescriptor implements ICDescriptor {
/**
* Concrete ICDescriptor for a Project.
*
* There is only one of these per project. Settings are serialized into all the
* ICConfigurationDescriptions of the project. Methods which change or access data
* on the descriptor use the Eclipse ILock 'fLock' on the given descriptor instance.
*
* Structural changes made to extension elements are persisted immediately to
* the project description.
*
* Changes made to child storage elements are serialized to the project description
* with saveProjectData(...) and the serializingJob.
*
* Users should consider using {@link ICDescriptorManager#runDescriptorOperation} for threadsafe
* access to the project's configuration. However failing this does provide some basic
* concurrency on {@link #getProjectStorageElement(String)} by wrapping the returned
* ICStorageElement in an {@link SynchronizedStorageElement}. Note that this is best
* effort, so concurrent structural changes to the tree (such as one thread removing
* an element from a tree while another is writing to it) may result in inconsistent data
* stored.
*
*/
final public class CConfigBasedDescriptor implements ICDescriptor {
private static final String CEXTENSION_NAME = "cextension"; //$NON-NLS-1$
/** The current default setting configuration description
* Equivalent to {@link ICProjectDescription#getDefaultSettingConfiguration()}*/
private ICConfigurationDescription fCfgDes;
private IProject fProject;
private COwner fOwner;
private final HashMap<String, ArrayList<ICExtensionReference>> fDesMap = new HashMap<String, ArrayList<ICExtensionReference>>();
private final HashMap<String, Element> fStorageDataElMap = new HashMap<String, Element>();
private boolean fApplyOnChange = true;
private boolean fIsDirty;
/** Map: storageModule ID -> ICStorageElement <br/>
* CDescriptor's map of so far uncommited storage elements. */
private final Map<String, SynchronizedStorageElement> fStorageDataElMap = new HashMap<String, SynchronizedStorageElement>();
private volatile boolean fIsDirty;
/** Current CDescriptor Event which tracks changes between operationStart & operationStop */
private CDescriptorEvent fOpEvent;
private boolean fIsOpStarted;
final class CConfigBaseDescriptorExtensionReference implements ICExtensionReference{
private ICConfigExtensionReference fCfgExtRef;
/** Flag indicating whether an operation has started */
private volatile boolean fIsOpStarted;
/** This descriptor's lock */
final ILock fLock = Job.getJobManager().newLock();
/**
* The Job the actually does the data applying (by getting and setting the current project description)
* saveProjectData never does the saving itself, rather it schedules this job to run.
* During the setCProjectDescriptionOperation the changes in this ICDescriptor are synchronized into the
* project description being persisted.
*/
class SerializingJob extends Job {
public SerializingJob(String name) {
super (name);
setSystem(true);
// This rule must contain that in SetCProjectDescriptionOperation
// (Resource scheduling rules are always obtained before data structure locks to prevent deadlocks.)
setRule(ResourcesPlugin.getWorkspace().getRoot());
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
fLock.acquire();
// No point scheduling the run if the project is closed...
if (!getProject().isAccessible())
return Status.CANCEL_STATUS;
serialize();
} catch (CoreException e) {
CCorePlugin.log(e);
} finally {
fLock.release();
}
return Status.OK_STATUS;
}
public void serialize() throws CoreException {
if (!getProject().isAccessible())
throw ExceptionFactory.createCoreException(MessageFormat.format(CCorePlugin.getResourceString("ProjectDescription.ProjectNotAccessible"), getProject().getName())); //$NON-NLS-1$
if(fIsDirty) {
ICProjectDescription des = fCfgDes.getProjectDescription();
if(des.isCdtProjectCreating())
des.setCdtProjectCreated();
CProjectDescriptionManager.getInstance().setProjectDescription(getProject(), des);
fIsDirty = false;
}
}
}
SerializingJob serializingJob = new SerializingJob("CConfigBasedDescriptor Serializing Job"); //$NON-NLS-1$ (system)
/**
* Concrete implementation of ICExtensionReference based on ICConfigExtensionReference elements.
* In the old world ICExtensions had no notion of which configuration they belong to.
* As a result all state that would have be persisted at the ICExtension level is saved to all
* the configurations in the project
*
* This is a lightweight proxy onto ICConfigExtensionReference and doesn't hold any state
* itself (though alters the isDirty state and descriptor event of the containing Descriptor).
*/
final class CConfigBaseDescriptorExtensionReference implements ICExtensionReference {
/** The ICConfigExtensionReference this is based on -- the identifying feature of this ICExtensionReference */
private final ICConfigExtensionReference fCfgExtRef;
CConfigBaseDescriptorExtensionReference(ICConfigExtensionReference cfgRef){
fCfgExtRef = cfgRef;
fCfgExtRef = cfgRef;
}
public ICExtension createExtension() throws CoreException {
@ -67,7 +152,7 @@ public class CConfigBasedDescriptor implements ICDescriptor {
IConfigurationElement el = CExtensionUtil.getFirstConfigurationElement(fCfgExtRef, CEXTENSION_NAME, false);
cExtension = (InternalCExtension)el.createExecutableExtension("run"); //$NON-NLS-1$
cExtension.setExtensionReference(this);
cExtension.setProject(fProject);
cExtension.setProject(getProject());
return (ICExtension)cExtension;
}
@ -105,6 +190,18 @@ public class CConfigBasedDescriptor implements ICDescriptor {
setOpEvent(new CDescriptorEvent(CConfigBasedDescriptor.this, CDescriptorEvent.CDTPROJECT_CHANGED, 0));
}
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof CConfigBaseDescriptorExtensionReference)
return fCfgExtRef.equals(((CConfigBaseDescriptorExtensionReference)obj).fCfgExtRef);
return fCfgExtRef.equals(obj);
}
@Override
public int hashCode() {
return fCfgExtRef.hashCode();
}
}
public CConfigBasedDescriptor(ICConfigurationDescription des) throws CoreException{
@ -114,315 +211,473 @@ public class CConfigBasedDescriptor implements ICDescriptor {
public CConfigBasedDescriptor(ICConfigurationDescription des, boolean write) throws CoreException{
updateConfiguration(des, write);
}
public void setApplyOnChange(boolean apply){
if(fApplyOnChange == apply)
return;
fApplyOnChange = apply;
}
public boolean isApplyOnChange(){
return fApplyOnChange;
}
public void apply(boolean force) throws CoreException{
if(force || fIsDirty){
ICProjectDescription des = fCfgDes.getProjectDescription();
if(des.isCdtProjectCreating())
des.setCdtProjectCreated();
CProjectDescriptionManager.getInstance().setProjectDescription(fProject, des);
fIsDirty = false;
}
}
private void checkApply() throws CoreException {
if(fApplyOnChange){
apply(false);
fIsDirty = false;
} else {
fIsDirty = true;
}
}
public ICExtensionReference create(String extensionPoint, String id)
throws CoreException {
ICConfigExtensionReference ref = fCfgDes.create(extensionPoint, id);
//write is done for all configurations to avoid "data loss" on configuration change
ICProjectDescription des = fCfgDes.getProjectDescription();
ICConfigurationDescription cfgs[] = des.getConfigurations();
for (ICConfigurationDescription cfg : cfgs) {
if(cfg != fCfgDes){
try {
cfg.create(extensionPoint, id);
} catch (CoreException e){
}
}
/**
* Persist the current project description (to persist changes to the ICExtensions)
* @param force
* @throws CoreException
*/
void apply(boolean force) throws CoreException {
fIsDirty |= force;
if (!fIsDirty)
return;
// If we're already serializing the project description, schedule a job
// to perform the serialization...
if (CProjectDescriptionManager.getInstance().isCurrentThreadSetProjectDescription()) {
serializingJob.schedule();
return;
}
// Deadlock warning: path entry, for example, can do getStorageElement
// in resource delta (while holding the workspace lock). As CModelOperation
// runs the job as a workspace runnable, this leads to potential deadlock.
//
// So before applying, we ensure that we hold the project resource rule
// before getting the 'lock' on the datastructures
// final IProject project = getProject();
// Release the lock
final int lockDepth = fLock.getDepth();
for (int i = 0; i < lockDepth ; ++i)
fLock.release();
try {
// This rule must contain that in SetCProjectDescriptionOperation
Job.getJobManager().beginRule(ResourcesPlugin.getWorkspace().getRoot(), new NullProgressMonitor());
try {
fLock.acquire();
serializingJob.serialize();
} finally {
if (lockDepth == 0) // Only release the lock if it wasn't previously held on entrance to this method
fLock.release();
else // Reacquire the lock to the appropriate depth
for (int i = 0; i < lockDepth - 1; i++)
fLock.acquire();
}
} finally {
Job.getJobManager().endRule(ResourcesPlugin.getWorkspace().getRoot());
}
ICExtensionReference r = create(ref);
fIsDirty = true;
checkApply();
if(isOperationStarted())
setOpEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.EXTENSION_CHANGED));
return r;
}
private void checkApply() throws CoreException {
apply(false);
}
/**
* Set the dirty flag
* @param dirty
*/
void setDirty(boolean dirty){
fIsDirty = dirty;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.core.ICDescriptor#create(java.lang.String, java.lang.String)
*/
public ICExtensionReference create(String extensionPoint, String id) throws CoreException {
try {
fLock.acquire();
ICConfigExtensionReference ref = fCfgDes.create(extensionPoint, id);
//write is done for all configurations to avoid "data loss" on configuration change
ICProjectDescription des = fCfgDes.getProjectDescription();
ICConfigurationDescription cfgs[] = des.getConfigurations();
for (ICConfigurationDescription cfg : cfgs) {
if(cfg != fCfgDes){
try {
cfg.create(extensionPoint, id);
} catch (CoreException e){
CCorePlugin.log(e);
}
}
}
ICExtensionReference r = new CConfigBaseDescriptorExtensionReference(ref);
fIsDirty = true;
checkApply();
if(isOperationStarted())
setOpEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.EXTENSION_CHANGED));
return r;
} finally {
fLock.release();
}
}
/**
* Equivalent to {@link #updateConfiguration(ICConfigurationDescription, true)}
* @param des the new ICConfigurationDescription
* @throws CoreException
*/
public void updateConfiguration(ICConfigurationDescription des) throws CoreException{
updateConfiguration(des, true);
}
/**
* Update the currently default (settings) configuration
* @param des
* @param write
* @throws CoreException
*/
public void updateConfiguration(ICConfigurationDescription des, boolean write) throws CoreException{
if(write && des instanceof CConfigurationDescriptionCache)
throw new IllegalArgumentException();
fCfgDes = des;
fProject = fCfgDes.getProjectDescription().getProject();
CConfigurationSpecSettings settings = ((IInternalCCfgInfo)fCfgDes).getSpecSettings();
fOwner = settings.getCOwner();
// settings.setDescriptor(this);
fStorageDataElMap.clear();
}
private CConfigBaseDescriptorExtensionReference create(ICConfigExtensionReference ref){
CConfigBaseDescriptorExtensionReference dr = new CConfigBaseDescriptorExtensionReference(ref);
synchronized (fDesMap) {
ArrayList<ICExtensionReference> list = fDesMap.get(ref.getExtensionPoint());
if(list == null){
list = new ArrayList<ICExtensionReference>(1);
fDesMap.put(ref.getExtensionPoint(), list);
} else {
list.ensureCapacity(list.size() + 1);
}
list.add(dr);
try {
fLock.acquire();
if(write && des instanceof CConfigurationDescriptionCache)
throw new IllegalArgumentException();
fCfgDes = des;
CConfigurationSpecSettings settings = ((IInternalCCfgInfo)fCfgDes).getSpecSettings();
fOwner = settings.getCOwner();
} finally {
fLock.release();
}
return dr;
}
/**
* Attempt to return an ICExtensionReference array based on the ICConfigExtensionReferences
* contained in this project description (which match the extensionPointId).
*
* Fetches all the ICConfigExtensionReferences from the project's configurations.
*
* Previously this cached the current set of ICExtensionReferences,
* but this cache was never used (it was always overwritten by this method).
*
* FIXME re-add caching (the current behaviour mirrors the previous behaviour -- just tidier)
* @return an array of ICExtenionReference
*/
public ICExtensionReference[] get(String extensionPoint) {
ICConfigExtensionReference[] rs = fCfgDes.get(extensionPoint);
ArrayList<ICConfigExtensionReference> refs = new ArrayList<ICConfigExtensionReference>();
refs.addAll(Arrays.asList(rs));
ICConfigurationDescription[] cfgs =
fCfgDes.getProjectDescription().getConfigurations();
for (int i=0; i<cfgs.length; i++) {
if (!fCfgDes.equals(cfgs[i])) {
rs = cfgs[i].get(extensionPoint);
for (int j=0; j<rs.length; j++) {
if (!refs.contains(rs[j]))
refs.add(rs[j]);
}
}
try {
fLock.acquire();
LinkedHashSet<ICExtensionReference> extRefs = new LinkedHashSet<ICExtensionReference>();
// Add the ICConfigExtensionReferences for the current configuration description
for (ICConfigExtensionReference cfgRes : fCfgDes.get(extensionPoint))
extRefs.add(new CConfigBaseDescriptorExtensionReference(cfgRes));
for (ICConfigurationDescription cfg : fCfgDes.getProjectDescription().getConfigurations())
if (!cfg.equals(fCfgDes))
for (ICConfigExtensionReference cfgRes : fCfgDes.get(extensionPoint))
extRefs.add(new CConfigBaseDescriptorExtensionReference(cfgRes));
return extRefs.toArray(new ICExtensionReference[extRefs.size()]);
} finally {
fLock.release();
}
ICConfigExtensionReference cfgRefs[] =
refs.toArray(
new ICConfigExtensionReference[refs.size()]);
if(cfgRefs.length == 0){
return new ICExtensionReference[0];
}
ICExtensionReference[] extRefs = new ICExtensionReference[cfgRefs.length];
synchronized (fDesMap) {
ArrayList<ICExtensionReference> list = fDesMap.get(extensionPoint);
// if(list == null){
// list = new ArrayList(cfgRefs.length);
// fDesMap.put(extensionPoint, list);
// }
// list = (ArrayList)list.clone();
//
// CConfigBaseDescriptorExtensionReference[] refs = (CConfigBaseDescriptorExtensionReference[])list.
// toArray(new CConfigBaseDescriptorExtensionReference[list.size()]);
int num = cfgRefs.length - 1;
for(int i = cfgRefs.length - 1; i >= 0; i--){
ICConfigExtensionReference ref = cfgRefs[i];
int k= -1;
if (list != null) {
for(k= list.size()-1; k >= 0; k--){
CConfigBaseDescriptorExtensionReference r = (CConfigBaseDescriptorExtensionReference)list.get(k);
if(r.fCfgExtRef == ref){
extRefs[num--] = r;
list.remove(k);
break;
}
}
}
if(k < 0){
extRefs[num--] = new CConfigBaseDescriptorExtensionReference(ref);
}
}
if(list == null){
list = new ArrayList<ICExtensionReference>(cfgRefs.length);
fDesMap.put(extensionPoint, list);
} else {
list.clear();
list.ensureCapacity(cfgRefs.length);
}
list.addAll(Arrays.asList(extRefs));
list.trimToSize();
}
return extRefs;
}
public ICExtensionReference[] get(String extensionPoint, boolean update)
throws CoreException {
ICExtensionReference[] refs = get(extensionPoint);
if(refs.length == 0 && update){
boolean prevApplyOnChange = fApplyOnChange;
fApplyOnChange = false;
fOwner.update(fProject, this, extensionPoint);
fApplyOnChange = prevApplyOnChange;
checkApply();
refs = get(extensionPoint);
/*
* (non-Javadoc)
* @see org.eclipse.cdt.core.ICDescriptor#get(java.lang.String, boolean)
*/
public ICExtensionReference[] get(String extensionPoint, boolean update) throws CoreException {
try {
fLock.acquire();
ICExtensionReference[] refs = get(extensionPoint);
if(refs.length == 0 && update){
fOwner.update(getProject(), this, extensionPoint);
checkApply();
refs = get(extensionPoint);
}
return refs;
} finally {
fLock.release();
}
return get(extensionPoint);
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.core.ICDescriptor#getPlatform()
*/
public String getPlatform() {
return fOwner.getPlatform();
try {
fLock.acquire();
return fOwner.getPlatform();
} finally {
fLock.release();
}
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.core.ICDescriptor#getProject()
*/
public IProject getProject() {
return fProject;
try {
fLock.acquire();
return fCfgDes.getProjectDescription().getProject();
} finally {
fLock.release();
}
}
public Element getProjectData(String id) throws CoreException {
// avoid deadlock by using different lock here.
synchronized(fStorageDataElMap /*CProjectDescriptionManager.getInstance()*/){
Element el = fStorageDataElMap.get(id);
if(el == null || el.getParentNode() == null){
InternalXmlStorageElement storageEl = (InternalXmlStorageElement)fCfgDes.getStorage(id, false);
if(storageEl == null){
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.newDocument();
el = CStorage.createStorageXmlElement(doc, id);
doc.appendChild(el);
} catch (ParserConfigurationException e) {
throw ExceptionFactory.createCoreException(e);
}
} else {
el = CProjectDescriptionManager.getInstance().createXmlElementCopy(storageEl);
/**
* Note that in the current implementation of the xml based project description
* it is not safe to work on the same storage element in more than one thread.
*
* It is likely that doing so will return a concurrent modification exception on the
* returned ICStorageElement. We must allow this as this is how the existing implementation
* behaves.
*/
public ICStorageElement getProjectStorageElement(String id) throws CoreException {
try {
fLock.acquire();
// Check if the storage element already exists in our local map
SynchronizedStorageElement storageEl = fStorageDataElMap.get(id);
if(storageEl == null){
ICStorageElement el = fCfgDes.getStorage(id, true);
try {
el = el.createCopy();
} catch (UnsupportedOperationException e) {
throw ExceptionFactory.createCoreException(e);
}
fStorageDataElMap.put(id, el);
storageEl = SynchronizedStorageElement.synchronizedElement(el);
fStorageDataElMap.put(id, storageEl);
}
return el;
return storageEl;
} finally {
fLock.release();
}
}
public void removeProjectStorageElement(String id) throws CoreException {
try {
fLock.acquire();
fStorageDataElMap.put(id, null);
} finally {
fLock.release();
}
}
public ICOwnerInfo getProjectOwner() {
return fOwner;
try {
fLock.acquire();
return fOwner;
} finally {
fLock.release();
}
}
public void remove(ICExtensionReference extension) throws CoreException {
ICConfigExtensionReference ref =((CConfigBaseDescriptorExtensionReference)extension).fCfgExtRef;
fCfgDes.remove(ref);
try {
fLock.acquire();
ICConfigExtensionReference ref = ((CConfigBaseDescriptorExtensionReference)extension).fCfgExtRef;
fCfgDes.remove(ref);
//write is done for all configurations to avoid "data loss" on configuration change
ICProjectDescription des = fCfgDes.getProjectDescription();
ICConfigurationDescription cfgs[] = des.getConfigurations();
for (ICConfigurationDescription cfg : cfgs) {
if(cfg != fCfgDes){
try {
ICConfigExtensionReference rs[] = cfg.get(ref.getExtensionPoint());
for (ICConfigExtensionReference element : rs) {
if(ref.getID().equals(element.getID())){
cfg.remove(element);
break;
// write is done for all configurations to avoid "data loss" on configuration change
for (ICConfigurationDescription cfg : fCfgDes.getProjectDescription().getConfigurations()) {
if(cfg != fCfgDes){
try {
ICConfigExtensionReference rs[] = cfg.get(ref.getExtensionPoint());
for (ICConfigExtensionReference element : rs) {
if(ref.getID().equals(element.getID())){
cfg.remove(element);
break;
}
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
} catch (CoreException e) {
}
}
fIsDirty = true;
checkApply();
if(isOperationStarted())
setOpEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.EXTENSION_CHANGED));
} finally {
fLock.release();
}
fIsDirty = true;
checkApply();
if(isOperationStarted())
setOpEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.EXTENSION_CHANGED));
}
public void remove(String extensionPoint) throws CoreException {
fCfgDes.remove(extensionPoint);
//write is done for all configurations to avoid "data loss" on configuration change
ICProjectDescription des = fCfgDes.getProjectDescription();
ICConfigurationDescription cfgs[] = des.getConfigurations();
for (ICConfigurationDescription cfg : cfgs) {
if(cfg != fCfgDes){
try {
cfg.remove(extensionPoint);
} catch (CoreException e) {
try {
fLock.acquire();
fCfgDes.remove(extensionPoint);
//write is done for all configurations to avoid "data loss" on configuration change
for (ICConfigurationDescription cfg : fCfgDes.getProjectDescription().getConfigurations()) {
if(cfg != fCfgDes){
try {
cfg.remove(extensionPoint);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
}
fIsDirty = true;
checkApply();
if(isOperationStarted())
setOpEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.EXTENSION_CHANGED));
} finally {
fLock.release();
}
fIsDirty = true;
checkApply();
if(isOperationStarted())
setOpEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, CDescriptorEvent.EXTENSION_CHANGED));
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.core.ICDescriptor#saveProjectData()
*/
public void saveProjectData() throws CoreException {
if(CProjectDescriptionManager.getInstance().getDescriptorManager().reconsile(this, fCfgDes.getProjectDescription()))
fIsDirty = true;
checkApply();
if(isOperationStarted())
setOpEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, 0));
try {
fLock.acquire();
// Reconcile changes into the current project description
if(reconcile(this, fCfgDes.getProjectDescription())) {
// Dirty => Apply
fIsDirty = true;
apply(true);
if(isOperationStarted())
setOpEvent(new CDescriptorEvent(this, CDescriptorEvent.CDTPROJECT_CHANGED, 0));
}
} finally {
fLock.release();
}
}
public Map<String, Element> getStorageDataElMap(){
@SuppressWarnings("unchecked")
final HashMap<String, Element> clone = (HashMap<String, Element>)fStorageDataElMap.clone();
return clone;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.core.ICDescriptor#getConfigurationDescription()
*/
public ICConfigurationDescription getConfigurationDescription() {
return fCfgDes;
try {
fLock.acquire();
return fCfgDes;
} finally {
fLock.release();
}
}
/*
* Event handling routines
*/
void setOpEvent(CDescriptorEvent event) {
if(!isOperationStarted())
return;
try {
fLock.acquire();
if(!isOperationStarted())
return;
if (event.getType() == CDescriptorEvent.CDTPROJECT_ADDED) {
fOpEvent = event;
} else if (event.getType() == CDescriptorEvent.CDTPROJECT_REMOVED) {
fOpEvent = event;
} else {
if (fOpEvent == null) {
if (event.getType() == CDescriptorEvent.CDTPROJECT_ADDED) {
fOpEvent = event;
} else if ( (fOpEvent.getFlags() & event.getFlags()) != event.getFlags()) {
fOpEvent = new CDescriptorEvent(event.getDescriptor(), event.getType(),
fOpEvent.getFlags() | event.getFlags());
} else if (event.getType() == CDescriptorEvent.CDTPROJECT_REMOVED) {
fOpEvent = event;
} else {
if (fOpEvent == null) {
fOpEvent = event;
} else if ( (fOpEvent.getFlags() & event.getFlags()) != event.getFlags()) {
fOpEvent = new CDescriptorEvent(event.getDescriptor(), event.getType(),
fOpEvent.getFlags() | event.getFlags());
}
}
} finally {
fLock.release();
}
}
boolean isOperationStarted(){
return fIsOpStarted;
}
void operationStart(){
fIsOpStarted = true;
}
/**
* Mark the operation as over -- return the CDescriptorEvent
* @return
*/
CDescriptorEvent operationStop(){
fIsOpStarted = false;
CDescriptorEvent e = fOpEvent;
fOpEvent = null;
return e;
try {
fLock.acquire();
fIsOpStarted = false;
CDescriptorEvent e = fOpEvent;
fOpEvent = null;
return e;
} finally {
fLock.release();
}
}
/*
*
* The reconcile methods below are for copying storage element changes from the current
* CConfigBasedDescriptor to the passed in writable project description
*
*/
/**
* Copies the changes made to the CConfigBasedDescriptor to the ICProjectDescription
*
* The changes are reconciled into all the project's configurations!
* @param descriptor
* @param des
* @return boolean indicating whether changes were made
*/
public static boolean reconcile(CConfigBasedDescriptor descriptor, ICProjectDescription des){
try {
descriptor.fLock.acquire();
Map<String, SynchronizedStorageElement> map = descriptor.fStorageDataElMap;
boolean reconciled = false;
if(!map.isEmpty()){
for (Map.Entry<String, SynchronizedStorageElement> entry : map.entrySet()) {
String id = entry.getKey();
SynchronizedStorageElement synchStor = entry.getValue();
if (synchStor != null ) {
// Lock the synchronized storage element to prevent further changes
synchronized (synchStor) {
if(reconcile(id, synchStor.getOriginalElement(), des))
reconciled = true;
}
} else {
if (reconcile(id, null, des))
reconciled = true;
}
}
}
return reconciled;
} finally {
descriptor.fLock.release();
}
}
private static boolean reconcile(String id, ICStorageElement newStorEl, ICProjectDescription des) {
ICConfigurationDescription cfgs[] = des.getConfigurations();
boolean reconciled = false;
for(int i = 0; i < cfgs.length; i++){
try {
if(reconcile(id, newStorEl, cfgs[i]))
reconciled = true;
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
return reconciled;
}
private static boolean reconcile(String id, ICStorageElement newStorEl, ICConfigurationDescription cfg) throws CoreException{
CConfigurationSpecSettings setting = ((IInternalCCfgInfo)cfg).getSpecSettings();
ICStorageElement storEl = setting.getStorage(id, false);
boolean modified = false;
if(storEl != null){
if(newStorEl == null){
setting.removeStorage(id);
modified = true;
} else {
if(!newStorEl.equals(storEl)){
setting.importStorage(id, newStorEl);
modified = true;
}
}
} else {
if(newStorEl != null){
setting.importStorage(id, newStorEl);
modified = true;
}
}
return modified;
}
}

View file

@ -79,6 +79,7 @@ pdom.indexer.name=C/C++ Indexer
pdom.indexer.task=Indexing
PDOMIndexerJob.updateMonitorJob=Update Monitor
PDOMManager.unsupportedVersion=The team-shared index cannot be imported, its format is no longer supported.
ProjectDescription.ProjectNotAccessible=Project: {0} is closed or inaccessible\!
CCoreInternals.savePreferencesJob=Save preferences
CConfigBasedDescriptorManager.0=the project is not a CDT project
CConfigBasedDescriptorManager.1=description based descriptor operation can not be nested

View file

@ -36,10 +36,10 @@ import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
import org.eclipse.cdt.core.cdtvariables.ICdtVariable;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.settings.model.util.XmlStorageElement;
import org.eclipse.cdt.internal.core.settings.model.CConfigurationSpecSettings;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
import org.eclipse.cdt.internal.core.settings.model.IInternalCCfgInfo;
import org.eclipse.cdt.internal.core.settings.model.xml.XmlStorageElement;
import org.eclipse.cdt.utils.cdtvariables.CdtVariableResolver;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.CoreException;

View file

@ -28,7 +28,7 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.settings.model.util.XmlStorageElement;
import org.eclipse.cdt.internal.core.settings.model.xml.XmlStorageElement;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

View file

@ -27,6 +27,8 @@ import org.w3c.dom.NodeList;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.doctools.IDocCommentOwner;
@ -117,23 +119,14 @@ class ProjectMap {
private static Map<IPath, String> load(IProject project) throws CoreException {
Map<IPath, String> result= new HashMap<IPath, String>();
ICDescriptor pd= CCorePlugin.getDefault().getCProjectDescription(project, true);
Element e= pd.getProjectData(ATTRVAL_STORAGEID);
if(e.hasChildNodes()) {
NodeList commentOwners= e.getElementsByTagName(ELEMENT_DOC_COMMENT_OWNER);
for(int i=0; i<commentOwners.getLength(); i++) {
Element node= (Element) commentOwners.item(i);
Node commentOwnerIDNode= node.getAttributes().getNamedItem(ATTRKEY_DCO_ID);
if(commentOwnerIDNode != null) {
String commentOwnerID= commentOwnerIDNode.getNodeValue();
NodeList paths= node.getElementsByTagName(ELEMENT_PATH);
for(int j=0; j<paths.getLength(); j++) {
Node path= paths.item(i);
Node pathValue= path.getAttributes().getNamedItem(ATTRKEY_PATH_VALUE);
if(pathValue != null) {
result.put(Path.fromPortableString(pathValue.getNodeValue()), commentOwnerID);
}
ICStorageElement e = pd.getProjectStorageElement(ATTRVAL_STORAGEID);
for (ICStorageElement node : e.getChildrenByName(ELEMENT_DOC_COMMENT_OWNER)) {
String commentOwnerID = node.getAttribute(ATTRKEY_DCO_ID);
if(commentOwnerID != null) {
for (ICStorageElement path : node.getChildrenByName(ELEMENT_PATH)) {
String pathValue= path.getAttribute(ATTRKEY_PATH_VALUE);
if(pathValue != null) {
result.put(Path.fromPortableString(pathValue), commentOwnerID);
}
}
}
@ -148,30 +141,23 @@ class ProjectMap {
ICDescriptor pd= CCorePlugin.getDefault().getCProjectDescription(fProject, true);
// remove current associations
Element data= pd.getProjectData(ATTRVAL_STORAGEID);
NodeList nl= data.getChildNodes();
for(int i=0; i<nl.getLength(); i++) {
Node node= nl.item(i);
if(node.getNodeType()== Node.ELEMENT_NODE) {
data.removeChild(node);
}
}
ICStorageElement data = pd.getProjectStorageElement(ATTRVAL_STORAGEID);
for (ICStorageElement child : data.getChildren())
data.removeChild(child);
// invert and persist associations
for(Iterator<String> i= fMap.values().iterator(); i.hasNext();) {
String cid= i.next();
Element commentNode= data.getOwnerDocument().createElement(ELEMENT_DOC_COMMENT_OWNER);
ICStorageElement commentNode = data.createChild(ELEMENT_DOC_COMMENT_OWNER);
commentNode.setAttribute(ATTRKEY_DCO_ID, cid);
for(Iterator<IPath> j= fMap.keySet().iterator(); j.hasNext(); ) {
IPath path= j.next();
String ccid= fMap.get(path);
if(cid.equals(ccid)) {
Element pathNode= data.getOwnerDocument().createElement(ELEMENT_PATH);
ICStorageElement pathNode = commentNode.createChild(ELEMENT_PATH);
pathNode.setAttribute(ATTRKEY_PATH_VALUE, path.toPortableString());
commentNode.appendChild(pathNode);
}
}
data.appendChild(commentNode);
}
pd.saveProjectData();
}