diff options
Diffstat (limited to 'build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java')
-rw-r--r-- | build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java | 566 |
1 files changed, 566 insertions, 0 deletions
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java new file mode 100644 index 00000000000..14c74c84ec1 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java @@ -0,0 +1,566 @@ +/********************************************************************** + * Copyright (c) 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.core; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.xerces.dom.DocumentImpl; +import org.apache.xml.serialize.Method; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.Serializer; +import org.apache.xml.serialize.SerializerFactory; +import org.eclipse.cdt.core.AbstractCExtension; +import org.eclipse.cdt.core.parser.*; +import org.eclipse.cdt.managedbuilder.internal.core.Configuration; +import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.internal.core.Target; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +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.QualifiedName; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * This is the main entry point for getting at the build information + * for the managed build system. + */ +public class ManagedBuildManager extends AbstractCExtension implements IScannerInfoProvider { + + private static final QualifiedName buildInfoProperty = new QualifiedName(ManagedBuilderCorePlugin.getUniqueIdentifier(), "managedBuildInfo"); + private static final String ROOT_ELEM_NAME = "ManagedProjectBuildInfo"; //$NON-NLS-1$ + private static final String FILE_NAME = ".cdtbuild"; //$NON-NLS-1$ + private static final ITarget[] emptyTargets = new ITarget[0]; + public static final String INTERFACE_IDENTITY = ManagedBuilderCorePlugin.getUniqueIdentifier() + "." + "ManagedBuildManager"; //$NON-NLS-1$ + public static final String EXTENSION_POINT_ID = "ManagedBuildInfo"; //$NON-NLS-1$ + + // Targets defined by extensions (i.e., not associated with a resource) + private static boolean extensionTargetsLoaded = false; + private static List extensionTargets; + private static Map extensionTargetMap; + + // Listeners interested in build model changes + private static Map buildModelListeners; + + /** + * Returns the list of targets that are defined by this project, + * projects referenced by this project, and by the extensions. + * + * @param project + * @return + */ + public static ITarget[] getDefinedTargets(IProject project) { + // Make sure the extensions are loaded + loadExtensions(); + + // Get the targets for this project and all referenced projects + List definedTargets = null; + // To Do + + // Create the array and copy the elements over + int size = extensionTargets != null ? + extensionTargets.size() + (definedTargets != null ? definedTargets.size() : 0) : + 0; + + ITarget[] targets = new ITarget[size]; + + int n = 0; + for (int i = 0; i < extensionTargets.size(); ++i) + targets[n++] = (ITarget)extensionTargets.get(i); + + if (definedTargets != null) + for (int i = 0; i < definedTargets.size(); ++i) + targets[n++] = (ITarget)definedTargets.get(i); + + return targets; + } + + /** + * @return + */ + public static Map getExtensionTargetMap() { + if (extensionTargetMap == null) { + extensionTargetMap = new HashMap(); + } + return extensionTargetMap; + } + + /** + * Returns the targets owned by this project. If none are owned, + * an empty array is returned. + * + * @param project + * @return + */ + public static ITarget[] getTargets(IResource resource) { + IManagedBuildInfo buildInfo = getBuildInfo(resource); + + if (buildInfo != null) { + List targets = buildInfo.getTargets(); + return (ITarget[])targets.toArray(new ITarget[targets.size()]); + } else { + return emptyTargets; + } + } + + + /** + * Answers the result of a best-effort search to find a target with the + * specified ID, or <code>null</code> if one is not found. + * + * @param resource + * @param id + * @return + */ + public static ITarget getTarget(IResource resource, String id) { + ITarget target = null; + // Check if the target is spec'd in the build info for the resource + if (resource != null) { + IManagedBuildInfo buildInfo = getBuildInfo(resource); + if (buildInfo != null) + target = buildInfo.getTarget(id); + } + // OK, check the extension map + if (target == null) { + target = (ITarget)getExtensionTargetMap().get(id); + } + return target; + } + + /** + * Creates a new target for the resource based on the parentTarget. + * + * @param resource + * @param parentTarget + * @return new <code>ITarget</code> with settings based on the parent passed in the arguments + * @throws BuildException + */ + public static ITarget createTarget(IResource resource, ITarget parentTarget) + throws BuildException + { + IResource owner = parentTarget.getOwner(); + + if (owner != null && owner.equals(resource)) + // Already added + return parentTarget; + + if (resource instanceof IProject) { + // Must be an extension target (why?) + if (owner != null) + throw new BuildException("addTarget: owner not null"); + } else { + // Owner must be owned by the project containing this resource + if (owner == null) + throw new BuildException("addTarget: null owner"); + if (!owner.equals(resource.getProject())) + throw new BuildException("addTarget: owner not project"); + } + + // Passed validation + return new Target(resource, parentTarget); + } + + /** + * Sets the default configuration for the project. Note that this will also + * update the default target if needed. + * + * @param project + * @param newDefault + */ + public static void setDefaultConfiguration(IProject project, IConfiguration newDefault) { + if (project == null || newDefault == null) { + return; + } + // Set the default in build information for the project + IManagedBuildInfo info = getBuildInfo(project); + if (info != null) { + info.setDefaultConfiguration(newDefault); + } + } + + /** + * @param config + * @param option + */ + private static void setDirty(IConfiguration config, IOption option) { + // Don't bother unless this is something that effect the + if (!(option.getValueType() == IOption.INCLUDE_PATH + || option.getValueType() == IOption.PREPROCESSOR_SYMBOLS)) { + return; + } + // Figure out if there is a listener for this change + IResource resource = config.getOwner(); + List listeners = (List) getBuildModelListeners().get(resource); + if (listeners == null) { + return; + } + ListIterator iter = listeners.listIterator(); + while (iter.hasNext()) { + ((IScannerInfoChangeListener)iter.next()).changeNotification(resource, getScannerInfo(resource)); + } + } + + /** + * Set the string value for an option for a given config. + * + * @param config The configuration the option belongs to. + * @param option The option to set the value for. + * @param value The boolean that the option should contain after the change. + */ + public static void setOption(IConfiguration config, IOption option, boolean value) { + try { + config.setOption(option, value); + setDirty(config, option); + } catch (BuildException e) { + return; + } + } + + /** + * Set the string value for an option for a given config. + * + * @param config The configuration the option belongs to. + * @param option The option to set the value for. + * @param value The value that the option should contain after the change. + */ + public static void setOption(IConfiguration config, IOption option, String value) { + try { + config.setOption(option, value); + setDirty(config, option); + } catch (BuildException e) { + return; + } + } + + /** + * Set the string array value for an option for a given config. + * + * @param config The configuration the option belongs to. + * @param option The option to set the value for. + * @param value The values the option should contain after the change. + */ + public static void setOption(IConfiguration config, IOption option, String[] value) { + try { + config.setOption(option, value); + setDirty(config, option); + } catch (BuildException e) { + return; + } + } + + /** + * Saves the build information associated with a project and all resources + * in the project to the build info file. + * + * @param project + */ + public static void saveBuildInfo(IProject project) { + // Create document + Document doc = new DocumentImpl(); + Element rootElement = doc.createElement(ROOT_ELEM_NAME); + doc.appendChild(rootElement); + + // Save the build info + ManagedBuildInfo buildInfo = (ManagedBuildInfo) getBuildInfo(project); + if (buildInfo != null) + buildInfo.serialize(doc, rootElement); + + // Save the document + ByteArrayOutputStream s = new ByteArrayOutputStream(); + OutputFormat format = new OutputFormat(); + format.setIndenting(true); + format.setLineSeparator(System.getProperty("line.separator")); //$NON-NLS-1$ + String xml = null; + try { + Serializer serializer + = SerializerFactory.getSerializerFactory(Method.XML).makeSerializer(new OutputStreamWriter(s, "UTF8"), format); + serializer.asDOMSerializer().serialize(doc); + xml = s.toString("UTF8"); //$NON-NLS-1$ + IFile rscFile = project.getFile(FILE_NAME); + InputStream inputStream = new ByteArrayInputStream(xml.getBytes()); + // update the resource content + if (rscFile.exists()) { + rscFile.setContents(inputStream, IResource.FORCE, null); + } else { + rscFile.create(inputStream, IResource.FORCE, null); + } + } catch (Exception e) { + return; + } + } + + /** + * @param resource + */ + public static void removeBuildInfo(IResource resource) { + try { + resource.setSessionProperty(buildInfoProperty, null); + } catch (CoreException e) { + } + } + + /** + * Resets the build information for the project and configuration specified in the arguments. + * The build information will contain the settings defined in the plugin manifest. + * + * @param project + * @param configuration + */ + public static void resetConfiguration(IProject project, IConfiguration configuration) { + // Make sure the extensions are loaded + loadExtensions(); + + // Find out the parent of the configuration + IConfiguration parentConfig = configuration.getParent(); + // Find the parent target the configuration + ITarget parentTarget = parentConfig.getTarget(); + + // Get the extension point information + IExtensionPoint extensionPoint = ManagedBuilderCorePlugin.getDefault().getDescriptor().getExtensionPoint(EXTENSION_POINT_ID); + IExtension[] extensions = extensionPoint.getExtensions(); + for (int i = 0; i < extensions.length; ++i) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension.getConfigurationElements(); + for (int j = 0; j < elements.length; ++j) { + IConfigurationElement element = elements[j]; + if (element.getName().equals(ITarget.TARGET_ELEMENT_NAME) && + element.getAttribute(ITarget.ID).equals(parentTarget.getId())) { + // We have the parent target so get the definition for the parent config + IConfigurationElement[] targetElements = element.getChildren(); + for (int k = 0; k < targetElements.length; ++k) { + IConfigurationElement targetElement = targetElements[k]; + if (targetElement.getName().equals(IConfiguration.CONFIGURATION_ELEMENT_NAME) && + targetElement.getAttribute(IConfiguration.ID).equals(parentConfig.getId())) { + // We now have the plugin element the target was originally based on + ((Configuration)configuration).reset(targetElement); + } + } + } + } + } + } + + // Private stuff + + public static void addExtensionTarget(Target target) { + if (extensionTargets == null) { + extensionTargets = new ArrayList(); + } + + extensionTargets.add(target); + getExtensionTargetMap().put(target.getId(), target); + } + + private static ManagedBuildInfo loadBuildInfo(IProject project) { + ManagedBuildInfo buildInfo = null; + IFile file = project.getFile(FILE_NAME); + if (!file.exists()) + return null; + + try { + InputStream stream = file.getContents(); + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document document = parser.parse(stream); + Node rootElement = document.getFirstChild(); + if (rootElement.getNodeName().equals(ROOT_ELEM_NAME)) { + buildInfo = new ManagedBuildInfo(project, (Element)rootElement); + project.setSessionProperty(buildInfoProperty, buildInfo); + } + } catch (Exception e) { + buildInfo = null; + } + + return buildInfo; + } + + private static void loadExtensions() { + if (extensionTargetsLoaded) + return; + extensionTargetsLoaded = true; + + IExtensionPoint extensionPoint = ManagedBuilderCorePlugin.getDefault().getDescriptor().getExtensionPoint(EXTENSION_POINT_ID); + IExtension[] extensions = extensionPoint.getExtensions(); + for (int i = 0; i < extensions.length; ++i) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension.getConfigurationElements(); + for (int j = 0; j < elements.length; ++j) { + IConfigurationElement element = elements[j]; + if (element.getName().equals(ITarget.TARGET_ELEMENT_NAME)) { + new Target(element); + } + } + } + } + + /** + * @param project + * @return + */ + public static boolean manages(IResource resource) { + // The managed build manager manages build information for the + // resource IFF it it is a project and has a build file with the proper + // root element + IProject project = null; + if (resource instanceof IProject){ + project = (IProject)resource; + } else if (resource instanceof IFile) { + project = ((IFile)resource).getProject(); + } else { + return false; + } + IFile file = project.getFile(FILE_NAME); + if (file.exists()) { + try { + InputStream stream = file.getContents(); + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document document = parser.parse(stream); + Node rootElement = document.getFirstChild(); + if (rootElement.getNodeName().equals(ROOT_ELEM_NAME)) { + return true; + } + } catch (Exception e) { + return false; + } + } + return false; + } + + private static ManagedBuildInfo findBuildInfo(IResource resource, boolean create) { + // Make sure the extension information is loaded first + loadExtensions(); + ManagedBuildInfo buildInfo = null; + try { + buildInfo = (ManagedBuildInfo)resource.getSessionProperty(buildInfoProperty); + } catch (CoreException e) { + return buildInfo; + } + + if (buildInfo == null && resource instanceof IProject) { + buildInfo = loadBuildInfo((IProject)resource); + } + + if (buildInfo == null && create) { + try { + buildInfo = new ManagedBuildInfo(); + resource.setSessionProperty(buildInfoProperty, buildInfo); + } catch (CoreException e) { + buildInfo = null; + } + } + + return buildInfo; + } + + public static IManagedBuildInfo getBuildInfo(IResource resource, boolean create) { + return (IManagedBuildInfo) findBuildInfo(resource, create); + } + + public static IManagedBuildInfo getBuildInfo(IResource resource) { + return (IManagedBuildInfo) findBuildInfo(resource, false); + } + + /* + * @return + */ + private static Map getBuildModelListeners() { + if (buildModelListeners == null) { + buildModelListeners = new HashMap(); + } + return buildModelListeners; + } + + /** + * Answers with an interface to the parse information that has been + * associated with the resource specified in the argument. + * + * @deprecated This method is not part of the registration interface. + * Clients of build information should now use getScannerInformation(IResource) + * for one-time information requests. + * + * @param resource + * @return + */ + public static IScannerInfo getScannerInfo(IResource resource) { + return (IScannerInfo) getBuildInfo(resource, false); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.IScannerInfoProvider#getScannerInformation(org.eclipse.core.resources.IResource) + */ + public IScannerInfo getScannerInformation(IResource resource) { + return (IScannerInfo) getBuildInfo(resource, false); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.IScannerInfoProvider#subscribe(org.eclipse.cdt.core.parser.IScannerInfoChangeListener) + */ + public synchronized void subscribe(IResource resource, IScannerInfoChangeListener listener) { + IResource project = null; + if (resource instanceof IProject) { + project = resource; + } else if (resource instanceof IFile) { + project = ((IFile)resource).getProject(); + } else { + return; + } + // Get listeners for this resource + Map map = getBuildModelListeners(); + List list = (List) map.get(project); + if (list == null) { + // Create a new list + list = new ArrayList(); + } + if (!list.contains(listener)) { + // Add the new listener for the resource + list.add(listener); + map.put(project, list); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.IScannerInfoProvider#unsubscribe(org.eclipse.cdt.core.parser.IScannerInfoChangeListener) + */ + public synchronized void unsubscribe(IResource resource, IScannerInfoChangeListener listener) { + IResource project = null; + if (resource instanceof IProject) { + project = resource; + } else if (resource instanceof IFile) { + project = ((IFile)resource).getProject(); + } else { + return; + } + // Remove the listener + Map map = getBuildModelListeners(); + List list = (List) map.get(project); + if (list != null && !list.isEmpty()) { + // The list is not empty so try to remove listener + list.remove(listener); + map.put(project, list); + } + } + +} |