| Index: src/main/org/apache/tools/ant/helper/ProjectHelper2.java |
| =================================================================== |
| --- src/main/org/apache/tools/ant/helper/ProjectHelper2.java (revision 1132928) |
| +++ src/main/org/apache/tools/ant/helper/ProjectHelper2.java (working copy) |
| @@ -27,6 +27,7 @@ |
| import org.apache.tools.ant.Target; |
| import org.apache.tools.ant.Task; |
| import org.apache.tools.ant.UnknownElement; |
| +import org.apache.tools.ant.DebugTask; |
| import org.apache.tools.ant.types.Resource; |
| import org.apache.tools.ant.types.resources.FileProvider; |
| import org.apache.tools.ant.types.resources.URLProvider; |
| @@ -923,7 +924,11 @@ |
| target.setProject(project); |
| target.setLocation(new Location(context.getLocator())); |
| context.addTarget(target); |
| - |
| + boolean isTarget = false; |
| + if(!(target instanceof ExtensionPoint)) { |
| + isTarget = true; |
| + } |
| + |
| for (int i = 0; i < attrs.getLength(); i++) { |
| String attrUri = attrs.getURI(i); |
| if (attrUri != null && !attrUri.equals("") && !attrUri.equals(uri)) { |
| @@ -1015,6 +1020,18 @@ |
| } |
| } |
| } |
| + |
| + if(isTarget && name.equals(project.getBreakAt())) { |
| + // If the current element is a target and it is the same one as specified |
| + // for Ant to suspend execution at, then add an internal dependency on |
| + // the Debug Target |
| + DebugTask.createDebugTarget(project); |
| + |
| + // add this dependency to the end of the dependency list so that this target |
| + // executes immediately ahead of the -breakAt target |
| + target.addDependency(DebugTask.DEBUG_TARGET_NAME); |
| + } |
| + |
| if (!isInIncludeMode && context.isIgnoringProjectTag() |
| && (prefix = getTargetPrefix(context)) != null) { |
| // In an imported file (and not completely |
| Index: src/main/org/apache/tools/ant/Project.java |
| =================================================================== |
| --- src/main/org/apache/tools/ant/Project.java (revision 1132928) |
| +++ src/main/org/apache/tools/ant/Project.java (working copy) |
| @@ -210,6 +210,19 @@ |
| private boolean keepGoingMode = false; |
| |
| /** |
| + * Contains the target to break the execution at. |
| + */ |
| + protected String breakAt; |
| + |
| + public void setBreakAt(String breakAt) { |
| + this.breakAt = breakAt; |
| + } |
| + |
| + public String getBreakAt() { |
| + return breakAt; |
| + } |
| + |
| + /** |
| * Set the input handler. |
| * |
| * @param handler the InputHandler instance to use for gathering input. |
| Index: src/main/org/apache/tools/ant/DebugTask.java |
| =================================================================== |
| --- src/main/org/apache/tools/ant/DebugTask.java (revision 0) |
| +++ src/main/org/apache/tools/ant/DebugTask.java (revision 0) |
| @@ -0,0 +1,329 @@ |
| +package org.apache.tools.ant; |
| + |
| +import java.util.ArrayList; |
| +import java.util.Date; |
| +import java.util.HashSet; |
| +import java.util.Iterator; |
| +import java.util.List; |
| +import java.util.Map; |
| +import java.util.Set; |
| + |
| +import org.apache.tools.ant.BuildException; |
| +import org.apache.tools.ant.ComponentHelper; |
| +import org.apache.tools.ant.Project; |
| +import org.apache.tools.ant.Target; |
| +import org.apache.tools.ant.Task; |
| +import org.apache.tools.ant.input.DefaultInputHandler; |
| +import org.apache.tools.ant.input.InputHandler; |
| +import org.apache.tools.ant.input.InputRequest; |
| +import org.apache.tools.ant.taskdefs.PathConvert; |
| +import org.apache.tools.ant.taskdefs.Property; |
| +import org.apache.tools.ant.types.Path; |
| +import org.apache.tools.ant.types.Reference; |
| +import org.apache.tools.ant.types.ResourceCollection; |
| +import org.apache.tools.ant.util.StringUtils; |
| + |
| +/** |
| + * A stand alone debug task that plugs into the build through projecthelper |
| + * class by injecting a dependency at the end of a target. This is a POC and |
| + * does not yet work for Extension-Points. |
| + */ |
| +public class DebugTask extends Task { |
| + /** |
| + * Debugger prompt |
| + */ |
| + public static final String PROMPT = "DEBUGGER> "; |
| + |
| + /** |
| + * Standard target name for the internal debugger |
| + */ |
| + public static final String DEBUG_TARGET_NAME = "-internal-debugger"; |
| + |
| + /* |
| + * A static final debug target that is injected as a dependency. We may need |
| + * to have more than one such target if we are to allow multiple |
| + * break-points in the build. |
| + */ |
| + private static final Target debugTarget = new Target(); |
| + |
| + /* |
| + * Set of all commands that can be interpreted at runtime. |
| + */ |
| + private static Set supportedCommands = new HashSet(); |
| + |
| + static { |
| + // add any more commands to be supported here |
| + // if need be, this can be considered to be |
| + // moved to a separate properties file |
| + supportedCommands.add("locate"); |
| + supportedCommands.add("inspect"); |
| + supportedCommands.add("return"); |
| + } |
| + |
| + public void execute() throws BuildException { |
| + // expect input here |
| + InputRequest ir = new InputRequest(PROMPT); |
| + InputHandler ih = new DefaultInputHandler(); |
| + String command = null; |
| + getProject().log( |
| + StringUtils.LINE_SEP |
| + + "-------- Ant Command Line Debugger --------" |
| + + StringUtils.LINE_SEP + StringUtils.LINE_SEP); |
| + |
| + // keep accepting inputs, until the user enters the return command |
| + do { |
| + ih.handleInput(ir); |
| + command = ir.getInput(); |
| + handleCommand(command); |
| + getProject().log(""); // log a new line |
| + } while (!"return".equals(command)); |
| + |
| + // resume build execution on this |
| + getProject().log( |
| + StringUtils.LINE_SEP |
| + + "--------- Resuming Ant Execution ----------" |
| + + StringUtils.LINE_SEP); |
| + } |
| + |
| + /** |
| + * Static method to create a runtime-debug target. For purposes of Command |
| + * Line Debugger (CLD), the target returned by this method, and identified |
| + * by DEBUG_TARGET_NAME must be added at the end of the dependency list of |
| + * the target where the break point exists. |
| + * |
| + * @param project |
| + * @return |
| + */ |
| + public static Target createDebugTarget(Project project) { |
| + // see what is the best value for the Location to assume? |
| + // Location loc = new Location(??); |
| + |
| + debugTarget.setProject(project); |
| + debugTarget.setName(DEBUG_TARGET_NAME); |
| + project.addTarget(debugTarget); |
| + // create an instance of debug task and attach it to this project |
| + Task debugtask = project.createTask("debug"); |
| + debugtask.setProject(project); |
| + debugtask.setTaskName("Debugger"); |
| + debugTarget.addTask(debugtask); |
| + return debugTarget; |
| + } |
| + |
| + /* |
| + * Interprets user input and decides if the command is supported or should |
| + * be rejected. |
| + */ |
| + protected void handleCommand(String command) { |
| + if (command == null || command.trim().length() == 0) { |
| + getProject().log("Invalid command. Use /? for more information."); |
| + } |
| + command = command.trim(); |
| + if (command.equals("/?")) { |
| + printUsage(); |
| + return; |
| + } |
| + |
| + String[] tokens = command.split(" "); |
| + if (!supportedCommands.contains(tokens[0])) { |
| + printUsage(); |
| + return; |
| + } |
| + |
| + DebugSupport[] debuggers = new DebugSupport[] { new NoOp(), |
| + new Inspector(), new Locator() }; |
| + DebugSupport selected = null; |
| + for (int j = 0; j < debuggers.length; j++) { |
| + if (debuggers[j].commandSupported(tokens[0])) |
| + selected = debuggers[j]; |
| + } |
| + selected.execute(getProject(), tokens); |
| + } |
| + |
| + protected void printUsage() { |
| + // log all help stuff here |
| + getProject() |
| + .log( |
| + "You may use one of the following commands: locate, inspect, return"); |
| + getProject() |
| + .log( |
| + "Type the command followed by /? for more information. Eg. inspect /?"); |
| + } |
| + |
| + protected static List searchTask(Class expectedTaskClass, Project project) { |
| + List result = new ArrayList(); |
| + for (Iterator iterator = project.getTargets().values().iterator(); iterator |
| + .hasNext();) { |
| + Target t = (Target) iterator.next(); |
| + for (int i = 0; i < t.getTasks().length; i++) { |
| + Task task = t.getTasks()[i]; |
| + Class taskClass = ComponentHelper.getComponentHelper(project) |
| + .getComponentClass(task.getTaskType()); |
| + // will need to see in what cases it could return a null type |
| + // perhaps failing when the task is using a custom antlib |
| + // defined task |
| + if (taskClass != null && taskClass.equals(expectedTaskClass)) { |
| + result.add(task); |
| + } |
| + } |
| + } |
| + return result; |
| + } |
| + |
| + /** |
| + * An interface for supporting debug commands. |
| + */ |
| + public static interface DebugSupport { |
| + |
| + /** |
| + * Check if this command is supported. |
| + * |
| + * @param command |
| + * @return |
| + */ |
| + public boolean commandSupported(String command); |
| + |
| + /** |
| + * Main execution body of the class. Pass all command parameters. |
| + * |
| + * @param project |
| + * @param params |
| + */ |
| + public void execute(Project project, String[] params); |
| + |
| + /** |
| + * Prints usage of the command. |
| + * |
| + * @param project |
| + */ |
| + public void printUsage(Project project); |
| + |
| + } |
| + |
| + /** |
| + * Used to implement commands that should not be handled by |
| + * {@link DebugSupport} at all. Example, the 'return' command |
| + */ |
| + public static final class NoOp implements DebugSupport { |
| + |
| + public boolean commandSupported(String command) { |
| + return "return".equalsIgnoreCase(command); |
| + } |
| + |
| + public void execute(Project project, String[] params) { |
| + // do nothing |
| + } |
| + |
| + public void printUsage(Project project) { |
| + }; |
| + } |
| + |
| + /** |
| + * Locates properties / paths in static build sources |
| + */ |
| + public static final class Locator implements DebugSupport { |
| + |
| + public boolean commandSupported(String command) { |
| + return "locate".equalsIgnoreCase(command); |
| + } |
| + |
| + public void execute(Project project, String[] params) { |
| + // the command syntax is 'locate property some.property' |
| + // or 'locate path some.path |
| + if (params.length != 3 || "/?".equals(params[1])) { |
| + printUsage(project); |
| + return; |
| + } |
| + |
| + List matches = null; |
| + String key = null; |
| + if ("property".equalsIgnoreCase(params[1])) { |
| + // locate and publish the property |
| + matches = DebugTask.searchTask(Property.class, project); |
| + key = "name"; |
| + } else if ("path".equalsIgnoreCase(params[1])) { |
| + // locate and publish the path |
| + matches = DebugTask.searchTask(Path.class, project); |
| + key = "id"; |
| + } else { |
| + // see if any other component may be supported |
| + project.log("Unexpected component: " + params[1]); |
| + project.log("Supported components are property, path."); |
| + return; |
| + } |
| + |
| + // probably accept some kind of a query from end user and select the |
| + // target object based on the query |
| + for (Iterator iterator = matches.iterator(); iterator.hasNext();) { |
| + Task task = (Task) iterator.next(); |
| + // display attributes |
| + Map attributeMap = task.getWrapper().getAttributeMap(); |
| + if (!params[2].equals(attributeMap.get(key))) { |
| + continue; |
| + } |
| + String value = (String) attributeMap.get("value"); |
| + project.log("Detected a property by name [" + params[2] |
| + + "]. Build file value: " + value); |
| + // and their respected location |
| + project.log("Located at: " + task.getLocation().toString()); |
| + } |
| + } |
| + |
| + public void printUsage(Project project) { |
| + project.log("Incorrect Parameters"); |
| + project.log("Usage: locate property/path propertyname/pathname"); |
| + } |
| + } |
| + |
| + /** |
| + * Inspects the current value of a property, path or some reference. |
| + */ |
| + public static final class Inspector implements DebugSupport { |
| + |
| + public boolean commandSupported(String command) { |
| + return "inspect".equalsIgnoreCase(command); |
| + } |
| + |
| + public void execute(Project project, String[] params) { |
| + if (params.length < 3 || "/?".equals(params[1])) { |
| + printUsage(project); |
| + } |
| + |
| + if ("property".equalsIgnoreCase(params[1])) { |
| + // show all matches for a property |
| + Object value = PropertyHelper.getProperty(project, params[2]); |
| + if (value != null) { |
| + project.log("Detected a property by name [" + params[1] |
| + + "]. Current value: " + value); |
| + } else { |
| + project.log("Found no such property."); |
| + } |
| + } else if ("path".equalsIgnoreCase(params[1])) { |
| + // look optional component |
| + // the remaining part of the string could be: |
| + // id=<someid> or refid=<somerefid> |
| + Object ref = project.getReference(params[2]); |
| + if (ref instanceof ResourceCollection) { |
| + if (ref != null) { |
| + PathConvert path = (PathConvert) project |
| + .createTask("pathconvert"); |
| + path.setProject(project); |
| + path.setPathSep(StringUtils.LINE_SEP + " - "); |
| + path.add((ResourceCollection) ref); |
| + path.execute(); |
| + } else { |
| + project.log("No path-reference found for " + params[2]); |
| + } |
| + } else { |
| + project.log("No path found for reference id: " + params[2]); |
| + } |
| + } |
| + |
| + } |
| + |
| + public void printUsage(Project project) { |
| + project.log("Incorrect Parameters"); |
| + project.log("Usage: inspect property some.property"); |
| + project.log(" inspect path path.id"); |
| + } |
| + } |
| +} |
| |
| Property changes on: src\main\org\apache\tools\ant\DebugTask.java |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + native |
| |
| Index: src/main/org/apache/tools/ant/taskdefs/defaults.properties |
| =================================================================== |
| --- src/main/org/apache/tools/ant/taskdefs/defaults.properties (revision 1132928) |
| +++ src/main/org/apache/tools/ant/taskdefs/defaults.properties (working copy) |
| @@ -230,3 +230,4 @@ |
| renameext=org.apache.tools.ant.taskdefs.optional.RenameExtensions |
| starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut |
| style=org.apache.tools.ant.taskdefs.XSLTProcess |
| +debug=org.apache.tools.ant.DebugTask |
| Index: src/main/org/apache/tools/ant/Main.java |
| =================================================================== |
| --- src/main/org/apache/tools/ant/Main.java (revision 1132928) |
| +++ src/main/org/apache/tools/ant/Main.java (working copy) |
| @@ -149,6 +149,11 @@ |
| private boolean proxy = false; |
| |
| /** |
| + * Target at which to break execution sequence |
| + */ |
| + private String breakAt = null; |
| + |
| + /** |
| * Prints the message of the Throwable if it (the message) is not |
| * <code>null</code>. |
| * |
| @@ -382,6 +387,8 @@ |
| throw new BuildException(msg); |
| } else if (arg.equals("-autoproxy")) { |
| proxy = true; |
| + } else if (arg.equals("-breakAt")) { |
| + breakAt = args[++i]; |
| } else if (arg.startsWith("-")) { |
| // we don't have any more args to recognize! |
| String msg = "Unknown argument: " + arg; |
| @@ -761,7 +768,7 @@ |
| |
| |
| project.init(); |
| - |
| + project.setBreakAt(breakAt); |
| // resolve properties |
| PropertyHelper propertyHelper |
| = (PropertyHelper) PropertyHelper.getPropertyHelper(project); |