| /******************************************************************************* |
| * Copyright (c) 2000, 2022 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - derived implementation |
| * Blake Meike (blakem@world.std.com)- patch for bug 31691 and bug 34488 |
| * Rob Stryker - Bug 459188 - InternalAntRunner tries to set null user property |
| *******************************************************************************/ |
| |
| package org.eclipse.ant.internal.core.ant; |
| |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.PrintStream; |
| import java.net.URL; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.ListIterator; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Properties; |
| import java.util.Vector; |
| |
| import org.apache.tools.ant.AntTypeDefinition; |
| import org.apache.tools.ant.BuildEvent; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.BuildListener; |
| import org.apache.tools.ant.BuildLogger; |
| import org.apache.tools.ant.ComponentHelper; |
| import org.apache.tools.ant.DefaultLogger; |
| import org.apache.tools.ant.DemuxOutputStream; |
| import org.apache.tools.ant.Diagnostics; |
| import org.apache.tools.ant.Main; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.ProjectHelper; |
| import org.apache.tools.ant.Target; |
| import org.apache.tools.ant.TaskAdapter; |
| import org.apache.tools.ant.XmlLogger; |
| import org.eclipse.ant.core.AntCorePlugin; |
| import org.eclipse.ant.core.AntCorePreferences; |
| import org.eclipse.ant.core.AntSecurityException; |
| import org.eclipse.ant.core.ProjectInfo; |
| import org.eclipse.ant.core.Property; |
| import org.eclipse.ant.core.TargetInfo; |
| import org.eclipse.ant.core.Task; |
| import org.eclipse.ant.core.Type; |
| import org.eclipse.ant.internal.core.AbstractEclipseBuildLogger; |
| import org.eclipse.ant.internal.core.AntCoreUtil; |
| import org.eclipse.ant.internal.core.AntSecurityManager; |
| import org.eclipse.ant.internal.core.IAntCoreConstants; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.FileLocator; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.variables.VariablesPlugin; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.Version; |
| |
| /** |
| * Eclipse application entry point into Ant. Derived from the original Ant Main class to ensure that the functionality is equivalent when running in |
| * the platform. |
| */ |
| public class InternalAntRunner { |
| |
| private IProgressMonitor monitor; |
| private ArrayList<String> buildListeners; |
| private String buildFileLocation; |
| |
| /** |
| * Targets we want to run. |
| */ |
| private Vector<String> targets; |
| |
| private Map<String, String> userProperties; |
| private boolean noExplicitUserProperties = true; |
| |
| private Project currentProject; |
| |
| private String defaultTarget; |
| |
| private BuildLogger buildLogger = null; |
| |
| /** |
| * Cache of the Ant version number when it has been loaded |
| */ |
| private String antVersionNumber = null; |
| |
| /** Current message output status. Follows Project.MSG_XXX */ |
| private int messageOutputLevel = Project.MSG_INFO; |
| |
| /** Indicates whether output to the log is to be unadorned. */ |
| private boolean emacsMode = false; |
| |
| /** Indicates we should only parse and display the project help information */ |
| private boolean projectHelp = false; |
| |
| /** Stream that we are using for logging */ |
| private PrintStream out = System.out; |
| |
| /** Stream that we are using for logging error messages */ |
| private PrintStream err = System.err; |
| |
| /** |
| * The Ant logger class. There may be only one logger. It will have the right to use the 'out' PrintStream. The class must implement the |
| * BuildLogger interface. An empty String indicates that no logger is to be used. A <code>null</code> name indicates that the |
| * <code>org.apache.tools.ant.DefaultLogger</code> will be used. |
| */ |
| private String loggerClassname = null; |
| |
| /** Extra arguments to be parsed as command line arguments. */ |
| private String[] extraArguments = null; |
| |
| private boolean executed = false; |
| |
| private ArrayList<String> propertyFiles = new ArrayList<>(); |
| |
| private URL[] customClasspath = null; |
| |
| /** |
| * The Ant InputHandler class. There may be only one input handler. |
| */ |
| private String inputHandlerClassname = null; |
| |
| private String buildAntHome = null; |
| |
| /** |
| * Indicates whether to execute all targets that do not depend on failed targets |
| * |
| * @since Ant 1.6.0 |
| */ |
| private boolean keepGoing = false; |
| |
| /** |
| * Indicates whether this build is to support interactive input |
| * |
| * @since Ant 1.6.0 |
| */ |
| private boolean allowInput = true; |
| |
| private String fEarlyErrorMessage = null; |
| |
| private boolean unknownTargetsFound = false; |
| |
| /** |
| * Adds a build listener. |
| * |
| * @param classNames |
| * the fully qualified names of the build listeners to be added |
| */ |
| public void addBuildListeners(List<String> classNames) { |
| if (buildListeners == null) { |
| buildListeners = new ArrayList<>(classNames.size()); |
| } |
| buildListeners.addAll(classNames); |
| } |
| |
| protected void addBuildListener(String clazz) { |
| if (buildListeners == null) { |
| buildListeners = new ArrayList<>(); |
| } |
| buildListeners.add(clazz); |
| } |
| |
| /** |
| * Adds a build logger. There can be only one build logger. |
| * |
| * @param className |
| * The fully qualified name of the build logger to add |
| */ |
| public void addBuildLogger(String className) { |
| loggerClassname = className; |
| } |
| |
| /** |
| * Adds user properties to the current collection of user properties. |
| * |
| * @param properties |
| * The user properties to be added |
| */ |
| public void addUserProperties(Map<String, String> properties) { |
| if (userProperties == null) { |
| userProperties = new HashMap<>(properties); |
| } else { |
| userProperties.putAll(properties); |
| } |
| noExplicitUserProperties = false; |
| } |
| |
| /** |
| * Adds user property files. |
| * |
| * @param additionalPropertyFiles |
| * The property files to add |
| * @since 2.1 |
| */ |
| public void addPropertyFiles(String[] additionalPropertyFiles) { |
| propertyFiles.addAll(Arrays.asList(additionalPropertyFiles)); |
| } |
| |
| /** |
| * Tries to add the build listeners to the backing {@link Project} |
| * |
| * @param project |
| * the project to add the listeners to |
| * @param log |
| * if we should be logging {@link ClassCastException}s here or not. |
| */ |
| protected void addBuildListeners(Project project, boolean log) { |
| String className = null; |
| try { |
| BuildLogger logger = createLogger(); |
| if (logger != null) { |
| project.addBuildListener(logger); |
| } |
| if (buildListeners != null) { |
| for (Iterator<String> iterator = buildListeners.iterator(); iterator.hasNext();) { |
| className = iterator.next(); |
| Class<?> listener = Class.forName(className); |
| project.addBuildListener((BuildListener) listener.getConstructor().newInstance()); |
| } |
| } |
| } |
| catch (ClassCastException e) { |
| String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_not_an_instance_of_apache_ant_BuildListener, new Object[] { |
| className }); |
| if (log) { |
| logMessage(null, message, Project.MSG_ERR); |
| } |
| throw new BuildException(message, e); |
| } |
| catch (BuildException e) { |
| throw e; |
| } |
| catch (Exception e) { |
| throw new BuildException(e); |
| } |
| } |
| |
| private void setProperties(Project project, boolean substituteVariables) { |
| setBuiltInProperties(project); |
| if (userProperties != null) { |
| for (Entry<String, String> entry : userProperties.entrySet()) { |
| String value = entry.getValue(); |
| if (substituteVariables && value != null) { |
| try { |
| value = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(value); |
| } |
| catch (CoreException e) { |
| // do nothing |
| } |
| } |
| if (value != null) |
| project.setUserProperty(entry.getKey(), value); |
| } |
| // may have properties set (always have the Ant process ID) |
| // using the Arguments and not the Properties page |
| // if set using the arguments, still include the global properties |
| if (noExplicitUserProperties) { |
| setGlobalProperties(project, substituteVariables); |
| } |
| } else { |
| setGlobalProperties(project, substituteVariables); |
| } |
| } |
| |
| /** |
| * Sets the default <code>ant.file</code> and <code>ant.version</code> properties in the given {@link Project} |
| * |
| * @param project |
| */ |
| protected void setBuiltInProperties(Project project) { |
| // note also see processAntHome for system properties that are set |
| project.setUserProperty("ant.file", getBuildFileLocation()); //$NON-NLS-1$ |
| project.setUserProperty("ant.version", Main.getAntVersion()); //$NON-NLS-1$ |
| } |
| |
| private void setGlobalProperties(Project project, boolean substituteVariables) { |
| AntCorePreferences prefs = AntCorePlugin.getPlugin().getPreferences(); |
| List<Property> properties = prefs.getProperties(); |
| if (properties != null) { |
| for (Property property : properties) { |
| String value = property.getValue(substituteVariables); |
| if (value != null) { |
| project.setUserProperty(property.getName(), value); |
| } |
| } |
| } |
| } |
| |
| private void setTasks(Project project) { |
| List<Task> tasks = AntCorePlugin.getPlugin().getPreferences().getTasks(); |
| for (Task task : tasks) { |
| if (isVersionCompatible("1.6")) { //$NON-NLS-1$ |
| AntTypeDefinition def = new AntTypeDefinition(); |
| String name = ProjectHelper.genComponentName(task.getURI(), task.getTaskName()); |
| def.setName(name); |
| def.setClassName(task.getClassName()); |
| def.setClassLoader(this.getClass().getClassLoader()); |
| def.setAdaptToClass(org.apache.tools.ant.Task.class); |
| def.setAdapterClass(TaskAdapter.class); |
| ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def); |
| } else { |
| try { |
| Class<?> taskClass = Class.forName(task.getClassName()); |
| if (isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| try { |
| project.checkTaskClass(taskClass); |
| } |
| catch (BuildException e) { |
| IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, MessageFormat.format(InternalAntMessages.InternalAntRunner_Error_setting_Ant_task, new Object[] { |
| task.getTaskName() }), e); |
| AntCorePlugin.getPlugin().getLog().log(status); |
| continue; |
| } |
| } |
| project.addTaskDefinition(task.getTaskName(), taskClass); |
| } |
| catch (ClassNotFoundException e) { |
| IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, MessageFormat.format(InternalAntMessages.InternalAntRunner_Class_not_found_for_task, new Object[] { |
| task.getClassName(), task.getTaskName() }), e); |
| AntCorePlugin.getPlugin().getLog().log(status); |
| } |
| } |
| } |
| } |
| |
| private void setTypes(Project project) { |
| for (Type type : AntCorePlugin.getPlugin().getPreferences().getTypes()) { |
| if (isVersionCompatible("1.6")) { //$NON-NLS-1$ |
| AntTypeDefinition def = new AntTypeDefinition(); |
| String name = ProjectHelper.genComponentName(type.getURI(), type.getTypeName()); |
| def.setName(name); |
| def.setClassName(type.getClassName()); |
| def.setClassLoader(this.getClass().getClassLoader()); |
| ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def); |
| } else { |
| try { |
| Class<?> typeClass = Class.forName(type.getClassName()); |
| project.addDataTypeDefinition(type.getTypeName(), typeClass); |
| } |
| catch (ClassNotFoundException e) { |
| IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_RUNNING_BUILD, MessageFormat.format(InternalAntMessages.InternalAntRunner_Class_not_found_for_type, new Object[] { |
| type.getClassName(), type.getTypeName() }), e); |
| AntCorePlugin.getPlugin().getLog().log(status); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Parses the build file and adds necessary information into the given project. |
| * |
| * @param project |
| * The project to configure |
| */ |
| protected void parseBuildFile(Project project) { |
| File buildFile = new File(getBuildFileLocation()); |
| if (!buildFile.exists()) { |
| throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Buildfile_does_not_exist, new Object[] { |
| buildFile.getAbsolutePath() })); |
| } |
| if (!buildFile.isFile()) { |
| throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Buildfile_is_not_a_file, new Object[] { |
| buildFile.getAbsolutePath() })); |
| } |
| |
| if (!isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| parseBuildFile(project, buildFile); |
| } else { |
| ProjectHelper helper = ProjectHelper.getProjectHelper(); |
| project.addReference("ant.projectHelper", helper); //$NON-NLS-1$ |
| helper.parse(project, buildFile); |
| } |
| } |
| |
| /** |
| * @deprecated support for Ant older than 1.5 |
| */ |
| @Deprecated |
| private void parseBuildFile(Project project, File buildFile) { |
| ProjectHelper.configureProject(project, buildFile); |
| } |
| |
| /** |
| * Gets all the target information from the build script. Returns a list of lists. Each item in the enclosing list represents a target, where the |
| * first element is the name, the second element is the description, the third element is the project name, and the last elements is an array of |
| * dependencies. |
| * |
| * @return a list of {@link TargetInfo} objects |
| */ |
| public List<TargetInfo> getTargets() { |
| try { |
| setJavaClassPath(); |
| Project antProject = getProject(); |
| processAntHome(false); |
| antProject.init(); |
| setTypes(antProject); |
| boolean exceptionState = processProperties(AntCoreUtil.getArrayList(extraArguments)); |
| if (fEarlyErrorMessage != null) { |
| if (exceptionState) { |
| throw new BuildException(fEarlyErrorMessage); |
| } |
| } |
| |
| setProperties(antProject, false); |
| if (isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| new InputHandlerSetter().setInputHandler(antProject, "org.eclipse.ant.internal.core.ant.NullInputHandler"); //$NON-NLS-1$ |
| } |
| parseBuildFile(antProject); |
| defaultTarget = antProject.getDefaultTarget(); |
| Hashtable<String, Target> projectTargets = antProject.getTargets(); |
| ArrayList<TargetInfo> infos = new ArrayList<>(); |
| ProjectInfo pinfo = new ProjectInfo(antProject.getName(), antProject.getDescription()); |
| boolean defaultFound = false; |
| for (Target target : projectTargets.values()) { |
| String name = target.getName(); |
| if (name.length() == 0) { |
| // "no name" implicit target of Ant 1.6 |
| continue; |
| } |
| if (target.getName().equals(defaultTarget)) { |
| defaultFound = true; |
| } |
| ArrayList<String> dependencies = new ArrayList<>(); |
| Enumeration<String> enumeration = target.getDependencies(); |
| while (enumeration.hasMoreElements()) { |
| dependencies.add(enumeration.nextElement()); |
| } |
| String[] dependencyArray = new String[dependencies.size()]; |
| dependencies.toArray(dependencyArray); |
| TargetInfo info = new TargetInfo(pinfo, name, target.getDescription(), dependencyArray, defaultFound); |
| infos.add(info); |
| } |
| if (!defaultFound) { |
| // default target must exist |
| throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Default_target_does_not_exist, new Object[] { "'", //$NON-NLS-1$ |
| defaultTarget, "'" })); //$NON-NLS-1$ |
| } |
| return infos; |
| } |
| finally { |
| processAntHome(true); |
| } |
| } |
| |
| /** |
| * Returns a list of target names in the build script. |
| * |
| * @return a list of target names |
| */ |
| private List<String> getTargetNames() { |
| try { |
| setJavaClassPath(); |
| Project antProject; |
| |
| antProject = getProject(); |
| processAntHome(false); |
| antProject.init(); |
| setTypes(antProject); |
| processProperties(AntCoreUtil.getArrayList(extraArguments)); |
| |
| setProperties(antProject, false); |
| if (isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| new InputHandlerSetter().setInputHandler(antProject, "org.eclipse.ant.internal.core.ant.NullInputHandler"); //$NON-NLS-1$ |
| } |
| parseBuildFile(antProject); |
| Hashtable<String, Target> projectTargets = antProject.getTargets(); |
| ArrayList<String> names = new ArrayList<>(); |
| for (Target target : projectTargets.values()) { |
| String name = target.getName(); |
| if (name.length() == 0) { |
| // "no name" implicit target of Ant 1.6 |
| continue; |
| } |
| names.add(name); |
| } |
| return names; |
| } |
| finally { |
| processAntHome(true); |
| } |
| } |
| |
| private Project getProject() { |
| Project antProject; |
| if (isVersionCompatible("1.6")) { //$NON-NLS-1$ |
| // in Ant version 1.6 or greater all tasks can exist outside the scope of a target |
| if (isVersionCompatible("1.6.3")) { //$NON-NLS-1$ |
| antProject = new InternalProject2(); |
| } else { |
| antProject = new Project(); |
| } |
| } else { |
| antProject = new InternalProject(); |
| } |
| return antProject; |
| } |
| |
| /** |
| * Returns the default target name that was last computed or <code>null</code> if no default target has been computed. |
| * |
| * @return the default target name |
| */ |
| public String getDefaultTarget() { |
| return defaultTarget; |
| } |
| |
| /** |
| * Runs the build script. |
| */ |
| public void run() { |
| run(AntCoreUtil.getArrayList(extraArguments)); |
| } |
| |
| private void printArguments(Project project) { |
| if ((messageOutputLevel != Project.MSG_DEBUG) && (messageOutputLevel != Project.MSG_VERBOSE)) { |
| return; |
| } |
| StringBuilder sb = new StringBuilder(); |
| for (String extraArgument : extraArguments) { |
| sb.append(extraArgument); |
| sb.append(' '); |
| } |
| project.log(MessageFormat.format(InternalAntMessages.InternalAntRunner_Arguments, new Object[] { sb.toString().trim() })); |
| } |
| |
| private void createMonitorBuildListener(Project project) { |
| if (monitor == null) { |
| return; |
| } |
| Vector<String> chosenTargets = targets; |
| if (chosenTargets == null || chosenTargets.isEmpty()) { |
| chosenTargets = new Vector<>(1); |
| String defltTarget = project.getDefaultTarget(); |
| if (defltTarget != null) { |
| chosenTargets.add(defltTarget); |
| } |
| } |
| project.addBuildListener(new ProgressBuildListener(project, chosenTargets, monitor)); |
| } |
| |
| /** |
| * Invokes the building of a project object and executes a build using either a given target or the default target. This method is called if |
| * running in headless mode. |
| * |
| * @see org.eclipse.ant.core.AntRunner#run(Object) |
| * @param argArray |
| * the command line arguments |
| * @exception Exception |
| * execution exceptions |
| */ |
| public void run(Object argArray) throws Exception { |
| run(AntCoreUtil.getArrayList((String[]) argArray)); |
| } |
| |
| /** |
| * Attempts to run the given list of command line arguments. Note that the list passed to this method must support {@link List#remove(Object)}. |
| * <br> |
| * <br> |
| * This method directly processes the following arguments: |
| * <ul> |
| * <li><b>-projecthelp</b>, <b>-p</b> - print project help information</li> |
| * </ul> |
| * |
| * @param argList |
| * the raw list of command line arguments |
| */ |
| private void run(List<String> argList) { |
| setCurrentProject(new Project()); |
| if (isVersionCompatible("1.6.3")) { //$NON-NLS-1$ |
| new ExecutorSetter().setExecutor(currentProject); |
| } |
| Throwable error = null; |
| PrintStream originalErr = System.err; |
| PrintStream originalOut = System.out; |
| InputStream originalIn = System.in; |
| |
| SecurityManager originalSM = System.getSecurityManager(); |
| setJavaClassPath(); |
| executed = true; |
| processAntHome(false); |
| try { |
| if (argList != null && (argList.remove("-projecthelp") || argList.remove("-p"))) { //$NON-NLS-1$ //$NON-NLS-2$ |
| projectHelp = true; |
| } |
| getCurrentProject().init(); |
| if (argList != null) { |
| executed = preprocessCommandLine(argList); |
| if (!executed) { |
| return; |
| } |
| } |
| |
| boolean exceptionState = processProperties(argList); |
| |
| addBuildListeners(getCurrentProject(), true); |
| |
| addInputHandler(getCurrentProject()); |
| |
| remapSystemIn(); |
| System.setOut(new PrintStream(new DemuxOutputStream(getCurrentProject(), false))); |
| System.setErr(new PrintStream(new DemuxOutputStream(getCurrentProject(), true))); |
| |
| if (!projectHelp) { |
| fireBuildStarted(getCurrentProject()); |
| } |
| |
| if (fEarlyErrorMessage != null) { |
| // an error occurred processing the properties |
| // build started has fired and we have |
| // listeners/loggers to report the error |
| logMessage(getCurrentProject(), fEarlyErrorMessage, Project.MSG_ERR); |
| if (exceptionState) { |
| throw new BuildException(fEarlyErrorMessage); |
| } |
| } |
| |
| // properties can only be set after buildStarted as some listeners/loggers |
| // depend on this (e.g. XMLLogger) |
| setProperties(getCurrentProject(), true); |
| |
| if (argList != null && !argList.isEmpty()) { |
| try { |
| executed = processCommandLine(argList); |
| } |
| catch (BuildException e) { |
| executed = false; |
| throw e; |
| } |
| } |
| if (!executed) { |
| return; |
| } |
| |
| // needs to occur after processCommandLine(List) |
| if (allowInput && (inputHandlerClassname != null && inputHandlerClassname.length() > 0)) { |
| if (isVersionCompatible("1.6")) { //$NON-NLS-1$ |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=182577 |
| // getCurrentProject().setDefaultInputStream(originalIn); |
| System.getProperties().remove("eclipse.ant.noInput"); //$NON-NLS-1$ |
| } |
| } else { |
| // set the system property that any input handler |
| // can check to see if handling input is allowed |
| System.setProperty("eclipse.ant.noInput", "true"); //$NON-NLS-1$//$NON-NLS-2$ |
| if (isVersionCompatible("1.5") && (inputHandlerClassname == null || inputHandlerClassname.length() == 0)) { //$NON-NLS-1$ |
| InputHandlerSetter setter = new InputHandlerSetter(); |
| setter.setInputHandler(getCurrentProject(), "org.eclipse.ant.internal.core.ant.FailInputHandler"); //$NON-NLS-1$ |
| } |
| } |
| |
| if (!projectHelp) { |
| logMessage(currentProject, MessageFormat.format(InternalAntMessages.InternalAntRunner_Build_file, new Object[] { |
| getBuildFileLocation() }), Project.MSG_INFO); |
| |
| setTasks(getCurrentProject()); |
| setTypes(getCurrentProject()); |
| |
| if (isVersionCompatible("1.6")) { //$NON-NLS-1$ |
| getCurrentProject().setKeepGoingMode(keepGoing); |
| } |
| parseBuildFile(getCurrentProject()); |
| } |
| |
| createMonitorBuildListener(getCurrentProject()); |
| |
| if (projectHelp) { |
| if (isVersionCompatible("1.7")) { //$NON-NLS-1$ |
| new EclipseMainHelper().runProjectHelp(getBuildFileLocation(), getCurrentProject()); |
| return; |
| } |
| logMessage(currentProject, InternalAntMessages.InternalAntRunner_ant_1_7_needed_for_help_info, Project.MSG_ERR); |
| executed = false; |
| return; |
| } |
| |
| if (extraArguments != null) { |
| printArguments(getCurrentProject()); |
| } |
| try { |
| System.setSecurityManager(new AntSecurityManager(originalSM, Thread.currentThread())); |
| } |
| catch (UnsupportedOperationException ex) { |
| AntCorePlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, 0, InternalAntMessages.InternalAntRunner_SecurityManagerError, null)); |
| } |
| if (targets == null) { |
| targets = new Vector<>(1); |
| } |
| String dtarget = currentProject.getDefaultTarget(); |
| if (targets.isEmpty() && dtarget != null) { |
| targets.add(dtarget); |
| } |
| if (!isVersionCompatible("1.6.3")) { //$NON-NLS-1$ |
| getCurrentProject().addReference(IAntCoreConstants.TARGET_VECTOR_NAME, targets); |
| } |
| getCurrentProject().executeTargets(targets); |
| } |
| catch (OperationCanceledException e) { |
| executed = false; |
| logMessage(currentProject, e.getMessage(), Project.MSG_INFO); |
| throw e; |
| } |
| catch (AntSecurityException e) { |
| // expected |
| } |
| catch (RuntimeException e) { |
| error = e; |
| throw e; |
| } |
| catch (Error e) { |
| error = e; |
| throw e; |
| } |
| finally { |
| System.setErr(originalErr); |
| System.setOut(originalOut); |
| System.setIn(originalIn); |
| if (System.getSecurityManager() instanceof AntSecurityManager) { |
| System.setSecurityManager(originalSM); |
| } |
| |
| if (!projectHelp) { |
| if (AntCorePlugin.getPlugin().getBundle().getState() != Bundle.ACTIVE) { |
| return; |
| } |
| fireBuildFinished(getCurrentProject(), error); |
| } |
| |
| // close any user specified build log |
| if (err != originalErr) { |
| err.close(); |
| } |
| if (out != originalOut) { |
| out.close(); |
| } |
| |
| processAntHome(true); |
| if (!allowInput) { |
| System.getProperties().remove("eclipse.ant.noInput"); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| /** |
| * Re-maps {@link System.in} to the Ant input stream setter |
| */ |
| protected void remapSystemIn() { |
| if (!isVersionCompatible("1.6")) { //$NON-NLS-1$ |
| return; |
| } |
| DemuxInputStreamSetter setter = new DemuxInputStreamSetter(); |
| setter.remapSystemIn(currentProject); |
| } |
| |
| private void processAntHome(boolean finished) { |
| AntCorePreferences prefs = AntCorePlugin.getPlugin().getPreferences(); |
| String antHome = prefs.getAntHome(); |
| if (buildAntHome != null && !finished) { |
| antHome = buildAntHome; |
| } |
| if (antHome == null || antHome.length() == 0) { |
| System.getProperties().remove("ant.home"); //$NON-NLS-1$ |
| System.getProperties().remove("ant.library.dir"); //$NON-NLS-1$ |
| } else { |
| System.setProperty("ant.home", antHome); //$NON-NLS-1$ |
| File antLibDir = new File(antHome, "lib"); //$NON-NLS-1$ |
| System.setProperty("ant.library.dir", antLibDir.getAbsolutePath()); //$NON-NLS-1$ |
| } |
| } |
| |
| public void setAntHome(String antHome) { |
| this.buildAntHome = antHome; |
| } |
| |
| /** |
| * Creates and returns the default build logger for logging build events to the ant log. |
| * |
| * @return the default build logger for logging build events to the ant log can return <code>null</code> if no logging is to occur |
| */ |
| protected BuildLogger createLogger() { |
| if (loggerClassname == null) { |
| buildLogger = new DefaultLogger(); |
| } else if (!IAntCoreConstants.EMPTY_STRING.equals(loggerClassname)) { |
| try { |
| buildLogger = (BuildLogger) (Class.forName(loggerClassname).getConstructor().newInstance()); |
| } |
| catch (ClassCastException e) { |
| String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_not_an_instance_of_apache_ant_BuildLogger, new Object[] { |
| loggerClassname }); |
| logMessage(null, message, Project.MSG_ERR); |
| throw new BuildException(message, e); |
| } |
| catch (Exception e) { |
| String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_Unable_to_instantiate_logger, new Object[] { |
| loggerClassname }); |
| logMessage(null, message, Project.MSG_ERR); |
| throw new BuildException(message, e); |
| } |
| } |
| |
| if (buildLogger != null) { |
| buildLogger.setMessageOutputLevel(messageOutputLevel); |
| buildLogger.setOutputPrintStream(out); |
| buildLogger.setErrorPrintStream(err); |
| buildLogger.setEmacsMode(emacsMode); |
| if (buildLogger instanceof AbstractEclipseBuildLogger) { |
| ((AbstractEclipseBuildLogger) buildLogger).configure(userProperties); |
| } |
| } |
| |
| return buildLogger; |
| } |
| |
| /** |
| * Project.fireBuildStarted is protected in Ant earlier than 1.5.*. Provides backwards compatibility with old Ant installs. |
| */ |
| protected void fireBuildStarted(Project project) { |
| if (!isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| BuildEvent event = new BuildEvent(project); |
| for (BuildListener listener : project.getBuildListeners()) { |
| listener.buildStarted(event); |
| } |
| } else { |
| project.fireBuildStarted(); |
| } |
| } |
| |
| /** |
| * Sends the the event to the backing project that the build has completed |
| * |
| * @param project |
| * @param error |
| */ |
| protected void fireBuildFinished(Project project, Throwable error) { |
| if (usingXmlLogger()) { |
| // generate the log file in the correct location |
| String fileName = project.getProperty("XmlLogger.file"); //$NON-NLS-1$ |
| if (fileName == null) { |
| fileName = "log.xml"; //$NON-NLS-1$ |
| } |
| String realPath = new Path(getBuildFileLocation()).toFile().getAbsolutePath(); |
| IPath path = new Path(realPath); |
| path = path.removeLastSegments(1); |
| path = path.addTrailingSeparator(); |
| path = path.append(fileName); |
| |
| project.setProperty("XmlLogger.file", path.toOSString()); //$NON-NLS-1$ |
| } |
| if (error == null && executed) { |
| logMessage(project, InternalAntMessages.InternalAntRunner_BUILD_SUCCESSFUL_1, messageOutputLevel); |
| } |
| if (!isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| BuildEvent event = new BuildEvent(project); |
| event.setException(error); |
| for (BuildListener listener : project.getBuildListeners()) { |
| listener.buildFinished(event); |
| } |
| } else { |
| project.fireBuildFinished(error); |
| } |
| } |
| |
| private boolean usingXmlLogger() { |
| if (buildLogger instanceof XmlLogger) { |
| return true; |
| } |
| if (buildListeners != null) { |
| for (BuildListener listener : currentProject.getBuildListeners()) { |
| if (listener instanceof XmlLogger) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| protected void logMessage(Project project, String message, int priority) { |
| if (project != null) { |
| project.log(message, priority); |
| } else { |
| if (buildListeners != null) { |
| Project p = new Project(); |
| addBuildListeners(p, false); |
| p.log(message, priority); |
| } else { |
| IStatus s = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.INTERNAL_ERROR, message, null); |
| AntCorePlugin.getPlugin().getLog().log(s); |
| } |
| } |
| } |
| |
| /** |
| * Sets the buildFileLocation. |
| * |
| * @param buildFileLocation |
| * the file system location of the build file |
| */ |
| public void setBuildFileLocation(String buildFileLocation) { |
| this.buildFileLocation = buildFileLocation; |
| if (currentProject != null) { |
| currentProject.setUserProperty("ant.file", buildFileLocation); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Sets the input handler class name. |
| * |
| * @param inputHandlerClassname |
| * the name of the class to use for the input handler |
| */ |
| public void setInputHandler(String inputHandlerClassname) { |
| this.inputHandlerClassname = inputHandlerClassname; |
| } |
| |
| /** |
| * Returns the class name of the input handler to use |
| * |
| * @return the input handler class name |
| */ |
| protected String getInputHandler() { |
| return this.inputHandlerClassname; |
| } |
| |
| protected String getBuildLogger() { |
| return this.loggerClassname; |
| } |
| |
| /** |
| * Returns the location of the buildfile. If one has not been supplied the default location of <code>build.xml</code> will be returned |
| * |
| * @return the absolute location of the build file |
| */ |
| protected String getBuildFileLocation() { |
| if (buildFileLocation == null) { |
| buildFileLocation = new File("build.xml").getAbsolutePath(); //$NON-NLS-1$ |
| } |
| return buildFileLocation; |
| } |
| |
| /** |
| * Sets the message output level. Use -1 for none. |
| * |
| * @param level |
| * The message output level |
| */ |
| public void setMessageOutputLevel(int level) { |
| messageOutputLevel = level; |
| if (buildLogger != null) { |
| buildLogger.setMessageOutputLevel(level); |
| } |
| } |
| |
| /** |
| * Sets the extra user arguments |
| * |
| * @param args |
| * The extra user arguments |
| */ |
| public void setArguments(String[] args) { |
| extraArguments = args; |
| } |
| |
| /** |
| * Sets the execution targets. |
| * |
| * @param executionTargets |
| * The targets to execute for the build |
| */ |
| public void setExecutionTargets(String[] executionTargets) { |
| targets = new Vector<>(executionTargets.length); |
| for (String executionTarget : executionTargets) { |
| targets.add(executionTarget); |
| } |
| } |
| |
| /* |
| * Returns a String representation of the Ant version number as specified in the version.txt file. |
| */ |
| protected String getAntVersionNumber() throws BuildException { |
| if (antVersionNumber == null) { |
| try (InputStream in = Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt")) { //$NON-NLS-1$ |
| Properties props = new Properties(); |
| props.load(in); |
| String versionNumber = props.getProperty("VERSION"); //$NON-NLS-1$ |
| antVersionNumber = versionNumber; |
| } |
| catch (IOException ioe) { |
| throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Could_not_load_the_version_information, new Object[] { |
| ioe.getMessage() }), ioe); |
| } |
| catch (NullPointerException npe) { |
| throw new BuildException(MessageFormat.format(InternalAntMessages.InternalAntRunner_Could_not_load_the_version_information, new Object[] { |
| npe.getMessage() }), npe); |
| } |
| } |
| return antVersionNumber; |
| } |
| |
| /* |
| * Returns whether the given version is compatible with the current Ant version. A version is compatible if it is less than or equal to the |
| * current version. |
| */ |
| protected boolean isVersionCompatible(String comparison) { |
| String version = getAntVersionNumber(); |
| Version osgiVersion = new Version(version); |
| Version osgiComparison = new Version(comparison); |
| return osgiVersion.compareTo(osgiComparison) >= 0; |
| } |
| |
| /** |
| * Pre-processes the raw command line to set up input handling and logging. <br> |
| * <br> |
| * This method checks for the following command line arguments: |
| * <ul> |
| * <li><b>-inputhandler</b> <em><class></em> - the class which will handle input requests</li> |
| * <li><b>-logger</b> <em><classname></em> - the class which is to perform logging</li> |
| * <li><b>-listener</b> <em><classname></em> - add an instance of class as a project listener</li> |
| * </ul> |
| * |
| * @param commands |
| * the raw command line arguments passed in from the application |
| * @return <code>true</code> if it is OK to run with the given list of arguments <code>false</code> otherwise |
| */ |
| protected boolean preprocessCommandLine(List<String> commands) { |
| String arg = AntCoreUtil.getArgument(commands, "-listener"); //$NON-NLS-1$ |
| while (arg != null) { |
| if (arg.length() == 0) { |
| throw new BuildException(InternalAntMessages.InternalAntRunner_specify_a_classname_using_the_listener_argument); |
| } |
| if (buildListeners == null) { |
| buildListeners = new ArrayList<>(1); |
| } |
| buildListeners.add(arg); |
| arg = AntCoreUtil.getArgument(commands, "-listener"); //$NON-NLS-1$ |
| } |
| |
| arg = AntCoreUtil.getArgument(commands, "-logger"); //$NON-NLS-1$ |
| if (arg != null) { |
| if (arg.length() == 0) { |
| throw new BuildException(InternalAntMessages.InternalAntRunner_specify_a_classname_using_the_logger_argument); |
| } |
| loggerClassname = arg; |
| } |
| arg = AntCoreUtil.getArgument(commands, "-logger"); //$NON-NLS-1$ |
| if (arg != null) { |
| throw new BuildException(InternalAntMessages.InternalAntRunner_Only_one_logger_class_may_be_specified); |
| } |
| |
| arg = AntCoreUtil.getArgument(commands, "-inputhandler"); //$NON-NLS-1$ |
| if (arg != null) { |
| if (!isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| throw new BuildException(InternalAntMessages.InternalAntRunner_Specifying_an_InputHandler_is_an_Ant_1_5_feature); |
| } |
| if (arg.length() == 0) { |
| throw new BuildException(InternalAntMessages.InternalAntRunner_specify_a_classname_the_inputhandler_argument); |
| } |
| inputHandlerClassname = arg; |
| } |
| arg = AntCoreUtil.getArgument(commands, "-inputhandler"); //$NON-NLS-1$ |
| if (arg != null) { |
| throw new BuildException(InternalAntMessages.InternalAntRunner_Only_one_input_handler_class_may_be_specified); |
| } |
| return true; |
| } |
| |
| /** |
| * Process the command line arguments. <br> |
| * <br> |
| * The listing of supported Ant command line arguments is: |
| * <ul> |
| * <li><b>-buildfile</b>, <b>-file</b>, <b>-f</b> <em><file></em> - use given buildfile</li> |
| * <li><b>-debug</b>, <b>-d</b> - print debugging information</li> |
| * <li><b>-diagnostics</b> - print information that might be helpful diagnose or report problems</li> |
| * <li><b>-emacs</b>, <b>-e</b> - produce logging information without adornments</li> |
| * <li><b>-find</b>, <b>-s</b> <em><file></em> - search for buildfile towards the root of the filesystem and use it</li> |
| * <li><b>-help</b>, <b>-h</b> - print this message</li> |
| * <li><b>-keep-going</b>, <b>-k</b> - execute all targets that do not depend on failed target(s)</li> |
| * <li><b>-lib</b> <em><path></em> - specifies a path to search for jars and classes</li> |
| * <li><b>-logfile</b>, <b>-l</b> <em><file></em> - use given file for logging</li> |
| * <li><b>-noinput</b> - do not allow interactive input</li> |
| * <li><b>-quiet</b>, <b>-q</b> - be extra quiet</li> |
| * <li><b>-verbose</b>, <b>-v</b> - be extra verbose</li> |
| * <li><b>-version</b> - print the version information and exit</li> |
| * </ul> |
| * The list of other Ant command line arguments that we currently do not support: |
| * <ul> |
| * <li><b>-nice</b> <em><number></em> - A niceness value for the main thread - 1 (lowest) to 10 (highest); 5 is the default</li> |
| * <li><b>-nouserlib</b> - Run ant without using the jar files from ${user.home}/.ant/lib</li> |
| * <li><b>-noclasspath</b> - Run ant without using CLASSPATH</li> |
| * <li><b>-autoproxy</b> - Java 1.5+ : use the OS proxies</li> |
| * <li><b>-main</b> <em><class></em> - override Ant's normal entry point</li> |
| * </ul> |
| * |
| * @param commands |
| * the raw command line arguments passed in from the application |
| * @return <code>true</code> if it is OK to run with the given list of arguments <code>false</code> otherwise |
| */ |
| private boolean processCommandLine(List<String> commands) { |
| if (commands.remove("-help") || commands.remove("-h")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| if (isVersionCompatible("1.7")) { //$NON-NLS-1$ |
| new EclipseMainHelper().runUsage(getBuildFileLocation(), currentProject); |
| } else { |
| logMessage(currentProject, InternalAntMessages.InternalAntRunner_ant_1_7_needed_for_help_message, Project.MSG_WARN); |
| } |
| return false; |
| } |
| |
| if (commands.remove("-version")) { //$NON-NLS-1$ |
| printVersion(); |
| return false; |
| } |
| |
| if (commands.remove("-verbose") || commands.remove("-v")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| printVersion(); |
| setMessageOutputLevel(Project.MSG_VERBOSE); |
| } |
| |
| if (commands.remove("-debug") || commands.remove("-d")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| printVersion(); |
| setMessageOutputLevel(Project.MSG_DEBUG); |
| } |
| |
| if (commands.remove("-quiet") || commands.remove("-q")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| setMessageOutputLevel(Project.MSG_WARN); |
| } |
| |
| if (commands.remove("-emacs") || commands.remove("-e")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| emacsMode = true; |
| if (buildLogger != null) { |
| buildLogger.setEmacsMode(true); |
| } |
| } |
| |
| if (commands.remove("-diagnostics")) { //$NON-NLS-1$ |
| if (!isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| throw new BuildException(InternalAntMessages.InternalAntRunner_The_diagnositics_options_is_an_Ant_1_5_feature); |
| } |
| try { |
| Diagnostics.doReport(System.out); |
| } |
| catch (NullPointerException e) { |
| logMessage(currentProject, InternalAntMessages.InternalAntRunner_anthome_must_be_set_to_use_ant_diagnostics, Project.MSG_ERR); |
| } |
| return false; |
| } |
| |
| String arg = AntCoreUtil.getArgument(commands, "-logfile"); //$NON-NLS-1$ |
| if (arg == null) { |
| arg = AntCoreUtil.getArgument(commands, "-l"); //$NON-NLS-1$ |
| } |
| if (arg != null) { |
| if (arg.length() == 0) { |
| String message = InternalAntMessages.InternalAntRunner_specify_a_log_file_using_the_log_argument; |
| logMessage(currentProject, message, Project.MSG_ERR); |
| throw new BuildException(message); |
| } |
| try { |
| createLogFile(arg); |
| } |
| catch (IOException e) { |
| // just log message and ignore exception |
| logMessage(currentProject, MessageFormat.format(InternalAntMessages.InternalAntRunner_Could_not_write_to_log_file, new Object[] { |
| arg }), Project.MSG_ERR); |
| return false; |
| } |
| |
| } |
| arg = AntCoreUtil.getArgument(commands, "-buildfile"); //$NON-NLS-1$ |
| if (arg == null) { |
| arg = AntCoreUtil.getArgument(commands, "-file"); //$NON-NLS-1$ |
| if (arg == null) { |
| arg = AntCoreUtil.getArgument(commands, "-f"); //$NON-NLS-1$ |
| } |
| } |
| if (arg != null) { |
| if (arg.length() == 0) { |
| String message = InternalAntMessages.InternalAntRunner_specify_a_buildfile_using_the_buildfile_argument; |
| logMessage(currentProject, message, Project.MSG_ERR); |
| throw new BuildException(message); |
| } |
| setBuildFileLocation(arg); |
| } |
| if (isVersionCompatible("1.6")) { //$NON-NLS-1$ |
| if (commands.remove("-k") || commands.remove("-keep-going")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| keepGoing = true; |
| } |
| if (commands.remove("-noinput")) { //$NON-NLS-1$ |
| allowInput = false; |
| } |
| arg = AntCoreUtil.getArgument(commands, "-lib"); //$NON-NLS-1$ |
| if (arg != null) { |
| logMessage(currentProject, InternalAntMessages.InternalAntRunner_157, Project.MSG_ERR); |
| return false; |
| } |
| } |
| |
| arg = AntCoreUtil.getArgument(commands, "-find"); //$NON-NLS-1$ |
| if (arg == null) { |
| arg = AntCoreUtil.getArgument(commands, "-s"); //$NON-NLS-1$ |
| } |
| if (arg != null) { |
| logMessage(currentProject, InternalAntMessages.InternalAntRunner_find_not_supported, Project.MSG_ERR); |
| return false; |
| } |
| |
| if (!commands.isEmpty()) { |
| processUnrecognizedCommands(commands); |
| } |
| |
| if (!commands.isEmpty()) { |
| processUnrecognizedTargets(commands); |
| } |
| |
| if (!commands.isEmpty()) { |
| processTargets(commands); |
| } |
| |
| if (unknownTargetsFound && (targets == null || targets.isEmpty())) { |
| // Some targets are specified but none of them are good. Hence quit |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=352536 |
| logMessage(currentProject, InternalAntMessages.InternalAntRunner_no_known_target, Project.MSG_ERR); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Checks for unrecognized targets on the command line and removes them. |
| * |
| * @since 3.6 |
| */ |
| private void processUnrecognizedTargets(List<String> commands) { |
| List<String> names = getTargetNames(); |
| ListIterator<String> iterator = commands.listIterator(); |
| while (iterator.hasNext()) { |
| String target = iterator.next(); |
| if (!names.contains(target)) { |
| iterator.remove(); |
| String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_unknown_target, new Object[] { target }); |
| logMessage(currentProject, message, Project.MSG_WARN); |
| unknownTargetsFound = true; |
| } |
| } |
| } |
| |
| /** |
| * Checks for unrecognized arguments on the command line. Since there is no syntactic way to distinguish between ant -foo target1 target2 ant -foo |
| * fooarg target we remove everything up to the last argument that begins with a '-'. In the latter case, above, that means that there will be an |
| * extra target, 'fooarg', left lying around. |
| */ |
| protected void processUnrecognizedCommands(List<String> commands) { |
| int p = -1; |
| |
| // find the last arg that begins with '-' |
| for (int i = commands.size() - 1; i >= 0; i--) { |
| if (commands.get(i).startsWith("-")) { //$NON-NLS-1$ |
| p = i; |
| break; |
| } |
| } |
| if (p < 0) { |
| return; |
| } |
| |
| // remove everything preceding that last '-arg' |
| String s = IAntCoreConstants.EMPTY_STRING; |
| for (int i = 0; i <= p; i++) { |
| s += " " + (commands.get(0)); //$NON-NLS-1$ |
| commands.remove(0); |
| } |
| |
| // warn of ignored commands |
| String message = MessageFormat.format(InternalAntMessages.InternalAntRunner_Unknown_argument, new Object[] { s.substring(1) }); |
| logMessage(currentProject, message, Project.MSG_WARN); |
| } |
| |
| /** |
| * Checks for targets specified at the command line. |
| */ |
| protected void processTargets(List<String> commands) { |
| if (targets == null) { |
| targets = new Vector<>(commands.size()); |
| } |
| for (String string : commands) { |
| targets.add(string); |
| } |
| } |
| |
| /** |
| * Creates the log file with the name specified by the user. If the fileName is not absolute, the file will be created in the working directory if |
| * specified or in the same directory as the location of the build file. |
| */ |
| protected void createLogFile(String fileName) throws FileNotFoundException, IOException { |
| File logFile = AntCoreUtil.getFileRelativeToBaseDir(fileName, currentProject.getUserProperty("basedir"), getBuildFileLocation()); //$NON-NLS-1$ |
| // this stream is closed in the finally block of run(list) |
| out = new PrintStream(new FileOutputStream(logFile)); |
| err = out; |
| logMessage(currentProject, MessageFormat.format(InternalAntMessages.InternalAntRunner_Using_file_as_build_log, new Object[] { |
| logFile.getCanonicalPath() }), Project.MSG_INFO); |
| if (buildLogger != null) { |
| buildLogger.setErrorPrintStream(err); |
| buildLogger.setOutputPrintStream(out); |
| } |
| } |
| |
| /** |
| * Processes the command line properties and adds the user properties. <br> |
| * <br> |
| * Any user properties that have been explicitly set are set as well. Ensures that -D properties take precedence. <br> |
| * <br> |
| * This command lie arguments used are: |
| * <ul> |
| * <li><b>-D</b> <em><property>=<value></em> - use value for given property</li> |
| * <li><b>-propertyfile</b> <em><name></em> - load all properties from file with -D properties taking precedence</li> |
| * </ul> |
| */ |
| private boolean processProperties(List<String> commands) { |
| boolean exceptionToBeThrown = false; |
| // MULTIPLE property files are allowed |
| String arg = AntCoreUtil.getArgument(commands, "-propertyfile"); //$NON-NLS-1$ |
| while (arg != null) { |
| if (!isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| fEarlyErrorMessage = InternalAntMessages.InternalAntRunner_Specifying_property_files_is_a_Ant_1_5_feature; |
| break; |
| } |
| if (arg.length() == 0) { |
| fEarlyErrorMessage = InternalAntMessages.InternalAntRunner_specify_a_property_filename_when_using_propertyfile_argument; |
| exceptionToBeThrown = true; |
| break; |
| } |
| |
| propertyFiles.add(arg); |
| arg = AntCoreUtil.getArgument(commands, "-propertyfile"); //$NON-NLS-1$ |
| } |
| |
| String[] globalPropertyFiles = AntCorePlugin.getPlugin().getPreferences().getCustomPropertyFiles(); |
| if (globalPropertyFiles.length > 0) { |
| if (!isVersionCompatible("1.5")) { //$NON-NLS-1$ |
| fEarlyErrorMessage = InternalAntMessages.InternalAntRunner_Specifying_property_files_is_a_Ant_1_5_feature; |
| } else { |
| if (propertyFiles == null) { |
| propertyFiles = new ArrayList<>(globalPropertyFiles.length); |
| } |
| propertyFiles.addAll(Arrays.asList(globalPropertyFiles)); |
| } |
| } |
| |
| if (propertyFiles != null && !propertyFiles.isEmpty()) { |
| loadPropertyFiles(); |
| } |
| |
| if (commands != null) { |
| processMinusDProperties(commands); |
| } |
| return exceptionToBeThrown; |
| } |
| |
| /** |
| * Process properties specified using <code>-D</code> |
| * |
| * @param commands |
| */ |
| protected void processMinusDProperties(List<String> commands) { |
| if (!commands.isEmpty() && userProperties == null) { |
| userProperties = new HashMap<>(); |
| } |
| AntCoreUtil.processMinusDProperties(commands, userProperties); |
| } |
| |
| /** |
| * Logs a message with the client indicating the version of <b>Ant</b> that this class fronts. |
| */ |
| protected void printVersion() { |
| logMessage(currentProject, Main.getAntVersion(), Project.MSG_INFO); |
| } |
| |
| /** |
| * Sets the build progress monitor. |
| * |
| * @param monitor |
| * The progress monitor to use |
| */ |
| public void setProgressMonitor(IProgressMonitor monitor) { |
| this.monitor = monitor; |
| } |
| |
| /** |
| * Returns the current {@link Project} context |
| * |
| * @return the current {@link Project} |
| */ |
| protected Project getCurrentProject() { |
| return currentProject; |
| } |
| |
| /** |
| * Sets the current {@link Project} context |
| * |
| * @param currentProject |
| * the new {@link Project} |
| */ |
| protected void setCurrentProject(Project currentProject) { |
| this.currentProject = currentProject; |
| } |
| |
| public String getBuildExceptionErrorMessage(Throwable t) { |
| if (t instanceof BuildException) { |
| return t.toString(); |
| } |
| return null; |
| } |
| |
| /** |
| * Load all properties from the files specified by -propertyfile. |
| */ |
| protected void loadPropertyFiles() { |
| if (userProperties == null) { |
| userProperties = new HashMap<>(); |
| } |
| try { |
| List<Properties> allProperties = AntCoreUtil.loadPropertyFiles(propertyFiles, currentProject.getUserProperty("basedir"), getBuildFileLocation()); //$NON-NLS-1$ |
| Iterator<Properties> iter = allProperties.iterator(); |
| while (iter.hasNext()) { |
| Properties props = iter.next(); |
| Enumeration<?> propertyNames = props.propertyNames(); |
| while (propertyNames.hasMoreElements()) { |
| String name = (String) propertyNames.nextElement(); |
| // most specific to global |
| // do not overwrite specific with a global property |
| if (userProperties.get(name) == null) { |
| userProperties.put(name, props.getProperty(name)); |
| } |
| } |
| } |
| } |
| catch (IOException e) { |
| fEarlyErrorMessage = MessageFormat.format(InternalAntMessages.InternalAntRunner_could_not_load_property_file, new Object[] { |
| e.getMessage() }); |
| } |
| } |
| |
| /** |
| * Creates the InputHandler and adds it to the project. |
| * |
| * @exception BuildException |
| * if a specified InputHandler implementation could not be loaded. |
| */ |
| protected void addInputHandler(Project project) { |
| if (!isVersionCompatible("1.5") || (inputHandlerClassname != null && inputHandlerClassname.length() == 0)) { //$NON-NLS-1$ |
| return; |
| } |
| InputHandlerSetter setter = new InputHandlerSetter(); |
| setter.setInputHandler(project, inputHandlerClassname); |
| } |
| |
| /* |
| * Sets the Java class path in org.apache.tools.ant.types.Path |
| */ |
| private void setJavaClassPath() { |
| URL[] antClasspath = null; |
| AntCorePreferences prefs = AntCorePlugin.getPlugin().getPreferences(); |
| if (customClasspath == null) { |
| antClasspath = prefs.getURLs(); |
| } else { |
| URL[] extraClasspath = prefs.getExtraClasspathURLs(); |
| antClasspath = new URL[customClasspath.length + extraClasspath.length]; |
| System.arraycopy(customClasspath, 0, antClasspath, 0, customClasspath.length); |
| System.arraycopy(extraClasspath, 0, antClasspath, customClasspath.length, extraClasspath.length); |
| } |
| StringBuilder buff = new StringBuilder(); |
| File file = null; |
| for (URL element : antClasspath) { |
| try { |
| file = new File(FileLocator.toFileURL(element).getPath()); |
| } |
| catch (IOException e) { |
| continue; |
| } |
| buff.append(file.getAbsolutePath()); |
| buff.append("; "); //$NON-NLS-1$ |
| } |
| |
| org.apache.tools.ant.types.Path systemClasspath = new org.apache.tools.ant.types.Path(null, buff.substring(0, buff.length() - 2)); |
| org.apache.tools.ant.types.Path.systemClasspath = systemClasspath; |
| } |
| |
| /** |
| * Sets the custom classpath to be included when setting the Java classpath for this build. |
| * |
| * @param classpath |
| * The custom classpath for this build. |
| */ |
| public void setCustomClasspath(URL[] classpath) { |
| customClasspath = classpath; |
| } |
| } |