/******************************************************************************* * Copyright (c) 2000, 2010 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * QNX Software Systems - Initial API and implementation * James Blackburn (Broadcom Corp.) - Use ICStorageElement * Red Hat Inc. - Add set method *******************************************************************************/ package org.eclipse.cdt.make.internal.core; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import javax.xml.parsers.DocumentBuilderFactory; 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; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.w3c.dom.Document; public class ProjectTargets { private static final String MAKE_TARGET_KEY = MakeCorePlugin.getUniqueIdentifier() + ".buildtargets"; //$NON-NLS-1$ private static final String TARGETS_EXT = "targets"; //$NON-NLS-1$ private static final String BUILD_TARGET_ELEMENT = "buildTargets"; //$NON-NLS-1$ private static final String TARGET_ELEMENT = "target"; //$NON-NLS-1$ private static final String TARGET_ATTR_ID = "targetID"; //$NON-NLS-1$ private static final String TARGET_ATTR_PATH = "path"; //$NON-NLS-1$ private static final String TARGET_ATTR_NAME = "name"; //$NON-NLS-1$ private static final String TARGET_STOP_ON_ERROR = "stopOnError"; //$NON-NLS-1$ private static final String TARGET_USE_DEFAULT_CMD = "useDefaultCommand"; //$NON-NLS-1$ private static final String TARGET_ARGUMENTS = "buildArguments"; //$NON-NLS-1$ private static final String TARGET_COMMAND = "buildCommand"; //$NON-NLS-1$ private static final String TARGET_RUN_ALL_BUILDERS = "runAllBuilders"; //$NON-NLS-1$ private static final String BAD_TARGET = "buidlTarget"; //$NON-NLS-1$ private static final String TARGET = "buildTarget"; //$NON-NLS-1$ private HashMap<IContainer, List<IMakeTarget>> targetMap = new HashMap<IContainer, List<IMakeTarget>>(); private IProject project; public ProjectTargets(MakeTargetManager manager, IProject project) { boolean writeTargets = false; File targetFile = null; this.project = project; 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 XML file location if (rootElement.getChildren().length == 0) { IPath targetFilePath = MakeCorePlugin.getDefault().getStateLocation().append(project.getName()).addFileExtension( TARGETS_EXT); targetFile = targetFilePath.toFile(); try { InputStream input = new FileInputStream(targetFile); ICStorageElement oldElement = translateInputStreamToDocument(input); rootElement.importChild(oldElement); writeTargets = true; // update the project description } catch (FileNotFoundException ex) { /* Ignore */ } } 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); } } public IMakeTarget[] get(IContainer container) { List<IMakeTarget> list = targetMap.get(container); if (list != null) { return list.toArray(new IMakeTarget[list.size()]); } return new IMakeTarget[0]; } public void set(IContainer container, IMakeTarget[] targets) throws CoreException { List<IMakeTarget> newList = new ArrayList<IMakeTarget>(); for (IMakeTarget target : targets) { target.setContainer(container); if (newList.contains(target)) { throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1, MakeMessages.getString("MakeTargetManager.target_exists"), null)); //$NON-NLS-1$ } newList.add(target); } targetMap.put(container, newList); } public IMakeTarget findTarget(IContainer container, String name) { List<IMakeTarget> list = targetMap.get(container); if (list != null) { for (IMakeTarget target : list) { if (name.equals(target.getName())) { return target; } } } return null; } public void add(IMakeTarget target) throws CoreException { 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<IMakeTarget>(); targetMap.put(target.getContainer(), list); } list.add(target); } public boolean contains(IMakeTarget target) { List<IMakeTarget> list = targetMap.get(target.getContainer()); if (list != null && list.contains(target)) { return true; } return false; } public boolean remove(IMakeTarget target) { List<IMakeTarget> list = targetMap.get(target.getContainer()); if (list == null || !list.contains(target)) { return false; } boolean found = list.remove(target); if (list.size() == 0) { targetMap.remove(list); } return found; } public IProject getProject() { return project; } /** * Persist the MakeTarget as a child of parent * * @return created 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()); 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 = targetElem.createChild(TARGET_ARGUMENTS); elem.setValue(targetAttr); } targetAttr = target.getBuildAttribute(IMakeTarget.BUILD_TARGET, null); if (targetAttr != null) { elem = targetElem.createChild(TARGET); elem.setValue(targetAttr); } 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()); return targetElem; } /** * Saves the targets to the project description */ 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 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); //Save the results descriptor.saveProjectData(); } /** * This method loads an old style XML document provided in the input stream * and returns an ICStorageElemnt wrapping it. * * @return ICStorageElement or null */ protected ICStorageElement translateInputStreamToDocument(InputStream input) { try { Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input); return XmlStorageUtil.createCStorageTree(document); } catch (Exception e) { MakeCorePlugin.log(e); } return null; } /** * Extract the make target information which is contained in the Storage Element * * @param root - root element * @param manager - MakeTargetManager */ 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; } try { IMakeTarget 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); } } } } } } }