/*******************************************************************************
* Copyright (c) 2004, 2010 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.managedbuilder.projectconverter;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IBuilder;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IConfigurationV2;
import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.core.IManagedProject;
import org.eclipse.cdt.managedbuilder.core.IOption;
import org.eclipse.cdt.managedbuilder.core.IProjectType;
import org.eclipse.cdt.managedbuilder.core.ITarget;
import org.eclipse.cdt.managedbuilder.core.ITargetPlatform;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.core.IToolReference;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.internal.core.Builder;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.internal.core.Tool;
import org.eclipse.cdt.managedbuilder.internal.core.ToolChain;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* @noextend This class is not intended to be subclassed by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
*/
class UpdateManagedProject20 {
private static final String ID_SEPARATOR = "."; //$NON-NLS-1$
/**
* @param monitor the monitor to allow users to cancel the long-running operation
* @param project the <code>IProject</code> that needs to be upgraded
*/
static void doProjectUpdate(IProgressMonitor monitor, final IProject project) throws CoreException {
String[] projectName = new String[]{project.getName()};
IFile file = project.getFile(ManagedBuildManager.SETTINGS_FILE_NAME);
File settingsFile = file.getLocation().toFile();
if (!settingsFile.exists()) {
monitor.done();
return;
}
// Backup the file
monitor.beginTask(ConverterMessages.getFormattedString("UpdateManagedProject20.0", projectName), 1); //$NON-NLS-1$
IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project);
UpdateManagedProjectManager.backupFile(file, "_20backup", monitor, project); //$NON-NLS-1$
try {
// Load the old build file
InputStream stream = new FileInputStream(settingsFile);
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = parser.parse(stream);
// Clone the target based on the proper target definition
NodeList targetNodes = document.getElementsByTagName(ITarget.TARGET_ELEMENT_NAME);
// This is a guess, but typically the project has 1 target, 2 configs, and 6 tool defs
int listSize = targetNodes.getLength();
monitor.beginTask(ConverterMessages.getFormattedString("UpdateManagedProject20.1", projectName), listSize * 9); //$NON-NLS-1$
for (int targIndex = 0; targIndex < listSize; ++targIndex) {
Element oldTarget = (Element) targetNodes.item(targIndex);
String oldTargetId = oldTarget.getAttribute(ITarget.ID);
IManagedProject newProject = convertTarget(project, oldTarget, monitor);
// Remove the old target
if (newProject != null) {
info.removeTarget(oldTargetId);
monitor.worked(9);
}
}
// Upgrade the version
((ManagedBuildInfo)info).setVersion("2.1.0"); //$NON-NLS-1$
info.setValid(true);
}catch (CoreException e){
throw e;
}catch (Exception e) {
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
e.getMessage(), e));
} finally {
// If the tree is locked spawn a job to this.
IWorkspace workspace = project.getWorkspace();
// boolean treeLock = workspace.isTreeLocked();
ISchedulingRule rule = workspace.getRuleFactory().createRule(project);
// if (treeLock) {
//since the java synchronized mechanism is now used for the build info loadding,
//initiate the job in all cases
WorkspaceJob job = new WorkspaceJob(ConverterMessages.getResourceString("UpdateManagedProject.notice")) { //$NON-NLS-1$
@Override
public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
ManagedBuildManager.saveBuildInfoLegacy(project, false);
return Status.OK_STATUS;
}
};
job.setRule(rule);
job.schedule();
// } else {
// ManagedBuildManager.saveBuildInfo(project, false);
// }
monitor.done();
}
}
protected static IManagedProject convertTarget(IProject project, Element oldTarget, IProgressMonitor monitor)
throws CoreException{
// What we want to create
IManagedProject newProject = null;
IProjectType newParent = null;
// Get the parent
String parentID = oldTarget.getAttribute(ITarget.PARENT);
String targetID = oldTarget.getAttribute(ITarget.ID);
// Get the new target definitions we need for the conversion
newParent = ManagedBuildManager.getProjectType(parentID);
if (newParent == null) {
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ConverterMessages.getFormattedString("UpdateManagedProject20.9",parentID), null)); //$NON-NLS-1$
}
try {
// Create a new ManagedProject based on the new parent
newProject = ManagedBuildManager.createManagedProject(project, newParent);
// Create new configurations
NodeList configNodes = oldTarget.getElementsByTagName(IConfigurationV2.CONFIGURATION_ELEMENT_NAME);
for (int configIndex = 0; configIndex < configNodes.getLength(); ++configIndex) {
try{
convertConfiguration(newProject, newParent, (Element) configNodes.item(configIndex), monitor);
}
catch(CoreException e){
//TODO: implement logging
//should we continue or fail ??
}
}
IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project);
IConfiguration[] newConfigs = newProject.getConfigurations();
if (newConfigs.length > 0) {
info.setDefaultConfiguration(newConfigs[0]);
info.setSelectedConfiguration(newConfigs[0]);
}
else{
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ConverterMessages.getFormattedString("UpdateManagedProject20.10",newProject.getName()), null)); //$NON-NLS-1$
}
} catch (BuildException e) {
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ConverterMessages.getFormattedString("UpdateManagedProject20.11",new String[]{project.getName(),e.getMessage()}), null)); //$NON-NLS-1$
}
monitor.worked(1);
return newProject;
}
protected static void convertConfiguration(IManagedProject newProject, IProjectType newParent, Element oldConfig, IProgressMonitor monitor)
throws CoreException {
IConfiguration newParentConfig = null;
IConfiguration newConfig = null;
// Figure out what the original parent of the config is
String parentId = oldConfig.getAttribute(IConfigurationV2.PARENT);
newParentConfig = newParent.getConfiguration(parentId);
if (newParentConfig == null) {
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ConverterMessages.getFormattedString("UpdateManagedProject20.2", parentId), null)); //$NON-NLS-1$
}
// Generate a random number for the new config id
int randomElement = ManagedBuildManager.getRandomNumber();
String newConfigId = parentId + ID_SEPARATOR + randomElement;
// Create the new configuration
newConfig = newProject.createConfiguration(newParentConfig, newConfigId);
if(oldConfig.hasAttribute(IConfigurationV2.NAME))
newConfig.setName(oldConfig.getAttribute(IConfigurationV2.NAME));
Element targetEl = (Element)oldConfig.getParentNode();
if(targetEl.hasAttribute(ITarget.ARTIFACT_NAME))
newConfig.setArtifactName(targetEl.getAttribute(ITarget.ARTIFACT_NAME));
if(targetEl.hasAttribute(ITarget.ERROR_PARSERS))
newConfig.setErrorParserIds(targetEl.getAttribute(ITarget.ERROR_PARSERS));
if(targetEl.hasAttribute(ITarget.CLEAN_COMMAND))
newConfig.setCleanCommand(targetEl.getAttribute(ITarget.CLEAN_COMMAND));
if(targetEl.hasAttribute(ITarget.EXTENSION))
newConfig.setArtifactExtension(targetEl.getAttribute(ITarget.EXTENSION));
// Convert the tool references
IToolChain toolChain = newConfig.getToolChain();
((ToolChain)toolChain).checkForMigrationSupport();
if(targetEl.hasAttribute(ITarget.OS_LIST)){
String oses = targetEl.getAttribute(ITarget.OS_LIST);
String osList[] = oses.split(","); //$NON-NLS-1$
for (int i = 0; i < osList.length; ++i) {
osList[i]=osList[i].trim();
}
toolChain.setOSList(osList);
}
if(targetEl.hasAttribute(ITarget.ARCH_LIST)){
String archs = targetEl.getAttribute(ITarget.ARCH_LIST);
String archList[] = archs.split(","); //$NON-NLS-1$
for (int i = 0; i < archList.length; ++i) {
archList[i]=archList[i].trim();
}
toolChain.setArchList(archList);
}
if(targetEl.hasAttribute(ITarget.BINARY_PARSER)){
String binaryParser = targetEl.getAttribute(ITarget.BINARY_PARSER);
ITargetPlatform targetPlatform = toolChain.getTargetPlatform();
if(targetPlatform.isExtensionElement()){
int nnn = ManagedBuildManager.getRandomNumber();
String subId = targetPlatform.getId() + "." + nnn; //$NON-NLS-1$
String builderName = targetPlatform.getName() + "." + newConfig.getName(); //$NON-NLS-1$
toolChain.createTargetPlatform(targetPlatform,subId,builderName,false);
}
targetPlatform.setBinaryParserList(new String[]{binaryParser}); // Older projects have only a single binary parser.
}
if(targetEl.hasAttribute(ITarget.MAKE_COMMAND)){
String makeCommand = targetEl.getAttribute(ITarget.MAKE_COMMAND);
IBuilder builder = toolChain.getBuilder();
if (builder.isExtensionElement()) {
int nnn = ManagedBuildManager.getRandomNumber();
String subId = builder.getId() + "." + nnn; //$NON-NLS-1$
String builderName = builder.getName() + "." + newConfig.getName(); //$NON-NLS-1$
builder = toolChain.createBuilder(builder, subId, builderName, false);
}
builder.setCommand(makeCommand);
}
if(targetEl.hasAttribute(ITarget.MAKE_ARGS)){
String makeArguments = targetEl.getAttribute(ITarget.MAKE_ARGS);
IBuilder builder = toolChain.getBuilder();
if (builder.isExtensionElement()) {
int nnn = ManagedBuildManager.getRandomNumber();
String subId = builder.getId() + "." + nnn; //$NON-NLS-1$
String builderName = builder.getName() + "." + newConfig.getName(); //$NON-NLS-1$
builder = toolChain.createBuilder(builder, subId, builderName, false);
}
builder.setArguments(makeArguments);
}
// by now if a builder is going to be created, it will have been
Builder builder = (Builder)toolChain.getBuilder();
if (! builder.isExtensionElement()) {
builder.checkForMigrationSupport();
}
NodeList toolRefNodes = oldConfig.getElementsByTagName(IConfigurationV2.TOOLREF_ELEMENT_NAME);
for (int refIndex = 0; refIndex < toolRefNodes.getLength(); ++refIndex) {
try{
convertToolRef(toolChain, (Element) toolRefNodes.item(refIndex), monitor);
}
catch(CoreException e){
newProject.removeConfiguration(newConfigId);
throw e;
}
}
monitor.worked(1);
}
protected static void convertToolRef(IToolChain toolChain, Element oldToolRef, IProgressMonitor monitor)
throws CoreException {
if(!oldToolRef.hasAttribute(IToolReference.ID)) {
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ConverterMessages.getResourceString("UpdateManagedProject20.3"), null)); //$NON-NLS-1$
}
String toolId = oldToolRef.getAttribute(IToolReference.ID);
IConfiguration configuration = toolChain.getParent();
ITool tools[] = configuration.getTools();
if(tools == null) {
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ConverterMessages.getResourceString("UpdateManagedProject20.4"), null)); //$NON-NLS-1$
}
ITool tool = null;
for(int i = 0; i < tools.length; i++){
ITool curTool = tools[i];
ITool parent = curTool.getSuperClass();
String curToolId = curTool.getId();
while (parent != null) {
String parentId = parent.getId();
if(parentId.equals(toolId))
break;
parent = parent.getSuperClass();
}
if(parent == null)
continue;
try{
Integer.decode(curToolId.substring(curToolId.lastIndexOf('.')+1));
}
catch(IndexOutOfBoundsException e){
continue;
}
catch(NumberFormatException e){
continue;
}
tool = curTool;
break;
}
if(tool == null){
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ConverterMessages.getFormattedString("UpdateManagedProject20.5",toolId), null)); //$NON-NLS-1$
}
// Check for migration support
((Tool)tool).checkForMigrationSupport();
//the tool found, proceed with conversion ...
if(oldToolRef.hasAttribute(IToolReference.COMMAND))
tool.setToolCommand(oldToolRef.getAttribute(IToolReference.COMMAND));
if(oldToolRef.hasAttribute(IToolReference.OUTPUT_FLAG))
tool.setOutputFlag(oldToolRef.getAttribute(IToolReference.OUTPUT_FLAG));
if(oldToolRef.hasAttribute(IToolReference.OUTPUT_PREFIX))
tool.setOutputPrefix(oldToolRef.getAttribute(IToolReference.OUTPUT_PREFIX));
if(oldToolRef.hasAttribute(IToolReference.OUTPUTS)){
String outputs = oldToolRef.getAttribute(IToolReference.OUTPUTS);
tool.setOutputsAttribute(outputs);
}
NodeList optRefs = oldToolRef.getElementsByTagName(ITool.OPTION_REF);
for (int refIndex = optRefs.getLength() - 1; refIndex >= 0; --refIndex) {
convertOptionRef(toolChain, tool, (Element) optRefs.item(refIndex), monitor);
}
monitor.worked(1);
}
protected static void convertOptionRef(IToolChain toolChain, ITool tool, Element optRef, IProgressMonitor monitor)
throws CoreException {
if(!optRef.hasAttribute(IOption.ID)){
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ConverterMessages.getResourceString("UpdateManagedProject20.6"), null)); //$NON-NLS-1$
}
String optId = optRef.getAttribute(IOption.ID);
IConfiguration configuration = toolChain.getParent();
IOption options[] = tool.getOptions();
IOption option = null;
for(int i = 0; i < options.length; i++){
IOption curOption = options[i];
IOption parent = curOption.getSuperClass();
if(parent == null)
continue;
for (;parent.getSuperClass()!=null;parent = parent.getSuperClass()) {
// empty body, the loop is to find superclass
}
String parentId = parent.getId();
if(!parentId.equals(optId))
continue;
option = curOption;
break;
}
if(option == null)
option = tool.getOptionById(optId);
if (option != null) { // Ignore options that don't have a match
try{
int type = option.getValueType();
switch(type){
case IOption.BOOLEAN:{
if(optRef.hasAttribute(IOption.DEFAULT_VALUE)){
Boolean bool = new Boolean(optRef.getAttribute(IOption.DEFAULT_VALUE));
configuration.setOption(tool,option,bool.booleanValue());
}
break;
}
case IOption.ENUMERATED:
case IOption.STRING:{
if(optRef.hasAttribute(IOption.DEFAULT_VALUE))
configuration.setOption(tool,option,optRef.getAttribute(IOption.DEFAULT_VALUE));
break;
}
case IOption.STRING_LIST:
case IOption.INCLUDE_PATH:
case IOption.PREPROCESSOR_SYMBOLS:
case IOption.LIBRARIES:
case IOption.OBJECTS:{
Vector<String> values = new Vector<String>();
NodeList nodes = optRef.getElementsByTagName(IOption.LIST_VALUE);
for (int j = 0; j < nodes.getLength(); ++j) {
Node node = nodes.item(j);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Boolean isBuiltIn = new Boolean(((Element)node).getAttribute(IOption.LIST_ITEM_BUILTIN));
if (!isBuiltIn.booleanValue()) {
values.add(((Element)node).getAttribute(IOption.LIST_ITEM_VALUE));
}
}
}
configuration.setOption(tool,option,values.toArray(new String[values.size()]));
break;
}
default:
break;
}
}
catch(BuildException e){
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ConverterMessages.getFormattedString("UpdateManagedProject20.8",e.getMessage()), e)); //$NON-NLS-1$
}
}
}
}