/*******************************************************************************
* Copyright (c) 2007, 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.internal.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.make.core.IMakeCommonBuildInfo;
import org.eclipse.cdt.managedbuilder.core.IBuilder;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.core.IManagedProject;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.core.ManagedCProjectNature;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
public class BuilderFactory {
private static final String PREFIX = "org.eclipse.cdt.make.core"; //$NON-NLS-1$
// private static final String PREFIX_WITH_DOT = PREFIX + '.'; //$NON-NLS-1$
static final String BUILD_COMMAND = PREFIX + ".buildCommand"; //$NON-NLS-1$
static final String BUILD_LOCATION = PREFIX + ".buildLocation"; //$NON-NLS-1$
static final String STOP_ON_ERROR = PREFIX + ".stopOnError"; //$NON-NLS-1$
static final String USE_DEFAULT_BUILD_CMD = PREFIX + ".useDefaultBuildCmd"; //$NON-NLS-1$
static final String BUILD_TARGET_AUTO = PREFIX + ".autoBuildTarget"; //$NON-NLS-1$
static final String BUILD_TARGET_INCREMENTAL = PREFIX + ".incrementalBuildTarget"; //$NON-NLS-1$
static final String BUILD_TARGET_FULL = PREFIX + ".fullBuildTarget"; //$NON-NLS-1$
static final String BUILD_TARGET_CLEAN = PREFIX + ".cleanBuildTarget"; //$NON-NLS-1$
static final String BUILD_FULL_ENABLED = PREFIX + ".enableFullBuild"; //$NON-NLS-1$
static final String BUILD_CLEAN_ENABLED = PREFIX + ".enableCleanBuild"; //$NON-NLS-1$
static final String BUILD_INCREMENTAL_ENABLED = PREFIX + ".enabledIncrementalBuild"; //$NON-NLS-1$
static final String BUILD_AUTO_ENABLED = PREFIX + ".enableAutoBuild"; //$NON-NLS-1$
static final String BUILD_ARGUMENTS = PREFIX + ".buildArguments"; //$NON-NLS-1$
static final String ENVIRONMENT = PREFIX + ".environment"; //$NON-NLS-1$
static final String BUILD_APPEND_ENVIRONMENT = PREFIX + ".append_environment"; //$NON-NLS-1$
static final String CONTENTS = PREFIX + ".contents"; //$NON-NLS-1$
static final String CONTENTS_BUILDER = PREFIX + ".builder"; //$NON-NLS-1$
static final String CONTENTS_BUILDER_CUSTOMIZATION = PREFIX + ".builderCustomization"; //$NON-NLS-1$
static final String CONTENTS_CONFIGURATION_IDS = PREFIX + ".configurationIds"; //$NON-NLS-1$
static final String CONTENTS_ACTIVE_CFG_SETTINGS = PREFIX + ".activeConfigSettings"; //$NON-NLS-1$
// static final String IDS = PREFIX + ".ids"; //$NON-NLS-1$
static final String CONFIGURATION_IDS = PREFIX + ".configurationIds"; //$NON-NLS-1$
static final IBuilder[] EMPTY_BUILDERS_ARRAY = new IBuilder[0];
static final String[] EMPTY_STRING_ARRAY = new String[0];
static final IConfiguration[] EMPTY_CFG_ARAY = new IConfiguration[0];
private static class BuildArgsStorageElement extends MapStorageElement{
public BuildArgsStorageElement(Map<String, String> map, MapStorageElement parent) {
super(map, parent);
}
public BuildArgsStorageElement(String name, MapStorageElement parent) {
super(name, parent);
}
@Override
public String getAttribute(String name) {
String value = super.getAttribute(name);
if(value == null){
String keys[] = Builder.toBuildAttributes(name);
for(int i = 0; i < keys.length; i++){
value = super.getAttribute(keys[i]);
if(value != null)
break;
}
}
return value;
}
// protected String getMapKey(String name) {
// if(name.indexOf('.') == -1)
// return PREFIX_WITH_DOT + name;
// return super.getMapKey(name);
// }
@Override
public void setAttribute(String name, String value) {
String[] names = Builder.toBuildAttributes(name);
String attrName = names.length != 0 ? names[names.length - 1] : null;
if(attrName == null && BuilderFactory.USE_DEFAULT_BUILD_CMD.equals(name))
attrName = BuilderFactory.USE_DEFAULT_BUILD_CMD;
if(attrName != null)
super.setAttribute(attrName, value);
}
@Override
protected MapStorageElement createChildElement(Map<String, String> childMap) {
return new BuildArgsStorageElement(childMap, this);
}
@Override
protected MapStorageElement createChildElement(String name) {
return new BuildArgsStorageElement(name, this);
}
}
/* public static IMakeBuilderInfo create(Preferences prefs, String builderID, boolean useDefaults) {
return new BuildInfoPreference(prefs, builderID, useDefaults);
}
public static IMakeBuilderInfo create(IProject project, String builderID) throws CoreException {
return new BuildInfoProject(project, builderID);
}
public static IMakeBuilderInfo create(Map args, String builderID) {
return new BuildInfoMap(args, builderID);
}
*/
/*
private static IBuilder customizeBuilder(IBuilder builder, Map args){
if(args.get(IBuilder.ID) == null){
args = new HashMap(args);
String id = builder.getSuperClass().getId();
id = ManagedBuildManager.calculateChildId(id, null);
args.put(IBuilder.ID, id);
}
MapStorageElement el = new MapStorageElement(args, null);
Builder builder = new Builder(builder.getParent(), )
}
*/
public static Map<String, String> createBuildArgs(IConfiguration cfgs[], IBuilder builder){
Map<String, String> map = builderToMap(builder);
cfgsToMap(cfgs, map);
map.put(CONTENTS, /*CONTENTS_BUILDER_CUSTOMIZATION*/CONTENTS_BUILDER);
return map;
}
public static Map<String, String> createBuildArgs(IConfiguration cfgs[]){
Map<String, String> map = new HashMap<String, String>();
cfgsToMap(cfgs, map);
map.put(CONTENTS, CONTENTS_CONFIGURATION_IDS);
return map;
}
private static Map<String, String> cfgIdsToMap(String ids[], Map<String, String> map){
map.put(CONFIGURATION_IDS, MapStorageElement.encodeList(Arrays.asList(ids)));
return map;
}
private static String[] cfgIdsFromMap(Map<String, String> map){
String idsString = map.get(CONFIGURATION_IDS);
if(idsString != null){
List<String> list = MapStorageElement.decodeList(idsString);
return list.toArray(new String[list.size()]);
}
return EMPTY_STRING_ARRAY;
}
private static IConfiguration[] configsFromMap(Map<String, String> map, IManagedBuildInfo info){
String ids[] = cfgIdsFromMap(map);
if(ids.length == 0){
IConfiguration cfg = info.getDefaultConfiguration();
if(cfg != null)
return new IConfiguration[]{cfg};
return EMPTY_CFG_ARAY;
}
IManagedProject mProj = info.getManagedProject();
if(mProj != null)
return idsToConfigurations(ids, mProj.getConfigurations());
return EMPTY_CFG_ARAY;
}
private static IConfiguration[] idsToConfigurations(String ids[], IConfiguration allCfgs[]){
List<IConfiguration> list = new ArrayList<IConfiguration>(ids.length);
for(int i = 0; i < ids.length; i++){
String id = ids[i];
for(int j = 0; j < allCfgs.length; j++){
if(allCfgs[j].getId().equals(id)){
list.add(allCfgs[j]);
break;
}
}
}
return list.toArray(new IConfiguration[list.size()]);
}
private static Map<String, String> cfgsToMap(IConfiguration cfgs[], Map<String, String> map){
String ids[] = getCfgIds(cfgs);
return cfgIdsToMap(ids, map);
}
private static String[] getCfgIds(IConfiguration cfgs[]){
String ids[] = new String[cfgs.length];
for(int i = 0; i < cfgs.length; i++){
ids[i] = cfgs[i].getId();
}
return ids;
}
private static Map<String, String> builderToMap(IBuilder builder){
MapStorageElement el = new MapStorageElement("", null); //$NON-NLS-1$
((Builder)builder).serialize(el, false);
return el.toStringMap();
}
private static Map<String, String> builderBuildArgsMap(IBuilder builder){
MapStorageElement el = new BuildArgsStorageElement("", null); //$NON-NLS-1$
((Builder)builder).serializeRawData(el);
Boolean d = Boolean.valueOf(builder.isDefaultBuildCmd());
el.setAttribute(BuilderFactory.USE_DEFAULT_BUILD_CMD, d.toString());
Map<String, String> map = el.toStringMap();
map.put(CONTENTS, CONTENTS_ACTIVE_CFG_SETTINGS);
return map;
}
public static IBuilder createCustomBuilder(IConfiguration cfg, String builderId) throws CoreException{
IBuilder builder = cfg.getBuilder();
if(!builderId.equals(builder.getId())){
builder = ManagedBuildManager.getExtensionBuilder(builderId);
}
if(builder != null)
return createCustomBuilder(cfg, builder);
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ManagedMakeMessages.getResourceString("BuilderFactory.1"), null)); //$NON-NLS-1$
}
public static IBuilder createCustomBuilder(IConfiguration cfg, IBuilder base){
String subId;
String subName = base.getName();
if (base.getSuperClass() != null) {
subId = ManagedBuildManager.calculateChildId(
base.getSuperClass().getId(),
null);
} else {
subId = ManagedBuildManager.calculateChildId(
base.getId(),
null);
}
return new Builder(cfg.getToolChain(), subId, subName, (Builder)base);
}
public static IBuilder createBuilderFromCommand(IConfiguration cfg, ICommand command){
Map<String, String> args = command.getArguments();
if(!args.containsKey(IBuilder.ID)){
args.put(IBuilder.ID, ManagedBuildManager.calculateChildId(command.getBuilderName(), null));
}
//TODO: do we need a to check for the non-customization case ?
return createBuilder(cfg, args, cfg.getBuilder() != null);
}
public static IBuilder createBuilderForEclipseBuilder(IConfiguration cfg, String eclipseBuilderID) throws CoreException {
IProject project = cfg.getOwner().getProject();
ICommand command = getBuildSpec(project.getDescription(), eclipseBuilderID);
if (command == null) {
throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.getUniqueIdentifier(), -1,
ManagedMakeMessages.getResourceString("BuildInfoFactory.Missing_Builder") + eclipseBuilderID, null)); //$NON-NLS-1$
}
return createBuilderFromCommand(cfg, command);
// Map args = command.getArguments();
// if(!args.containsKey(IBuilder.ID)){
// args.put(IBuilder.ID, ManagedBuildManager.calculateChildId(eclipseBuilderID, null));
// }
//
// return createBuilder(cfg, args);
}
public static ICommand getBuildSpec(IProjectDescription description, String builderID) {
ICommand[] commands = description.getBuildSpec();
for (int i = 0; i < commands.length; ++i) {
if (commands[i].getBuilderName().equals(builderID)) {
return commands[i];
}
}
return null;
}
@SuppressWarnings("deprecation")
private static IBuilder createBuilder(IConfiguration cfg, Map<String, String> args, boolean customization){
IToolChain tCh = cfg.getToolChain();
IBuilder cfgBuilder = cfg.getEditableBuilder();
Builder builder;
if(customization){
builder = (Builder)createCustomBuilder(cfg, cfgBuilder);
//adjusting settings
String tmp = args.get(ErrorParserManager.PREF_ERROR_PARSER);
if(tmp != null && tmp.length() == 0)
args.remove(ErrorParserManager.PREF_ERROR_PARSER);
tmp = args.get(USE_DEFAULT_BUILD_CMD);
if(tmp != null){
if(Boolean.valueOf(tmp).equals(Boolean.TRUE)){
args.remove(IMakeCommonBuildInfo.BUILD_COMMAND);
args.remove(IMakeCommonBuildInfo.BUILD_ARGUMENTS);
} else {
args.put(IBuilder.ATTRIBUTE_IGNORE_ERR_CMD, ""); //$NON-NLS-1$
args.put(IBuilder.ATTRIBUTE_PARALLEL_BUILD_CMD, ""); //$NON-NLS-1$
}
}
//end adjusting settings
MapStorageElement el = new BuildArgsStorageElement(args, null);
builder.loadFromProject(el);
} else {
if(args.get(IBuilder.ID) == null){
args.put(IBuilder.ID, ManagedBuildManager.calculateChildId(cfg.getId(), null));
}
MapStorageElement el = new BuildArgsStorageElement(args, null);
builder = new Builder(tCh, el, ManagedBuildManager.getVersion().toString());
}
return builder;
}
public static IBuilder[] createBuilders(IProject project, Map<String, String> args){
IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project);
IBuilder[] builders = null;
if(info != null){
if(args == null){
IConfiguration cfg = info.getDefaultConfiguration();
IBuilder builder = cfg.getEditableBuilder();
builders = new IBuilder[]{builder};
} else {
String type = args.get(CONTENTS);
if(type == null || CONTENTS_BUILDER_CUSTOMIZATION.equals(type)){
IConfiguration cfg = info.getDefaultConfiguration();
IBuilder builder;
if(args.size() == 0){
builder = cfg.getEditableBuilder();
} else {
builder = createBuilder(cfg, args, true);
}
builders = new IBuilder[]{builder};
} else if (CONTENTS_ACTIVE_CFG_SETTINGS.equals(type)) {
IConfiguration cfg = info.getDefaultConfiguration();
IBuilder builder = cfg.getEditableBuilder();
builders = new IBuilder[]{builder};
} else if (CONTENTS_BUILDER.equals(type)){
IConfiguration cfgs[] = configsFromMap(args, info);
if(cfgs.length != 0){
List<IBuilder> list = new ArrayList<IBuilder>(cfgs.length);
for(int i = 0; i < cfgs.length; i++){
IBuilder builder = createBuilder(cfgs[i], args, false);
if(builder != null)
list.add(builder);
}
builders = list.toArray(new IBuilder[list.size()]);
}
} else if (CONTENTS_CONFIGURATION_IDS.equals(type)){
IConfiguration cfgs[] = configsFromMap(args, info);
if(cfgs.length != 0){
List<IBuilder> list = new ArrayList<IBuilder>(cfgs.length);
for(int i = 0; i < cfgs.length; i++){
list.add(cfgs[i].getEditableBuilder());
}
builders = list.toArray(new IBuilder[list.size()]);
}
} /*else if (CONTENTS_BUILDER_CUSTOMIZATION.equals(type)){
String idsString = (String)args.get(CONFIGURATION_IDS);
if(idsString != null){
String[] ids = CDataUtil.stringToArray(idsString, SEPARATOR);
if(ids.length != 0){
IManagedProject mProj = info.getManagedProject();
List list = new ArrayList(ids.length);
for(int i = 0; i < ids.length; i++){
IConfiguration cfg = mProj.getConfiguration(ids[i]);
if(cfg != null){
IBuilder builder = customizeBuilder(cfg.getEditableBuilder(), args);
if(builder != null)
list.add(builder);
}
}
builders = (IBuilder[])list.toArray(new IBuilder[list.size()]);
}
}
}*/
}
}
if(builders != null)
return builders;
return EMPTY_BUILDERS_ARRAY;
}
public static int applyBuilder(IProjectDescription eDes, IBuilder builder){
return applyBuilder(eDes, CommonBuilder.BUILDER_ID, builder);
}
public static final int CMD_UNDEFINED = -1;
public static final int NO_CHANGES = 0;
public static final int CMD_CHANGED = 1;
public static int applyBuilder(IProjectDescription eDes, String eBuilderId, IBuilder builder){
ICommand cmd = ManagedCProjectNature.getBuildSpec(eDes, eBuilderId);
if(cmd == null)
return CMD_UNDEFINED;
if(applyBuilder(cmd, builder)){
ManagedCProjectNature.setBuildSpec(eDes, cmd);
return CMD_CHANGED;
}
return NO_CHANGES;
}
public static boolean applyBuilder(ICommand cmd, IBuilder builder) {
Map<String, String> oldMap = cmd.getArguments();
Map<String, String> map = builderBuildArgsMap(builder);
if(oldMap.equals(map))
return false;
cmd.setArguments(map);
cmd.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, builder.isAutoBuildEnable());
cmd.setBuilding(IncrementalProjectBuilder.FULL_BUILD, builder.isFullBuildEnabled());
cmd.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, builder.isIncrementalBuildEnabled());
cmd.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, builder.isCleanBuildEnabled());
return true;
}
}