/******************************************************************************* * Copyright (c) 2008, 2011 Thomas Holland (thomas@innot.de) 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: * Thomas Holland - initial API and implementation *******************************************************************************/ package de.innot.avreclipse.mbs; import org.eclipse.cdt.managedbuilder.core.BuildException; import org.eclipse.cdt.managedbuilder.core.IBuildObject; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IFolderInfo; import org.eclipse.cdt.managedbuilder.core.IHoldsOptions; import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedOptionValueHandler; import org.eclipse.cdt.managedbuilder.internal.core.Tool; import org.eclipse.cdt.managedbuilder.internal.core.ToolChain; /** * Handle changes of additional build target options. * * <p> * This class is registered as a <code>valueHandler</code> by the options of * the base toolchain in the AVR Eclipse plugin. All changes to the option * implementing this handler will cause a call to the <code>handleValue</code> * method of this class. * </p> * <p> * The value of the <code>valueHandlerExtraArgument</code> attribute in the * option element is used as the Id of the tool to be added to / removed from * the toolchain. * </p> * <p> * This class is extended from * {@link org.eclipse.cdt.managedbuilder.core.ManagedOptionValueHandler}, which * covers the other methods of the * {@link org.eclipse.cdt.managedbuilder.core.IManagedOptionValueHandler} * interface. * </p> * * @author Thomas Holland * @version 1.0 */ @SuppressWarnings("restriction") public class AddToolsValueHandler extends ManagedOptionValueHandler { /** Array of all available tools on this computer.*/ private final ITool[] alltools = ManagedBuildManager.getRealTools(); /** * Handle Option Change events. * * <p> * Adjust the ToolChain according to the selected option. <code>extraArgument</code> * has the id of the tool to be added or removed from the winAVR toolchain, depending * on the boolean value of the option. * </p> * * @see org.eclipse.cdt.managedbuilder.core.IManagedOptionValueHandler#handleValue(org.eclipse.cdt.managedbuilder.core.IBuildObject, * org.eclipse.cdt.managedbuilder.core.IHoldsOptions, * org.eclipse.cdt.managedbuilder.core.IOption, java.lang.String, int) */ @Override public boolean handleValue(IBuildObject configuration, IHoldsOptions holder, IOption option, String extraArgument, int event) { Boolean value = null; try { value = option.getBooleanValue(); } catch (BuildException e1) { // something wrong with the plugin.xml e1.printStackTrace(); return false; } if (value == null) { return false; } // At the EVENT_LOAD event the toolchain exists, but has not been correctly // initialized. Especially the options have not been set to their persistent / // default state and are always at <code>true</code>. Not usable, although // it would be nice to adjust the toolchain to the defaults with this event, // as it is always generated at eclipse load time. For the time being the // defaults have to be done via <enablement> elements in the plugin.xml. if (event == EVENT_LOAD) { return false; } // sanity check, could only happen with mistakes in the plugin.xml if (extraArgument == null) { return false; } // The IFolderInfo API has the required modifyToolChain() method. IFolderInfo fi = null; if (configuration instanceof IConfiguration) { fi = ((IConfiguration) configuration).getRootFolderInfo(); } else if (configuration instanceof IFolderInfo) { fi = (IFolderInfo) configuration; } else { return false; } // System.out // .println("\n\n------------------- AddTools handlevalue() -------------------"); // System.out.print("event=" + event + ", "); // System.out.print(value.booleanValue() == true ? "add " : "remove "); // System.out.println(extraArgument + " ToolchainID: " // + fi.getToolChain().getId()); // System.out.print("Toolchain before: "); // dumpTC(fi.getFilteredTools()); if (value) { /* * Add tool to toolchain */ if (fi.getToolsBySuperClassId(extraArgument).length != 0) { // tool already in toolchain return false; } ITool[] add = new ITool[1]; // modifyToolChain() requires an Array of Tools as Argument // find the tool in the list of all tools for (int i = 0; i < alltools.length; i++) { ITool tool = alltools[i]; while (tool.getSuperClass() != null) { tool = tool.getSuperClass(); } if (extraArgument.equals(tool.getId())) { // found it add[0] = tool; break; } } if (add[0] != null) { // System.out.println("internal toolid = " + add[0].getId()); try { fi.modifyToolChain(new ITool[0], add); } catch (BuildException e) { // What can cause this exception ? e.printStackTrace(); return false; } // System.out.println(add[0].getId() + " added"); /* Small hack to get the tool to the end of the list * IFolderInfo.modifyToolChain() makes no guarantees * about the ordering of added tools. Removing / Adding * numerous times will result in an predetermined but * uncontrollable tool order (probably the order of the * internal HashMap or something). * This might break in future versions of CDT as it uses * an undocumented internal API. */ if (fi.getToolChain() instanceof ToolChain) { ToolChain tc = (ToolChain) fi.getToolChain(); // The toolchain has a new instance of the tool we added. // find it and remove it and add it again to move it to // the end of the internal list. ITool[] tctools = tc.getToolsBySuperClassId(add[0].getId()); if (tctools.length != 0) { tc.removeTool((Tool) tctools[0]); tc.addTool((Tool) tctools[0]); } } } // System.out.print("Toolchain after: "); // dumpTC(fi.getFilteredTools()); } else { /* * remove tool from toolchain */ ITool[] remove = fi.getToolsBySuperClassId(extraArgument); if (remove.length != 0) { // System.out.println("internal toolid = " + remove[0].getId()); try { fi.modifyToolChain(remove, new ITool[0]); } catch (BuildException e) { // What can cause this exception ? e.printStackTrace(); return false; } // System.out.println(remove[0].getId() + " removed"); } // System.out.print("Toolchain after: "); // dumpTC(fi.getFilteredTools()); } return false; } /** * Dump array of ITools * * Used for debugging. * * @param tools */ // private void dumpTC(ITool[] tools) { // System.out.print("["); // for (int i = 0; i < tools.length; i++) { // System.out.print(ManagedBuildManager.getRealTool(tools[i]).getId() // .substring(12) // + ", "); // } // System.out.println("]"); // // } }