You are viewing a plain text version of this content. The canonical link for it is here.
Posted to easyant-commits@incubator.apache.org by hi...@apache.org on 2011/02/17 17:01:56 UTC

svn commit: r1071697 [17/42] - in /incubator/easyant: buildtypes/ buildtypes/trunk/ buildtypes/trunk/build-osgi-bundle-java/ buildtypes/trunk/build-osgi-bundle-java/src/ buildtypes/trunk/build-osgi-bundle-java/src/main/ buildtypes/trunk/build-osgi-bund...

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntEngine.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntEngine.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntEngine.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntEngine.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,745 @@
+/*
+ *  Copyright 2008-2010 the EasyAnt project
+ *
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.easyant.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.apache.easyant.core.ant.Phase;
+import org.apache.easyant.core.ant.listerners.DefaultEasyAntLogger;
+import org.apache.easyant.core.descriptor.PluginDescriptor;
+import org.apache.easyant.core.factory.EasyantConfigurationFactory;
+import org.apache.easyant.core.ivy.IvyInstanceHelper;
+import org.apache.easyant.core.services.PluginService;
+import org.apache.easyant.core.services.impl.DefaultPluginServiceImpl;
+import org.apache.easyant.tasks.Import;
+import org.apache.easyant.tasks.LoadModule;
+import org.apache.ivy.Ivy;
+import org.apache.ivy.ant.IvyAntSettings;
+import org.apache.ivy.ant.IvyConfigure;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.BuildLogger;
+import org.apache.tools.ant.DemuxInputStream;
+import org.apache.tools.ant.DemuxOutputStream;
+import org.apache.tools.ant.Location;
+import org.apache.tools.ant.MagicNames;
+import org.apache.tools.ant.Main;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.PropertyHelper;
+import org.apache.tools.ant.Target;
+import org.apache.tools.ant.input.DefaultInputHandler;
+import org.apache.tools.ant.input.InputHandler;
+import org.apache.tools.ant.util.ClasspathUtils;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.ProxySetup;
+
+/**
+ * This class provides everything you need to run easyant. This class should be
+ * used to bootstrap easyant from IDE for example
+ */
+public class EasyAntEngine {
+
+	private static final long MEGABYTE = 1024 * 1024;;
+
+	private final EasyAntConfiguration configuration;
+
+	private PluginService pluginService = null;
+
+	/**
+	 * Default constructor will initialize the default configuration
+	 */
+	public EasyAntEngine() {
+		this(EasyantConfigurationFactory.getInstance()
+				.createDefaultConfiguration());
+	}
+
+	/**
+	 * Constructor if you want to use a custom configuration
+	 * 
+	 * @param configuration
+	 */
+	public EasyAntEngine(final EasyAntConfiguration configuration) {
+		this.configuration = configuration;
+	}
+
+	/**
+	 * Configure easyant ivy instance
+	 * 
+	 * @param project
+	 *            project instance
+	 * @return a configured {@link Ivy} instance
+	 */
+	protected Ivy configureEasyAntIvyInstance(Project project) {
+		IvyConfigure easyantIvyConfigure = new IvyConfigure();
+		easyantIvyConfigure
+				.setSettingsId(EasyAntMagicNames.EASYANT_IVY_INSTANCE);
+
+		project
+				.setNewProperty(
+						EasyAntMagicNames.EASYANT_DEFAULT_IVYSETTINGS,
+						this
+								.getClass()
+								.getResource(
+										"/org/apache/easyant/core/default-easyant-ivysettings.xml")
+								.toExternalForm());
+		project
+				.setNewProperty(
+						EasyAntMagicNames.EASYANT_EXTRA_IVYSETTINGS,
+						this
+								.getClass()
+								.getResource(
+										"/org/apache/easyant/core/extra-easyant-ivysettings.xml")
+								.toExternalForm());
+
+		project.setNewProperty(EasyAntMagicNames.EASYANT_CORE_REPO_URL, this
+				.getClass().getResource(
+						"/org/apache/easyant/core/repository/modules")
+				.toExternalForm());
+		if (this.getClass().getResource(
+				"/org/apache/easyant/repository/extra-modules") != null) {
+			project.setNewProperty(EasyAntMagicNames.EASYANT_EXTRA_REPO_URL,
+					this.getClass().getResource(
+							"/org/apache/easyant/repository/extra-modules")
+							.toExternalForm());
+		}
+
+		File userSettings = getUserEasyAntIvySettings(project);
+		String globalSettings = getGlobalEasyAntIvySettings(project);
+		boolean isIgnoringUserIvysettings=Project.toBoolean(project.getProperty(EasyAntMagicNames.IGNORE_USER_IVYSETTINGS));
+
+		if (userSettings.exists() && !isIgnoringUserIvysettings) {
+			project.log("loading user's easyant ivysettings file from "
+					+ userSettings.getAbsolutePath(),Project.MSG_DEBUG);
+			easyantIvyConfigure.setFile(userSettings);
+		} else if (globalSettings != null) {
+			project.log("loading global easyant ivysettings file from "
+					+ globalSettings,Project.MSG_DEBUG);
+			try {
+				easyantIvyConfigure.setUrl(globalSettings);
+			} catch (MalformedURLException malformedUrl) {
+				throw new BuildException(
+						"Unable to parse easyant ivysettings from the following url : "
+								+ globalSettings, malformedUrl);
+			}
+
+		} else {
+			project.log("using easyant default ivy settings file",
+					Project.MSG_VERBOSE);
+			String url = project
+					.getProperty(EasyAntMagicNames.EASYANT_DEFAULT_IVYSETTINGS);
+			try {
+				easyantIvyConfigure.setUrl(url);
+			} catch (MalformedURLException malformedUrl) {
+				throw new BuildException(
+						"Unable to parse easyant ivysettings from the following url : "
+								+ url, malformedUrl);
+			}
+		}
+		easyantIvyConfigure.setProject(project);
+		easyantIvyConfigure.setTaskName("configure-easyant");
+		easyantIvyConfigure.execute();
+
+		IvyAntSettings ivyAntSettings = IvyInstanceHelper
+				.getEasyAntIvyAntSettings(project);
+		return ivyAntSettings.getConfiguredIvyInstance(easyantIvyConfigure);
+	}
+
+	/**
+	 * Get user easyant-ivysettings file
+	 * 
+	 * @param project
+	 * @return the configured user easyant-ivysettings.file
+	 */
+	private File getUserEasyAntIvySettings(Project project) {
+		// path can be specified through a property
+		String path = project
+				.getProperty(EasyAntMagicNames.USER_EASYANT_IVYSETTINGS);
+		// if no property is set check the default location
+		if (path == null) {
+			path = PropertyHelper.getPropertyHelper(project).replaceProperties(
+					EasyAntConstants.DEFAULT_USER_EASYANT_IVYSETTINGS);
+		}
+		project.log("user's easyant-ivysettings file : " + path,
+				Project.MSG_DEBUG);
+		return new File(path);
+	}
+
+	/**
+	 * Get global easyant-ivysettings file
+	 * 
+	 * @param project
+	 * @return the configured global easyant-ivysettings.file
+	 */
+	private String getGlobalEasyAntIvySettings(Project project) {
+		PropertyHelper helper = PropertyHelper.getPropertyHelper(project);
+		String path=null;
+		if (configuration.getEasyantIvySettingsFile() != null) {
+			File f = new File(helper.replaceProperties(configuration.getEasyantIvySettingsFile()));
+			try {
+				path = f.toURL().toExternalForm();
+			} catch (MalformedURLException e) {
+				throw new BuildException("Can't load easyant ivysettings file from "+ f.getAbsolutePath());
+			}
+		}
+		if (configuration.getEasyantIvySettingsUrl() != null) {
+			path = helper.replaceProperties(configuration.getEasyantIvySettingsUrl());
+		}
+		// path can be specified through a property
+		if (path==null && project.getProperty(EasyAntMagicNames.GLOBAL_EASYANT_IVYSETTINGS) != null) {
+			path = project
+					.getProperty(EasyAntMagicNames.GLOBAL_EASYANT_IVYSETTINGS);
+		}
+		// if no property is set check the default location
+		if (path == null) {
+			path = helper.replaceProperties(
+					EasyAntConstants.DEFAULT_GLOBAL_EASYANT_IVYSETTINGS);
+		}
+		project.log("global easyant-ivysettings file : " + path,
+				Project.MSG_DEBUG);
+		return path;
+	}
+
+	protected void configurePluginService(Project project,
+			Ivy easyantIvyInstance) {
+		pluginService = new DefaultPluginServiceImpl(easyantIvyInstance);
+		project.addReference(EasyAntMagicNames.PLUGIN_SERVICE_INSTANCE,
+				pluginService);
+
+	}
+
+	/**
+	 * Adds the listeners specified in the command line arguments, along with
+	 * the default listener, to the specified project.
+	 * 
+	 * @param project
+	 *            The project to add listeners to. Must not be <code>null</code>
+	 *            .
+	 */
+	protected void addBuildListeners(Project project) {
+
+		// Add the default listener
+		project.addBuildListener(createLogger());
+
+		for (int i = 0; i < configuration.getListeners().size(); i++) {
+			String className = (String) configuration.getListeners().elementAt(
+					i);
+			BuildListener listener = (BuildListener) ClasspathUtils
+					.newInstance(className, EasyAntEngine.class
+							.getClassLoader(), BuildListener.class);
+			project.setProjectReference(listener);
+
+			project.addBuildListener(listener);
+		}
+	}
+
+	/**
+	 * Creates the InputHandler and adds it to the project.
+	 * 
+	 * @param project
+	 *            the project instance.
+	 * 
+	 * @exception BuildException
+	 *                if a specified InputHandler implementation could not be
+	 *                loaded.
+	 */
+	protected void addInputHandler(Project project) {
+		InputHandler handler = null;
+
+		if (configuration.getInputHandlerClassname() == null) {
+			handler = new DefaultInputHandler();
+		} else {
+			handler = (InputHandler) ClasspathUtils.newInstance(configuration
+					.getInputHandlerClassname(), Main.class.getClassLoader(),
+					InputHandler.class);
+			project.setProjectReference(handler);
+		}
+		project.setInputHandler(handler);
+	}
+
+	/**
+	 * Creates the default build logger for sending build events to the ant log.
+	 * 
+	 * @return the logger instance for this build.
+	 */
+	protected BuildLogger createLogger() {
+		BuildLogger logger = null;
+		if (configuration.getLoggerClassname() != null) {
+			try {
+				logger = (BuildLogger) ClasspathUtils.newInstance(configuration
+						.getLoggerClassname(), EasyAntEngine.class
+						.getClassLoader(), BuildLogger.class);
+			} catch (BuildException e) {
+				throw new RuntimeException("The specified logger class "
+						+ configuration.getLoggerClassname()
+						+ " could not be used because " + e.getMessage(), e);
+			}
+		} else {
+			logger = new DefaultEasyAntLogger();
+		}
+
+		logger.setMessageOutputLevel(configuration.getMsgOutputLevel());
+		logger.setOutputPrintStream(configuration.getOut());
+		logger.setErrorPrintStream(configuration.getErr());
+		logger.setEmacsMode(configuration.isEmacsMode());
+
+		return logger;
+	}
+
+	/**
+	 * Search parent directories for the build file.
+	 * <p>
+	 * Takes the given target as a suffix to append to each parent directory in
+	 * search of a build file. Once the root of the file-system has been reached
+	 * an exception is thrown.
+	 * 
+	 * @param start
+	 *            Leaf directory of search. Must not be <code>null</code>.
+	 * @param suffix
+	 *            Suffix filename to look for in parents. Must not be
+	 *            <code>null</code>.
+	 * 
+	 * @return A handle to the build file if one is found
+	 * 
+	 * @exception BuildException
+	 *                if no build file is found
+	 */
+	protected File findBuildModule(String start, String suffix)
+			throws BuildException {
+		if (configuration.getMsgOutputLevel() >= Project.MSG_INFO) {
+			System.out.println("Searching for " + suffix + " ...");
+		}
+
+		File parent = new File(new File(start).getAbsolutePath());
+		File file = new File(parent, suffix);
+
+		// check if the target file exists in the current directory
+		while (!file.exists()) {
+			// change to parent directory
+			parent = parent.getParentFile();
+
+			// if parent is null, then we are at the root of the fs,
+			// complain that we can't find the build file.
+			if (parent == null) {
+				throw new BuildException("Could not locate a build file!");
+			}
+
+			// refresh our file handle
+			file = new File(parent, suffix);
+		}
+
+		return file;
+	}
+
+	/**
+	 * configure a given project with current configuration
+	 * 
+	 * @param project
+	 *            a given project
+	 * @throws BuildException
+	 */
+	public void configureProject(Project project) throws BuildException {
+
+		addBuildListeners(project);
+		addInputHandler(project);
+
+		// set the thread priorities
+		if (configuration.getThreadPriority() != null) {
+			try {
+				project.log("Setting Ant's thread priority to "
+						+ configuration.getThreadPriority(),
+						Project.MSG_VERBOSE);
+				Thread.currentThread().setPriority(
+						configuration.getThreadPriority().intValue());
+			} catch (SecurityException swallowed) {
+				// we cannot set the priority here.
+				project
+						.log("A security manager refused to set the -nice value");
+			}
+		}
+
+		project.setKeepGoingMode(configuration.isKeepGoingMode());
+		if (configuration.isProxy()) {
+			// proxy setup if enabledcoreLoader
+			ProxySetup proxySetup = new ProxySetup(project);
+			proxySetup.enableProxies();
+		}
+
+		project.setName("EasyAnt");
+
+	}
+
+	/**
+	 * Initialize an easyant Project
+	 * 
+	 * @param project
+	 */
+	public void initProject(Project project) {
+		project.init();
+		// set user-define properties
+		Enumeration e = configuration.getDefinedProps().keys();
+		while (e.hasMoreElements()) {
+			String arg = (String) e.nextElement();
+			String value = (String) configuration.getDefinedProps().get(arg);
+			project.setUserProperty(arg, value);
+        }
+
+        project.setUserProperty(EasyAntMagicNames.EASYANT_OFFLINE, Boolean.toString(configuration.isOffline()));
+
+		File buildModule = configuration.getBuildModule();
+		File buildFile = configuration.getBuildFile();
+
+		if (buildModule == null) {
+			buildModule = new File(EasyAntConstants.DEFAULT_BUILD_MODULE);
+		}
+
+		if (!buildModule.exists() && configuration.isBuildModuleLookupEnabled()) {
+			buildModule = findBuildModule(System.getProperty("user.dir"),
+					buildModule.toString());
+		}
+
+		// calculate buildFile location based on buildModule directory
+		if (buildModule.exists() && buildFile == null) {
+			buildFile = new File(buildModule.getParentFile(),
+					EasyAntConstants.DEFAULT_BUILD_FILE);
+		}
+
+		if (buildFile == null && configuration.isBuildModuleLookupEnabled()) {
+			buildFile = findBuildModule(System.getProperty("user.dir"),
+					EasyAntConstants.DEFAULT_BUILD_FILE);
+		}
+
+		// Normalize buildFile for re-import detection
+		if (buildModule != null) {
+			buildModule = FileUtils.getFileUtils().normalize(
+					buildModule.getAbsolutePath());
+			project.setNewProperty(EasyAntMagicNames.EASYANT_FILE, buildModule
+					.getAbsolutePath());
+
+		}
+
+		if (buildFile != null) {
+			buildFile = FileUtils.getFileUtils().normalize(
+					buildFile.getAbsolutePath());
+			project.setNewProperty(MagicNames.ANT_FILE, buildFile
+					.getAbsolutePath());
+
+		}
+
+		configuration.setBuildFile(buildFile);
+		configuration.setBuildModule(buildModule);
+
+		// Emulate an empty project
+		// import task check that projectHelper is at toplevel by checking the
+		// size of projectHelper.getImportTask()
+		ProjectHelper helper = ProjectHelper.getProjectHelper();
+		File mainscript = null;
+		try {
+			mainscript = File.createTempFile(
+					EasyAntConstants.EASYANT_TASK_NAME, null);
+			mainscript.deleteOnExit();
+		} catch (IOException e1) {
+			throw new BuildException("Can't create temp file", e1);
+		}
+
+		Location mainscriptLocation = new Location(mainscript.toString());
+		helper.getImportStack().addElement(mainscript);
+		project.addReference(ProjectHelper.PROJECTHELPER_REFERENCE, helper);
+
+		// Used to emulate top level target
+		Target topLevel = new Target();
+		topLevel.setName("");
+
+		// Validate Phase is used by several system plugin so we should
+		// initialize it
+		Phase validatePhase = new Phase();
+		validatePhase.setName("validate");
+		validatePhase
+				.setDescription("validate the project is correct and all necessary information is available");
+		project.addTarget("validate", validatePhase);
+
+		Ivy easyantIvyInstance = configureEasyAntIvyInstance(project);
+		configurePluginService(project, easyantIvyInstance);
+
+		// Profile
+		if (configuration.getActiveBuildConfigurations().size() != 0) {
+			String buildConfigurations = null;
+			for (String conf : configuration.getActiveBuildConfigurations()) {
+				if (buildConfigurations == null) {
+					buildConfigurations = conf;
+				} else {
+					buildConfigurations = buildConfigurations + "," + conf;
+				}
+
+			}
+			project.log("Active build configurations : " + buildConfigurations,
+					Project.MSG_INFO);
+			project.setProperty(EasyAntMagicNames.ACTIVE_BUILD_CONFIGURATIONS,
+					buildConfigurations);
+		}
+
+		// Load system plugins
+		if (configuration.getSystemPlugins().size() > 0) {
+			project.log("Loading System Plugins...");
+		}
+		for (PluginDescriptor systemPlugin : configuration.getSystemPlugins()) {
+			// import/include system plugin
+			Import importTask = new Import();
+			importTask.setMrid(systemPlugin.getMrid());
+			importTask.setOrganisation(systemPlugin.getOrganisation());
+			importTask.setModule(systemPlugin.getModule());
+			importTask.setRevision(systemPlugin.getRevision());
+			importTask.setAs(systemPlugin.getAs());
+			importTask.setMode(systemPlugin.getMode());
+			importTask.setMandatory(systemPlugin.isMandatory());
+			importTask.setProject(project);
+			importTask.setTaskName(EasyAntConstants.EASYANT_TASK_NAME);
+			importTask.setOwningTarget(topLevel);
+			importTask.setLocation(mainscriptLocation);
+			importTask.execute();
+		}
+
+		if (configuration.getBuildModule() != null
+				|| configuration.getBuildFile() != null) {
+			LoadModule lm = new LoadModule();
+			lm.setBuildModule(configuration.getBuildModule());
+			lm.setBuildFile(configuration.getBuildFile());
+			lm.setTaskName(EasyAntConstants.EASYANT_TASK_NAME);
+			lm.setProject(project);
+			lm.setOwningTarget(topLevel);
+			lm.setLocation(mainscriptLocation);
+			lm.execute();
+		}
+	}
+
+	/**
+	 * this method run the build process
+	 * 
+	 * @throws BuildException
+	 */
+	public void doBuild() throws BuildException {
+		final Project project = new Project();
+		project.fireBuildStarted();
+
+		Throwable error = null;
+
+		try {
+
+			PrintStream savedErr = System.err;
+			PrintStream savedOut = System.out;
+			InputStream savedIn = System.in;
+
+			// use a system manager that prevents from System.exit()
+			SecurityManager oldsm = null;
+			oldsm = System.getSecurityManager();
+
+			// SecurityManager can not be installed here for backwards
+			// compatibility reasons (PD). Needs to be loaded prior to
+			// ant class if we are going to implement it.
+			// System.setSecurityManager(new NoExitSecurityManager());
+			try {
+				if (configuration.isAllowInput()) {
+					project.setDefaultInputStream(System.in);
+				}
+				System.setIn(new DemuxInputStream(project));
+				System.setOut(new PrintStream(new DemuxOutputStream(project,
+						false)));
+				System.setErr(new PrintStream(new DemuxOutputStream(project,
+						true)));
+				configureProject(project);
+				initProject(project);
+
+				// make sure that we have a target to execute
+				if (configuration.getTargets().size() == 0) {
+					if (project.getDefaultTarget() != null) {
+						configuration.getTargets().addElement(
+								project.getDefaultTarget());
+					}
+				}
+
+				project.executeTargets(configuration.getTargets());
+			} finally {
+				// put back the original security manager
+				// The following will never eval to true. (PD)
+				if (oldsm != null) {
+					System.setSecurityManager(oldsm);
+				}
+
+				System.setOut(savedOut);
+				System.setErr(savedErr);
+				System.setIn(savedIn);
+			}
+		} catch (RuntimeException exc) {
+			error = exc;
+			throw exc;
+		} catch (Error e) {
+			error = e;
+			throw e;
+		} finally {
+			try {
+				project.fireBuildFinished(error);
+			} catch (Throwable t) {
+				// yes, I know it is bad style to catch Throwable,
+				// but if we don't, we lose valuable information
+				System.err.println("Caught an exception while logging the"
+						+ " end of the build.  Exception was:");
+				t.printStackTrace();
+				if (error != null) {
+					System.err.println("There has been an error prior to"
+							+ " that:");
+					error.printStackTrace();
+				}
+				throw new BuildException(t);
+			}
+		}
+		if (configuration.isShowMemoryDetails()
+				|| configuration.getMsgOutputLevel() >= Project.MSG_VERBOSE) {
+			printMemoryDetails(project);
+		}
+
+	}
+
+	/**
+	 * This is a static method used to run build process
+	 * 
+	 * @param eaConfig
+	 *            an easyant configuration
+	 * @throws BuildException
+	 */
+	public static void runBuild(EasyAntConfiguration eaConfig)
+			throws BuildException {
+		EasyAntEngine eaEngine = new EasyAntEngine(eaConfig);
+		eaEngine.doBuild();
+	}
+
+	/**
+	 * This is a static method used to configure and initialize an existing
+	 * project
+	 * 
+	 * @param project
+	 *            a given project
+	 * @param eaConfiguration
+	 *            an easyant configuration
+	 * @return configured project
+	 * @throws BuildException
+	 */
+	public static Project configureAndInitProject(Project project,
+			EasyAntConfiguration eaConfiguration) throws BuildException {
+		EasyAntEngine eaEngine = new EasyAntEngine(eaConfiguration);
+		eaEngine.configureProject(project);
+		eaEngine.initProject(project);
+		return project;
+	}
+
+	/**
+	 * Print memory details
+	 * 
+	 * @param project
+	 *            a given project
+	 */
+	public static void printMemoryDetails(Project project) {
+		project.log("---- Memory Details ----");
+		project.log("  Used Memory  = "
+				+ (Runtime.getRuntime().totalMemory() / MEGABYTE - Runtime
+						.getRuntime().freeMemory()
+						/ MEGABYTE) + "MB");
+		project.log("  Free Memory  = "
+				+ (Runtime.getRuntime().freeMemory() / MEGABYTE) + "MB");
+		project.log("  Total Memory = "
+				+ (Runtime.getRuntime().totalMemory() / MEGABYTE) + "MB");
+		project.log("-----------------------");
+	}
+
+	/**
+	 * Return the configured plugin service instance
+	 * 
+	 * @return the configured plugin service instance
+	 */
+	public PluginService getPluginService() {
+		// hack for IDE integration
+		if (pluginService == null) {
+			Project project = new Project();
+			project.setCoreLoader(configuration.getCoreLoader());
+			Enumeration<?> e = configuration.getDefinedProps().keys();
+			while (e.hasMoreElements()) {
+				String arg = (String) e.nextElement();
+				String value = (String) configuration.getDefinedProps()
+						.get(arg);
+				project.setUserProperty(arg, value);
+			}
+			project.setName("EasyAnt");
+			// not sure we need to invoke init here
+			project.init();
+			Ivy ivy = configureEasyAntIvyInstance(project);
+			configurePluginService(project, ivy);
+		}
+		return pluginService;
+	}
+
+	/**
+	 * Cache of the EasyAnt version information when it has been loaded.
+	 */
+	private static String easyantVersion = null;
+
+	/**
+	 * Returns the EasyAnt version information, if available. Once the
+	 * information has been loaded once, it's cached and returned from the cache
+	 * on future calls.
+	 * 
+	 * @return the Ant version information as a String (always non-
+	 *         <code>null</code>)
+	 * 
+	 * @exception BuildException
+	 *                if the version information is unavailable
+	 */
+	public static String getEasyAntVersion() {
+
+		if (easyantVersion == null) {
+			try {
+				Properties props = new Properties();
+				InputStream in = Main.class
+						.getResourceAsStream("/META-INF/version.properties");
+				props.load(in);
+				in.close();
+
+				StringBuffer msg = new StringBuffer();
+				msg.append("EasyAnt version ");
+				msg.append(props.getProperty("VERSION"));
+				msg.append(" compiled on ");
+				msg.append(props.getProperty("DATE"));
+				easyantVersion = msg.toString();
+			} catch (IOException ioe) {
+				throw new BuildException(
+						"Could not load the version information:"
+								+ ioe.getMessage());
+			} catch (NullPointerException npe) {
+				throw new BuildException(
+						"Could not load the version information.");
+			}
+		}
+		return easyantVersion;
+	}
+
+}

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntEngine.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntEngine.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntEngine.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntEngine.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMagicNames.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMagicNames.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMagicNames.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMagicNames.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,187 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.core;
+
+import org.apache.easyant.tasks.CoreRevisionCheckerTask;
+
+/**
+ * Magic names used within EasyAnt.
+ * 
+ * Not all magic names are here yet.
+ * 
+ * s
+ */
+public interface EasyAntMagicNames {
+
+	/**
+	 * property for easyant file name. Value: {@value}
+	 */
+	public static final String EASYANT_FILE = "easyant.file";
+
+	/**
+	 * Name the default ivy instance name used by easyant Value: {@value}
+	 */
+	public static final String EASYANT_IVY_INSTANCE = "easyant.ivy.instance";
+
+	/**
+	 * Name of directory to store EasyAnt modules Value: {@value}
+	 */
+	public static final String EASYANT_MODULES_DIR = "easyant.modules.dir";
+
+	/**
+	 * Name the default ivy instance name used by projects Value: {@value}
+	 */
+	public static final String PROJECT_IVY_INSTANCE = "project.ivy.instance";
+
+	/**
+	 * Name of the property that contains the project ivy setting file Value: *
+	 * {@value}
+	 */
+	public static final String PROJECT_IVY_SETTING_FILE = "project.ivy.settings.file";
+
+	/**
+	 * Name of the property that contains the project ivy setting url Value: *
+	 * {@value}
+	 */
+	public static final String PROJECT_IVY_SETTING_URL = "project.ivy.settings.url";
+
+	/**
+	 * Name of the property that contains active build configuration Value: *
+	 * {@value}
+	 */
+	public static final String ACTIVE_BUILD_CONFIGURATIONS = "active.build.configurations";
+
+	/**
+	 * Name of the property that contains all active build configuration for the
+	 * current project Value: {@value}
+	 */
+	public static final String MAIN_CONFS = "main.confs";
+
+	/**
+	 * Name of the property that contains build configuration available in
+	 * current project Value: {@value}
+	 */
+	public static final String AVAILABLE_BUILD_CONFIGURATIONS = "available.build.configurations";
+
+	/**
+	 * Property name used to disable core revision check if this property is set
+	 * to true it means that corerevision checker feature will be disabled.
+	 * Value: {@value}
+	 * 
+	 * @see CoreRevisionCheckerTask
+	 */
+	public static final String SKIP_CORE_REVISION_CHECKER = "skip.corerevision.checker";
+
+	/**
+	 * Property name containing the target directory Value: {@value}
+	 */
+	public static final String TARGET = "target";
+
+	/**
+	 * Name of the plugin service instance Value: {@value}
+	 */
+	public static final String PLUGIN_SERVICE_INSTANCE = "plugin.service.instance";
+
+	/**
+	 * Name of the property containing the default location of ivysettings file
+	 * used by easyant ivy instance Value: {@value}
+	 */
+	public static final String EASYANT_DEFAULT_IVYSETTINGS = "easyant.default.ivysettings.url";
+
+	/**
+	 * Name of the property containing the default location of ivysettings file
+	 * used by easyant ivy instance with extra modules Value: {@value}
+	 */
+	public static final String EASYANT_EXTRA_IVYSETTINGS = "easyant.extra.ivysettings.url";
+
+	/**
+	 * Name of the property containing the default location of ivysettings file
+	 * used by project ivy instance Value: {@value}
+	 */
+	public static final String PROJECT_DEFAULT_IVYSETTINGS = "project.default.ivysettings.url";
+
+	/**
+	 * Name of the property containing the easyant core repository Value:
+	 * {@value}
+	 */
+	public static final String EASYANT_CORE_REPO_URL = "easyant.core.repo.url";
+
+	/**
+	 * Name of the property containing the easyant extra repository Value:
+	 * {@value}
+	 */
+	public static final String EASYANT_EXTRA_REPO_URL = "easyant.extramodules.repo.url";
+
+	/**
+	 * Name of the property containing the log stategy for easyant modules
+	 * Value: {@value}
+	 */
+	public static final String MODULE_DOWNLOAD_LOG = "easyant.modules.download.log";
+
+	/**
+	 * Name of the property containing the build-scoped repository name, if
+	 * configured Value: {@value}
+	 */
+	public static final String EASYANT_BUILD_REPOSITORY = "easyant.build.repository";
+
+	public static final String META_TARGET = "meta.target";
+
+	/**
+	 * Name of the property containing the appended to menu generator registry
+	 * references Value: {@value}
+	 */
+	public static final String MENU_GENERATOR_REGISTRY_REF = "menugen.ref";
+
+	/**
+	 * Name of the property containing pre module targets. In a multi project
+	 * context, those targets will be executed before delagating to subprojects.
+	 * Value : {@value}
+	 */
+	public static final String PRE_MODULE_TARGETS = "pre.module.targets";
+
+	/**
+	 * Name of the property containing path to user easyant ivysettings file
+	 * Value: {@value}
+	 */
+	public static final String USER_EASYANT_IVYSETTINGS = "user.easyant.ivysettings.file";
+
+	/**
+	 * Name of the property containing path to global easyant ivysettings file
+	 * Value: {@value}
+	 */
+	public static final String GLOBAL_EASYANT_IVYSETTINGS = "global.easyant.ivysettings.file";
+	
+	/**
+	 * Name of the property specifyinf if build repository should be used
+	 * Value: {@value}
+	 */
+	public static final String USE_BUILD_REPOSITORY = "use.build.repository";
+
+    /**
+     * property for easyant offline mode. Value: {@value}
+     */
+    public static final String EASYANT_OFFLINE = "easyant.offline";
+
+    /**
+     * Property specifying if user ivysettings should be ignored
+     * Value: {@value}
+     */
+	public static final String IGNORE_USER_IVYSETTINGS = "ignore.user.ivysettings";
+
+}

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMagicNames.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMagicNames.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMagicNames.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMain.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMain.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMain.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMain.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,1010 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+
+package org.apache.easyant.core;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+import org.apache.easyant.core.ant.Phase;
+import org.apache.easyant.core.factory.EasyantConfigurationFactory;
+import org.apache.easyant.man.ProjectMan;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DemuxInputStream;
+import org.apache.tools.ant.DemuxOutputStream;
+import org.apache.tools.ant.Diagnostics;
+import org.apache.tools.ant.ExitStatusException;
+import org.apache.tools.ant.Main;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Target;
+import org.apache.tools.ant.launch.AntMain;
+import org.apache.tools.ant.util.FileUtils;
+
+/**
+ * Command line entry point into EasyAnt. This class is entered via the
+ * canonical `public static void main` entry point and reads the command line
+ * arguments. It then assembles and executes an Ant project.
+ * <p>
+ * If you integrating EasyAnt into some other tool, this is not the class to use
+ * as an entry point. Instead you should have a look at {@link EasyAntEngine}.
+ * </p>
+ */
+public class EasyAntMain implements AntMain {
+	/**
+	 * A Set of args are are handled by the launcher and should not be seen by
+	 * Main.
+	 */
+	private static final Set LAUNCH_COMMANDS = new HashSet();
+	private boolean isLogFileUsed;
+	static {
+		LAUNCH_COMMANDS.add("-lib");
+		LAUNCH_COMMANDS.add("-cp");
+		LAUNCH_COMMANDS.add("-noclasspath");
+		LAUNCH_COMMANDS.add("--noclasspath");
+		LAUNCH_COMMANDS.add("-nouserlib");
+		LAUNCH_COMMANDS.add("-main");
+	}
+	private EasyAntConfiguration easyAntConfiguration;
+	private boolean projectHelp;
+	private boolean projectMan;
+
+	private ProjectMan man;
+	
+	/**
+	 * Whether or not this instance has successfully been constructed and is
+	 * ready to run.
+	 */
+	private boolean readyToRun;
+	private Vector propertyFiles = new Vector(1);
+	private File buildFile;
+	private File buildModule;
+	private File easyantConfFile;
+	private String buildConf;
+
+	/**
+	 * Prints the message of the Throwable if it (the message) is not
+	 * <code>null</code>.
+	 * 
+	 * @param t
+	 *            Throwable to print the message of. Must not be
+	 *            <code>null</code>.
+	 */
+	private static void printMessage(Throwable t) {
+		String message = t.getMessage();
+		if (message != null) {
+			System.err.println(message);
+		}
+	}
+
+	/**
+	 * Creates a new instance of this class using the arguments specified, gives
+	 * it any extra user properties which have been specified, and then runs the
+	 * build using the classloader provided.
+	 * 
+	 * @param args
+	 *            Command line arguments. Must not be <code>null</code>.
+	 * @param additionalUserProperties
+	 *            Any extra properties to use in this build. May be
+	 *            <code>null</code>, which is the equivalent to passing in an
+	 *            empty set of properties.
+	 * @param coreLoader
+	 *            Classloader used for core classes. May be <code>null</code> in
+	 *            which case the system classloader is used.
+	 */
+	public static void start(String[] args,
+			Properties additionalUserProperties, ClassLoader coreLoader) {
+		EasyAntMain m = new EasyAntMain();
+		m.startAnt(args, additionalUserProperties, coreLoader);
+	}
+
+	/**
+	 * Start Ant
+	 * 
+	 * @param args
+	 *            command line args
+	 * @param additionalUserProperties
+	 *            properties to set beyond those that may be specified on the
+	 *            args list
+	 * @param coreLoader
+	 *            - not used
+	 * 
+	 * @since Ant 1.6
+	 */
+	public void startAnt(String[] args, Properties additionalUserProperties,
+			ClassLoader coreLoader) {
+		easyAntConfiguration.setCoreLoader(coreLoader);
+		try {
+			Diagnostics.validateVersion();
+			processArgs(args);
+		} catch (Throwable exc) {
+			if (easyAntConfiguration.getMsgOutputLevel() >= Project.MSG_VERBOSE) {
+				exc.printStackTrace();
+			} 
+			handleLogfile();
+			printMessage(exc);
+			exit(1);
+			return;
+		}
+
+		if (additionalUserProperties != null) {
+			for (Enumeration e = additionalUserProperties.keys(); e
+					.hasMoreElements();) {
+				String key = (String) e.nextElement();
+				String property = additionalUserProperties.getProperty(key);
+				easyAntConfiguration.getDefinedProps().put(key, property);
+			}
+		}
+
+		// expect the worst
+		int exitCode = 1;
+		try {
+			try {
+				runBuild(coreLoader);
+				exitCode = 0;
+			} catch (ExitStatusException ese) {
+				exitCode = ese.getStatus();
+				if (exitCode != 0) {
+					throw ese;
+				}
+			}
+		} catch (BuildException be) {
+			if (easyAntConfiguration.getErr() != System.err) {
+				printMessage(be);
+			}
+		} catch (Throwable exc) {
+			exc.printStackTrace();
+			printMessage(exc);
+		} finally {
+			handleLogfile();
+		}
+		exit(exitCode);
+	}
+
+	/**
+	 * This operation is expected to call {@link System#exit(int)}, which is
+	 * what the base version does. However, it is possible to do something else.
+	 * 
+	 * @param exitCode
+	 *            code to exit with
+	 */
+	protected void exit(int exitCode) {
+		System.exit(exitCode);
+	}
+
+	/**
+	 * Close logfiles, if we have been writing to them.
+	 * 
+	 * @since Ant 1.6
+	 */
+	private void handleLogfile() {
+		if (isLogFileUsed && easyAntConfiguration != null) {
+			FileUtils.close(easyAntConfiguration.getOut());
+			FileUtils.close(easyAntConfiguration.getErr());
+		}
+	}
+
+	/**
+	 * Command line entry point. This method kicks off the building of a project
+	 * object and executes a build using either a given target or the default
+	 * target.
+	 * 
+	 * @param args
+	 *            Command line arguments. Must not be <code>null</code>.
+	 */
+	public static void main(String[] args) {
+		start(args, null, null);
+	}
+
+	/**
+	 * Constructor used when creating Main for later arg processing and startup
+	 */
+	public EasyAntMain() {
+		easyAntConfiguration = EasyantConfigurationFactory.getInstance()
+				.createDefaultConfiguration();
+	}
+
+	/**
+	 * Process command line arguments. When ant is started from Launcher,
+	 * launcher-only arguments do not get passed through to this routine.
+	 * 
+	 * @param args
+	 *            the command line arguments.
+	 * 
+	 * @since Ant 1.6
+	 */
+	private void processArgs(String[] args) {
+		String searchForThis = null;
+		PrintStream logTo = null;
+
+		// cycle through given args
+
+		boolean justPrintUsage = false;
+		boolean justPrintVersion = false;
+		boolean justPrintDiagnostics = false;
+
+		for (int i = 0; i < args.length; i++) {
+			String arg = args[i];
+
+			if (arg.equals("-help") || arg.equals("-h")) {
+				justPrintUsage = true;
+			} else if (arg.equals("-version")) {
+				justPrintVersion = true;
+			} else if (arg.equals("-showMemoryDetails")) {
+				easyAntConfiguration.setShowMemoryDetails(true);
+			} else if (arg.equals("-diagnostics")) {
+				justPrintDiagnostics = true;
+			} else if (arg.equals("-quiet") || arg.equals("-q")) {
+				easyAntConfiguration.setMsgOutputLevel(Project.MSG_WARN);
+			} else if (arg.equals("-verbose") || arg.equals("-v")) {
+				easyAntConfiguration.setMsgOutputLevel(Project.MSG_VERBOSE);
+			} else if (arg.equals("-debug") || arg.equals("-d")) {
+				easyAntConfiguration.setMsgOutputLevel(Project.MSG_DEBUG);
+			} else if (arg.equals("-noinput")) {
+				easyAntConfiguration.setAllowInput(false);
+			} else if (arg.equals("-logfile") || arg.equals("-l")) {
+				try {
+					File logFile = new File(args[i + 1]);
+					i++;
+					logTo = new PrintStream(new FileOutputStream(logFile));
+					isLogFileUsed = true;
+				} catch (IOException ioe) {
+					String msg = "Cannot write on the specified log file. "
+							+ "Make sure the path exists and you have write "
+							+ "permissions.";
+					throw new BuildException(msg);
+				} catch (ArrayIndexOutOfBoundsException aioobe) {
+					String msg = "You must specify a log file when "
+							+ "using the -log argument";
+					throw new BuildException(msg);
+				}
+			} else if (arg.equals("-buildmodule") || arg.equals("-file")
+					|| arg.equals("-f")) {
+				i = handleArgBuildModule(args, i);
+				easyAntConfiguration.setBuildModule(buildModule);
+			} else if (arg.equals("-buildfile")) {
+				i = handleArgBuildFile(args, i);
+				easyAntConfiguration.setBuildFile(buildFile);
+			} else if (arg.equals("-buildconf") || arg.equals("-C")) {
+				i = handleArgBuildConf(args,i);
+				easyAntConfiguration.getActiveBuildConfigurations().add(buildConf);
+			} else if (arg.equals("-config-file")) {
+				i = handleArgEasyAntConf(args, i);
+				try {
+					easyAntConfiguration = EasyantConfigurationFactory
+							.getInstance().createConfigurationFromFile(
+									easyAntConfiguration,
+									easyantConfFile.toURL());
+				} catch (Exception e) {
+					throw new BuildException(e);
+				}
+			} else if (arg.equals("-listener")) {
+				i = handleArgListener(args, i);
+			} else if (arg.startsWith("-D")) {
+				i = handleArgDefine(args, i);
+			} else if (arg.equals("-logger")) {
+				i = handleArgLogger(args, i);
+			} else if (arg.equals("-inputhandler")) {
+				i = handleArgInputHandler(args, i);
+			} else if (arg.equals("-emacs") || arg.equals("-e")) {
+				easyAntConfiguration.setEmacsMode(true);
+			} else if (arg.equals("-listTargets")
+					|| arg.equals("-describe")
+					|| arg.equals("-listProps")
+					|| arg.equals("-listPhases")
+					|| arg.equals("-listPlugins")) {
+				projectMan = true;
+				man = new ProjectMan();
+				man.setCommand(arg);
+				if(i < args.length-1 && !args[i+1].startsWith("-")) {
+					man.addParam(args[++i]);
+				}
+			} else if(arg.equals("-projecthelp")
+					|| arg.equals("-p")) {
+				// set the flag to display the targets and quit
+				projectHelp = true;
+			} else if (arg.equals("-find") || arg.equals("-s")) {
+				// eat up next arg if present, default to module.ivy
+				if (i < args.length - 1) {
+					searchForThis = args[++i];
+
+				} else {
+					searchForThis = EasyAntConstants.DEFAULT_BUILD_MODULE;
+				}
+				easyAntConfiguration.setBuildModule(new File(searchForThis));
+				easyAntConfiguration.setBuildModuleLookupEnabled(true);
+			} else if (arg.startsWith("-propertyfile")) {
+				i = handleArgPropertyFile(args, i);
+			} else if (arg.equals("-k") || arg.equals("-keep-going")) {
+				easyAntConfiguration.setKeepGoingMode(true);
+            } else if (arg.equals("-offline") || arg.equals("-o")) {
+                easyAntConfiguration.setOffline(true);
+			} else if (arg.equals("-nice")) {
+				i = handleArgNice(args, i);
+			} else if (LAUNCH_COMMANDS.contains(arg)) {
+				// catch script/ant mismatch with a meaningful message
+				// we could ignore it, but there are likely to be other
+				// version problems, so we stamp down on the configuration now
+				String msg = "Ant's Main method is being handed "
+						+ "an option " + arg
+						+ " that is only for the launcher class."
+						+ "\nThis can be caused by a version mismatch between "
+						+ "the ant script/.bat file and Ant itself.";
+				throw new BuildException(msg);
+			} else if (arg.equals("-autoproxy")) {
+				easyAntConfiguration.setProxy(true);
+			} else if (arg.startsWith("-")) {
+				// we don't have any more args to recognize!
+				String msg = "Unknown argument: " + arg;
+				System.err.println(msg);
+				printUsage();
+				throw new BuildException("");
+			} else {
+				easyAntConfiguration.getTargets().addElement(arg);
+			}
+		}
+
+		if (easyAntConfiguration.getMsgOutputLevel() >= Project.MSG_VERBOSE
+				|| justPrintVersion) {
+			printVersion(easyAntConfiguration.getMsgOutputLevel());
+		}
+
+		if (justPrintUsage || justPrintVersion || justPrintDiagnostics) {
+			if (justPrintUsage) {
+				printUsage();
+			}
+			if (justPrintDiagnostics) {
+				Diagnostics.doReport(System.out, easyAntConfiguration
+						.getMsgOutputLevel());
+			}
+			return;
+		}
+
+		// Load the property files specified by -propertyfile
+		loadPropertyFiles();
+
+		if (logTo != null) {
+			easyAntConfiguration.setOut(logTo);
+			easyAntConfiguration.setErr(logTo);
+			System.setOut(easyAntConfiguration.getOut());
+			System.setErr(easyAntConfiguration.getErr());
+		}
+		readyToRun = true;
+	}
+
+	// --------------------------------------------------------
+	// Methods for handling the command line arguments
+	// --------------------------------------------------------
+
+	/** Handle the -buildfile, -file, -f argument */
+	private int handleArgBuildFile(String[] args, int pos) {
+		try {
+			buildFile = new File(args[++pos].replace('/', File.separatorChar));
+			++pos;
+		} catch (ArrayIndexOutOfBoundsException aioobe) {
+			throw new BuildException(
+					"You must specify a buildfile when using the -buildfile argument");
+		}
+		return pos;
+	}
+
+	private int handleArgBuildModule(String[] args, int pos) {
+		try {
+			buildModule = new File(args[++pos].replace('/', File.separatorChar));
+		} catch (ArrayIndexOutOfBoundsException aioobe) {
+			throw new BuildException(
+					"You must specify a buildfile when using the -buildmodule argument");
+		}
+		return pos;
+	}
+	
+	private int handleArgBuildConf(String[] args, int pos) {
+		try {
+			buildConf = args[++pos];
+		} catch (ArrayIndexOutOfBoundsException aioobe) {
+			throw new BuildException(
+					"You must specify a build configuration when using the -buildconf argument");
+		}
+		return pos;
+	}
+
+	/** Handle -config-file argument */
+	private int handleArgEasyAntConf(String[] args, int pos) {
+		try {
+			easyantConfFile = new File(args[++pos].replace('/',
+					File.separatorChar));
+		} catch (ArrayIndexOutOfBoundsException aioobe) {
+			throw new BuildException(
+					"You must specify an easyant ivy configuration when using the -easyantivyconf argument");
+		}
+		return pos;
+	}
+
+	/** Handle -listener argument */
+	private int handleArgListener(String[] args, int pos) {
+		try {
+			easyAntConfiguration.getListeners().addElement(args[pos + 1]);
+			pos++;
+		} catch (ArrayIndexOutOfBoundsException aioobe) {
+			String msg = "You must specify a classname when "
+					+ "using the -listener argument";
+			throw new BuildException(msg);
+		}
+		return pos;
+	}
+
+	/** Handler -D argument */
+	private int handleArgDefine(String[] args, int argPos) {
+		/*
+		 * Interestingly enough, we get to here when a user uses -Dname=value.
+		 * However, in some cases, the OS goes ahead and parses this out to args
+		 * {"-Dname", "value"} so instead of parsing on "=", we just make the
+		 * "-D" characters go away and skip one argument forward.
+		 * 
+		 * I don't know how to predict when the JDK is going to help or not, so
+		 * we simply look for the equals sign.
+		 */
+		String arg = args[argPos];
+		String name = arg.substring(2, arg.length());
+		String value = null;
+		int posEq = name.indexOf("=");
+		if (posEq > 0) {
+			value = name.substring(posEq + 1);
+			name = name.substring(0, posEq);
+		} else if (argPos < args.length - 1) {
+			value = args[++argPos];
+		} else {
+			throw new BuildException("Missing value for property " + name);
+		}
+		easyAntConfiguration.getDefinedProps().put(name, value);
+		return argPos;
+	}
+
+	/** Handle the -logger argument. */
+	private int handleArgLogger(String[] args, int pos) {
+		if (easyAntConfiguration.getLoggerClassname() != null) {
+			throw new BuildException("Only one logger class may be specified.");
+		}
+		try {
+			easyAntConfiguration.setLoggerClassname(args[++pos]);
+		} catch (ArrayIndexOutOfBoundsException aioobe) {
+			throw new BuildException(
+					"You must specify a classname when using the -logger argument");
+		}
+		return pos;
+	}
+
+	/** Handle the -inputhandler argument. */
+	private int handleArgInputHandler(String[] args, int pos) {
+		if (easyAntConfiguration.getInputHandlerClassname() != null) {
+			throw new BuildException("Only one input handler class may "
+					+ "be specified.");
+		}
+		try {
+			easyAntConfiguration.setInputHandlerClassname(args[++pos]);
+		} catch (ArrayIndexOutOfBoundsException aioobe) {
+			throw new BuildException("You must specify a classname when"
+					+ " using the -inputhandler" + " argument");
+		}
+		return pos;
+	}
+
+	/** Handle the -propertyfile argument. */
+	private int handleArgPropertyFile(String[] args, int pos) {
+		try {
+			propertyFiles.addElement(args[++pos]);
+		} catch (ArrayIndexOutOfBoundsException aioobe) {
+			String msg = "You must specify a property filename when "
+					+ "using the -propertyfile argument";
+			throw new BuildException(msg);
+		}
+		return pos;
+	}
+
+	/** Handle the -nice argument. */
+	private int handleArgNice(String[] args, int pos) {
+		try {
+			easyAntConfiguration.setThreadPriority(Integer.decode(args[++pos]));
+		} catch (ArrayIndexOutOfBoundsException aioobe) {
+			throw new BuildException("You must supply a niceness value (1-10)"
+					+ " after the -nice option");
+		} catch (NumberFormatException e) {
+			throw new BuildException("Unrecognized niceness value: "
+					+ args[pos]);
+		}
+
+		if (easyAntConfiguration.getThreadPriority().intValue() < Thread.MIN_PRIORITY
+				|| easyAntConfiguration.getThreadPriority().intValue() > Thread.MAX_PRIORITY) {
+			throw new BuildException("Niceness value is out of the range 1-10");
+		}
+		return pos;
+	}
+
+	// --------------------------------------------------------
+	// other methods
+	// --------------------------------------------------------
+
+	/** Load the property files specified by -propertyfile */
+	private void loadPropertyFiles() {
+		for (int propertyFileIndex = 0; propertyFileIndex < propertyFiles
+				.size(); propertyFileIndex++) {
+			String filename = (String) propertyFiles
+					.elementAt(propertyFileIndex);
+			Properties props = new Properties();
+			FileInputStream fis = null;
+			try {
+				fis = new FileInputStream(filename);
+				props.load(fis);
+			} catch (IOException e) {
+				System.out.println("Could not load property file " + filename
+						+ ": " + e.getMessage());
+			} finally {
+				FileUtils.close(fis);
+			}
+
+			// ensure that -D properties take precedence
+			Enumeration propertyNames = props.propertyNames();
+			while (propertyNames.hasMoreElements()) {
+				String name = (String) propertyNames.nextElement();
+				if (easyAntConfiguration.getDefinedProps().getProperty(name) == null) {
+					easyAntConfiguration.getDefinedProps().put(name,
+							props.getProperty(name));
+				}
+			}
+		}
+	}
+
+	/**
+	 * Executes the build. If the constructor for this instance failed (e.g.
+	 * returned after issuing a warning), this method returns immediately.
+	 * 
+	 * @param coreLoader
+	 *            The classloader to use to find core classes. May be
+	 *            <code>null</code>, in which case the system classloader is
+	 *            used.
+	 * 
+	 * @exception BuildException
+	 *                if the build fails
+	 */
+	private void runBuild(ClassLoader coreLoader) throws BuildException {
+		Project project = new Project();
+		if (!readyToRun) {
+			return;
+		}
+		if (projectHelp) {
+			displayProjectHelp();
+		} else if(projectMan) {
+			EasyAntEngine.configureAndInitProject(project, easyAntConfiguration);
+			File moduleDescriptor =new File(project.getProperty(EasyAntMagicNames.EASYANT_FILE));
+			if (moduleDescriptor.exists()) {
+				man.setContext(project, moduleDescriptor);
+				man.execute();
+			} else {
+				project.log("Can't print project manual, there is no module descriptor available.");
+			}
+		} else {
+			EasyAntEngine.runBuild(easyAntConfiguration);
+		}
+
+	}
+
+	/**
+	 * Prints the description of a project (if there is one) to
+	 * <code>System.out</code>.
+	 * 
+	 * @param project
+	 *            The project to display a description of. Must not be
+	 *            <code>null</code>.
+	 */
+	protected void printDescription(Project project) {
+		if (project.getDescription() != null) {
+			project.log(project.getDescription());
+		}
+	}
+
+	/**
+	 * Targets in imported files with a project name and not overloaded by the
+	 * main build file will be in the target map twice. This method removes the
+	 * duplicate target.
+	 * 
+	 * @param targets
+	 *            the targets to filter.
+	 * @return the filtered targets.
+	 */
+	private static Map removeDuplicateTargets(Map targets) {
+		Map locationMap = new HashMap();
+		for (Iterator i = targets.entrySet().iterator(); i.hasNext();) {
+			Map.Entry entry = (Map.Entry) i.next();
+			String name = (String) entry.getKey();
+			Target target = (Target) entry.getValue();
+			Target otherTarget = (Target) locationMap.get(target.getLocation());
+			// Place this entry in the location map if
+			// a) location is not in the map
+			// b) location is in map, but it's name is longer
+			// (an imported target will have a name. prefix)
+			if (otherTarget == null
+					|| otherTarget.getName().length() > name.length()) {
+				locationMap.put(target.getLocation(), target); // Smallest name
+				// wins
+			}
+		}
+		Map ret = new HashMap();
+		for (Iterator i = locationMap.values().iterator(); i.hasNext();) {
+			Target target = (Target) i.next();
+			ret.put(target.getName(), target);
+		}
+		return ret;
+	}
+
+	/**
+	 * Searches for the correct place to insert a name into a list so as to keep
+	 * the list sorted alphabetically.
+	 * 
+	 * @param names
+	 *            The current list of names. Must not be <code>null</code>.
+	 * @param name
+	 *            The name to find a place for. Must not be <code>null</code>.
+	 * 
+	 * @return the correct place in the list for the given name
+	 */
+	private static int findTargetPosition(Vector names, String name) {
+		int res = names.size();
+		for (int i = 0; i < names.size() && res == names.size(); i++) {
+			if (name.compareTo((String) names.elementAt(i)) < 0) {
+				res = i;
+			}
+		}
+		return res;
+	}
+
+	/**
+	 * Writes a formatted list of target names to <code>System.out</code> with
+	 * an optional description.
+	 * 
+	 * 
+	 * @param project
+	 *            the project instance.
+	 * @param names
+	 *            The names to be printed. Must not be <code>null</code>.
+	 * @param descriptions
+	 *            The associated target descriptions. May be <code>null</code>,
+	 *            in which case no descriptions are displayed. If non-
+	 *            <code>null</code>, this should have as many elements as
+	 *            <code>names</code>.
+	 * @param heading
+	 *            The heading to display. Should not be <code>null</code>.
+	 * @param maxlen
+	 *            The maximum length of the names of the targets. If
+	 *            descriptions are given, they are padded to this position so
+	 *            they line up (so long as the names really <i>are</i> shorter
+	 *            than this).
+	 */
+	private static void printTargets(Project project, Vector names,
+			Vector descriptions, String heading, int maxlen) {
+		// now, start printing the targets and their descriptions
+		String lSep = System.getProperty("line.separator");
+		// got a bit annoyed that I couldn't find a pad function
+		String spaces = "    ";
+		while (spaces.length() <= maxlen) {
+			spaces += spaces;
+		}
+		StringBuffer msg = new StringBuffer();
+		msg.append(heading + lSep + lSep);
+		for (int i = 0; i < names.size(); i++) {
+			msg.append(" ");
+			msg.append(names.elementAt(i));
+			if (descriptions != null) {
+				msg.append(spaces.substring(0, maxlen
+						- ((String) names.elementAt(i)).length() + 2));
+				msg.append(descriptions.elementAt(i));
+			}
+			msg.append(lSep);
+		}
+		project.log(msg.toString(), Project.MSG_WARN);
+	}
+
+	/**
+	 * Prints a list of all targets in the specified project to
+	 * <code>System.out</code>, optionally including subtargets.
+	 * 
+	 * @param project
+	 *            The project to display a description of. Must not be
+	 *            <code>null</code>.
+	 * @param printSubTargets
+	 *            Whether or not subtarget names should also be printed.
+	 */
+	protected static void printTargets(Project project, boolean printSubTargets) {
+		// find the target with the longest name
+		int maxLength = 0;
+		Map ptargets = removeDuplicateTargets(project.getTargets());
+		String targetName;
+		String targetDescription;
+		Target currentTarget;
+		// split the targets in top-level and sub-targets depending
+		// on the presence of a description
+		Vector topNames = new Vector();
+		Vector topDescriptions = new Vector();
+		Vector subNames = new Vector();
+
+		Vector phases = new Vector();
+		Vector phasesDescriptions = new Vector();
+
+		for (Iterator i = ptargets.values().iterator(); i.hasNext();) {
+			currentTarget = (Target) i.next();
+			targetName = currentTarget.getName();
+			if (targetName.equals("")) {
+				continue;
+			}
+			targetDescription = currentTarget.getDescription();
+			// maintain a sorted list of targets
+			if (targetDescription == null) {
+				int pos = findTargetPosition(subNames, targetName);
+				subNames.insertElementAt(targetName, pos);
+			} else {
+				if (currentTarget instanceof Phase) {
+					int pos = findTargetPosition(phases, targetName);
+					phases.insertElementAt(targetName, pos);
+					phasesDescriptions.insertElementAt(targetDescription, pos);
+				} else {
+					int pos = findTargetPosition(topNames, targetName);
+					topNames.insertElementAt(targetName, pos);
+					topDescriptions.insertElementAt(targetDescription, pos);
+
+				}
+				if (targetName.length() > maxLength) {
+					maxLength = targetName.length();
+				}
+			}
+		}
+
+		printTargets(project, phases, phasesDescriptions, "Main phases:",
+				maxLength);
+		printTargets(project, topNames, topDescriptions, "Main targets:",
+				maxLength);
+		// if there were no main targets, we list all subtargets
+		// as it means nothing has a description
+		if (topNames.size() == 0) {
+			printSubTargets = true;
+		}
+		if (printSubTargets) {
+			printTargets(project, subNames, null, "Other targets:", 0);
+		}
+
+		String defaultTarget = project.getDefaultTarget();
+		if (defaultTarget != null && !"".equals(defaultTarget)) {
+			// shouldn't need to check but...
+			project.log("Default target: " + defaultTarget);
+		}
+	}
+
+	private void displayProjectHelp() {
+		final Project project = new Project();
+		Throwable error = null;
+
+		try {
+
+			PrintStream savedErr = System.err;
+			PrintStream savedOut = System.out;
+			InputStream savedIn = System.in;
+
+			// use a system manager that prevents from System.exit()
+			SecurityManager oldsm = null;
+			oldsm = System.getSecurityManager();
+
+			// SecurityManager can not be installed here for backwards
+			// compatibility reasons (PD). Needs to be loaded prior to
+			// ant class if we are going to implement it.
+			// System.setSecurityManager(new NoExitSecurityManager());
+			try {
+				if (easyAntConfiguration.isAllowInput()) {
+					project.setDefaultInputStream(System.in);
+				}
+				System.setIn(new DemuxInputStream(project));
+				System.setOut(new PrintStream(new DemuxOutputStream(project,
+						false)));
+				System.setErr(new PrintStream(new DemuxOutputStream(project,
+						true)));
+				EasyAntEngine.configureAndInitProject(project, easyAntConfiguration);
+				printDescription(project);
+				printTargets(project,
+						easyAntConfiguration.getMsgOutputLevel() > Project.MSG_INFO);
+			} finally {
+				// put back the original security manager
+				// The following will never eval to true. (PD)
+				if (oldsm != null) {
+					System.setSecurityManager(oldsm);
+				}
+
+				System.setOut(savedOut);
+				System.setErr(savedErr);
+				System.setIn(savedIn);
+			}
+		} catch (RuntimeException exc) {
+			error = exc;
+			throw exc;
+		} catch (Error e) {
+			error = e;
+			throw e;
+		} finally {
+			if (error != null) {
+				project.log(error.toString(), Project.MSG_ERR);
+			}
+		}
+	}
+	
+	/**
+	 * Prints the usage information for this class to <code>System.out</code>.
+	 */
+	private static void printUsage() {
+		String lSep = System.getProperty("line.separator");
+		StringBuffer msg = new StringBuffer();
+		msg.append("easyant [options] [target [target2 [target3] ...]]" + lSep);
+		msg.append("Options: " + lSep);
+		msg.append("  -help, -h              print this message" + lSep);
+		msg.append("  -projecthelp, -p       print project help information"
+				+ lSep);
+		msg
+				.append("  -version               print the version information and exit"
+						+ lSep);
+		msg
+				.append("  -diagnostics           print information that might be helpful to"
+						+ lSep);
+		msg.append("                         diagnose or report problems."
+				+ lSep);
+		msg
+				.append("  -showMemoryDetails     print memory details (used/free/total)"
+						+ lSep);
+		msg.append("  -quiet, -q             be extra quiet" + lSep);
+		msg.append("  -verbose, -v           be extra verbose" + lSep);
+		msg.append("  -debug, -d             print debugging information"
+				+ lSep);
+		msg
+				.append("  -emacs, -e             produce logging information without adornments"
+						+ lSep);
+		msg
+				.append("  -lib <path>            specifies a path to search for jars and classes"
+						+ lSep);
+		msg.append("  -logfile <file>        use given file for log" + lSep);
+		msg.append("    -l     <file>                ''" + lSep);
+		msg
+				.append("  -logger <classname>    the class which is to perform logging"
+						+ lSep);
+		msg
+				.append("  -listener <classname>  add an instance of class as a project listener"
+						+ lSep);
+		msg.append("  -noinput               do not allow interactive input"
+				+ lSep);
+		msg.append("  -buildmodule <file>    use given buildmodule" + lSep);
+		msg.append("    -file    <file>              ''" + lSep);
+		msg.append("    -f       <file>              ''" + lSep);
+		msg.append("  -listTargets           Lists all targets available"+lSep);
+		msg.append("  -listTargets <arg>     Lists all targets associated with specified phase / plugin as argument"+lSep);
+		msg.append("  -listPhases            Lists all phases available"+lSep);
+		msg.append("  -listPlugins           Lists all plugins / modules imported by specified build module"+lSep);
+		msg.append("  -listProps <plugin>    Lists all properties available in the specified imported module"+lSep);
+		msg.append("  -describe <arg>        Describes the phase / target / property specified by the argument"+lSep);
+		msg.append("  -buildconf <confs>     specify build configurations (profiles)"+lSep);
+		msg.append("    -C  <confs>                  ''"+lSep);
+		msg.append("  -buildfile <file>      use given buildfile" + lSep);
+		msg.append("  -config-file <file>    use given easyant configuration"
+				+ lSep);
+		msg.append("  -D<property>=<value>   use value for given property"
+				+ lSep);
+		msg
+				.append("  -keep-going, -k        execute all targets that do not depend"
+						+ lSep);
+		msg.append("                         on failed target(s)" + lSep);
+		msg
+				.append("  -propertyfile <name>   load all properties from file with -D"
+						+ lSep);
+		msg.append("                         properties taking precedence"
+				+ lSep);
+		msg
+				.append("  -inputhandler <class>  the class which will handle input requests"
+						+ lSep);
+		msg
+				.append("  -find <file>           (s)earch for buildfile towards the root of"
+						+ lSep);
+		msg.append("    -s  <file>           the filesystem and use it" + lSep);
+		msg
+				.append("  -nice  number          A niceness value for the main thread:"
+						+ lSep
+						+ "                         1 (lowest) to 10 (highest); 5 is the default"
+						+ lSep);
+		msg
+				.append("  -nouserlib             Run ant without using the jar files from"
+						+ lSep
+						+ "                         ${user.home}/.ant/lib"
+						+ lSep);
+		msg.append("  -noclasspath           Run ant without using CLASSPATH"
+				+ lSep);
+		msg
+				.append("  -autoproxy             Java1.5+: use the OS proxy settings"
+						+ lSep);
+		msg
+				.append("  -main <class>          override Ant's normal entry point");
+		System.out.println(msg.toString());
+	}
+
+	/**
+	 * Prints the EasyAnt version information to <code>System.out</code>.
+	 * 
+	 * @exception BuildException
+	 *                if the version information is unavailable
+	 */
+	private static void printVersion(int logLevel) throws BuildException {
+		System.out.println(EasyAntEngine.getEasyAntVersion());
+		System.out.println(getAntVersion());
+	}
+
+	/**
+	 * Cache of the Ant version information when it has been loaded.
+	 */
+	private static String antVersion = null;
+
+	/**
+	 * Returns the Ant version information, if available. Once the information
+	 * has been loaded once, it's cached and returned from the cache on future
+	 * calls.
+	 * 
+	 * @return the Ant version information as a String (always non-
+	 *         <code>null</code>)
+	 * 
+	 * @exception BuildException
+	 *                if the version information is unavailable
+	 */
+	public static synchronized String getAntVersion() throws BuildException {
+		if (antVersion == null) {
+			try {
+				Properties props = new Properties();
+				InputStream in = Main.class
+						.getResourceAsStream("/org/apache/tools/ant/version.txt");
+				props.load(in);
+				in.close();
+
+				StringBuffer msg = new StringBuffer();
+				msg.append("Apache Ant version ");
+				msg.append(props.getProperty("VERSION"));
+				msg.append(" compiled on ");
+				msg.append(props.getProperty("DATE"));
+				antVersion = msg.toString();
+			} catch (IOException ioe) {
+				throw new BuildException(
+						"Could not load the version information:"
+								+ ioe.getMessage());
+			} catch (NullPointerException npe) {
+				throw new BuildException(
+						"Could not load the version information.");
+			}
+		}
+		return antVersion;
+	}
+
+}

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMain.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMain.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMain.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/EasyAntMain.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/EasyAntProjectHelper.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/EasyAntProjectHelper.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/EasyAntProjectHelper.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/EasyAntProjectHelper.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,302 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.core.ant;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.ExtensionPoint;
+import org.apache.tools.ant.Location;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.Target;
+import org.apache.tools.ant.helper.AntXMLContext;
+import org.apache.tools.ant.helper.ProjectHelper2;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXParseException;
+
+/**
+ * This class is the custom project helper used by easyant introducing support
+ * for phase concept
+ * 
+ */
+public class EasyAntProjectHelper extends ProjectHelper2 {
+
+	public EasyAntProjectHelper() {
+		super();
+		setProjectHandler(new EasyAntProjectHandler());
+		setTargetHandler(new EasyAntTargetHandler());
+	}
+
+	/**
+	 * Handler for the top level "project" element.
+	 */
+	public static class EasyAntProjectHandler extends ProjectHandler {
+
+		/**
+		 * Handles the start of a top-level element within the project. An
+		 * appropriate handler is created and initialised with the details of
+		 * the element.
+		 * 
+		 * @param uri
+		 *            The namespace URI for this element.
+		 * @param name
+		 *            The name of the element being started. Will not be
+		 *            <code>null</code>.
+		 * @param qname
+		 *            The qualified name for this element.
+		 * @param attrs
+		 *            Attributes of the element being started. Will not be
+		 *            <code>null</code>.
+		 * @param context
+		 *            The context for this element.
+		 * @return a target or an element handler.
+		 * 
+		 * @exception org.xml.sax.SAXParseException
+		 *                if the tag given is not <code>"taskdef"</code>,
+		 *                <code>"typedef"</code>, <code>"property"</code>,
+		 *                <code>"target"</code>, <code>"phase"</code> or a data
+		 *                type definition
+		 */
+		public AntHandler onStartChild(String uri, String name, String qname,
+				Attributes attrs, AntXMLContext context)
+				throws SAXParseException {
+
+			return (name.equals("target") || name.equals("phase") || name
+					.equals("extension-point"))
+					&& (uri.equals("") || uri.equals(ANT_CORE_URI)) ? getTargetHandler()
+					: getElementHandler();
+		}
+	}
+
+	/**
+	 * Handler for "target" and "phase" elements.
+	 */
+	public static class EasyAntTargetHandler extends TargetHandler {
+
+		/**
+		 * Initialisation routine called after handler creation with the element
+		 * name and attributes. The attributes which this handler can deal with
+		 * are: <code>"name"</code>, <code>"depends"</code>, <code>"if"</code>,
+		 * <code>"unless"</code>, <code>"id"</code> and
+		 * <code>"description"</code>.
+		 * 
+		 * @param uri
+		 *            The namespace URI for this element.
+		 * @param tag
+		 *            Name of the element which caused this handler to be
+		 *            created. Should not be <code>null</code>. Ignored in this
+		 *            implementation.
+		 * @param qname
+		 *            The qualified name for this element.
+		 * @param attrs
+		 *            Attributes of the element which caused this handler to be
+		 *            created. Must not be <code>null</code>.
+		 * @param context
+		 *            The current context.
+		 * 
+		 * @exception SAXParseException
+		 *                if an unexpected attribute is encountered or if the
+		 *                <code>"name"</code> attribute is missing.
+		 */
+		public void onStartElement(String uri, String tag, String qname,
+				Attributes attrs, AntXMLContext context)
+				throws SAXParseException {
+
+			String name = null;
+			String depends = "";
+			String extensionPoint = null;
+			String phase = null;
+
+			Project project = context.getProject();
+
+			Target target;
+			if ("extension-point".equals(tag)) {
+				target = new ExtensionPoint();
+			} else if ("phase".equals(tag)) {
+				target = new Phase();
+			} else {
+				target = new Target();
+			}
+
+			target.setProject(project);
+			target.setLocation(new Location(context.getLocator()));
+			context.addTarget(target);
+
+			for (int i = 0; i < attrs.getLength(); i++) {
+				String attrUri = attrs.getURI(i);
+				if (attrUri != null && !attrUri.equals("")
+						&& !attrUri.equals(uri)) {
+					continue; // Ignore attributes from unknown uris
+				}
+				String key = attrs.getLocalName(i);
+				String value = attrs.getValue(i);
+
+				if (key.equals("name")) {
+					name = value;
+					if ("".equals(name)) {
+						throw new BuildException("name attribute must "
+								+ "not be empty");
+					}
+				} else if (key.equals("depends")) {
+					depends = value;
+				} else if (key.equals("if")) {
+					target.setIf(value);
+				} else if (key.equals("unless")) {
+					target.setUnless(value);
+				} else if (key.equals("id")) {
+					if (value != null && !value.equals("")) {
+						context.getProject().addReference(value, target);
+					}
+				} else if (key.equals("description")) {
+					target.setDescription(value);
+				} else if (key.equals("extensionOf")) {
+					extensionPoint = value;
+				} else if (key.equals("phase")) {
+					phase = value;
+				} else {
+					throw new SAXParseException("Unexpected attribute \"" + key
+							+ "\"", context.getLocator());
+				}
+			}
+
+			if (name == null) {
+				throw new SAXParseException(
+						"target element appears without a name attribute",
+						context.getLocator());
+			}
+
+			boolean isPhase = target instanceof Phase;
+
+			String prefix = null;
+			boolean isInIncludeMode = context.isIgnoringProjectTag()
+					&& isInIncludeMode();
+			String sep = getCurrentPrefixSeparator();
+
+			if (isInIncludeMode && !isPhase) {
+				prefix = getTargetPrefix(context);
+				if (prefix == null) {
+					throw new BuildException("can't include build file "
+							+ context.getBuildFile()
+							+ ", no as attribute has been given"
+							+ " and the project tag doesn't"
+							+ " specify a name attribute");
+				}
+				name = prefix + sep + name;
+			}
+
+			// Check if this target is in the current build file
+			if (context.getCurrentTargets().get(name) != null) {
+				throw new BuildException("Duplicate target '" + name + "'",
+						target.getLocation());
+			}
+			Hashtable projectTargets = project.getTargets();
+			boolean usedTarget = false;
+			// If the name has not already been defined define it
+			if (projectTargets.containsKey(name)) {
+				project.log(
+						"Already defined in main or a previous import, ignore "
+								+ name, Project.MSG_VERBOSE);
+			} else {
+				target.setName(name);
+				context.getCurrentTargets().put(name, target);
+				project.addOrReplaceTarget(name, target);
+				usedTarget = true;
+			}
+
+			if (depends.length() > 0) {
+				if (!isInIncludeMode) {
+					target.setDepends(depends);
+				} else {
+					for (Iterator iter = Target.parseDepends(depends, name,
+							"depends").iterator(); iter.hasNext();) {
+						String curTarget = (String) iter.next();
+						if (projectTargets.containsKey(curTarget) && (projectTargets.get(curTarget) instanceof Phase)) {
+							
+							target.addDependency(curTarget);
+						} else {
+							target.addDependency(prefix + sep + curTarget);
+						}
+					}
+				}
+			}
+			if (!isInIncludeMode && context.isIgnoringProjectTag()
+					&& (prefix = getTargetPrefix(context)) != null) {
+				// In an imported file (and not completely
+				// ignoring the project tag or having a preconfigured prefix)
+				String newName = prefix + sep + name;
+				Target newTarget = usedTarget ? new Target(target) : target;
+				newTarget.setName(newName);
+				context.getCurrentTargets().put(newName, newTarget);
+				project.addOrReplaceTarget(newName, newTarget);
+			}
+			if (extensionPoint != null) {
+				ProjectHelper helper = (ProjectHelper) context.getProject()
+						.getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
+				for (Iterator iter = Target.parseDepends(extensionPoint, name,
+						"extensionOf").iterator(); iter.hasNext();) {
+					String tgName = (String) iter.next();
+					if (isInIncludeMode()) {
+						tgName = prefix + sep + tgName;
+					}
+
+					// defer extensionpoint resolution until the full
+					// import stack has been processed
+					helper.getExtensionStack().add(
+							new String[] { tgName, name });
+				}
+			}
+			if (phase != null) {
+				if (!projectTargets.containsKey(phase)) {
+					throw new BuildException("can't add target " + name
+							+ " to phase " + phase + " because the phase"
+							+ " is unknown.");
+				}
+				Target t = (Target) projectTargets.get(phase);
+
+				if (!(t instanceof Phase)) {
+					throw new BuildException("referenced target " + phase
+							+ " is not a phase");
+				}
+				t.addDependency(name);
+			}
+
+		}
+
+		private String getTargetPrefix(AntXMLContext context) {
+			String configuredValue = getCurrentTargetPrefix();
+			if (configuredValue != null && configuredValue.length() == 0) {
+				configuredValue = null;
+			}
+			if (configuredValue != null) {
+				return configuredValue;
+			}
+
+			String projectName = context.getCurrentProjectName();
+			if ("".equals(projectName)) {
+				projectName = null;
+			}
+
+			return projectName;
+		}
+
+	}
+
+}

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/EasyAntProjectHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/EasyAntProjectHelper.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/EasyAntProjectHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/MetaBuildExecutor.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/MetaBuildExecutor.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/MetaBuildExecutor.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/MetaBuildExecutor.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,169 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.core.ant;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.easyant.core.EasyAntConstants;
+import org.apache.easyant.core.EasyAntMagicNames;
+import org.apache.easyant.core.ivy.IvyInstanceHelper;
+import org.apache.easyant.tasks.SubModule;
+import org.apache.easyant.tasks.SubModule.TargetList;
+import org.apache.ivy.ant.IvyAntSettings;
+import org.apache.ivy.ant.IvyBuildList;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.MDArtifact;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
+import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
+import org.apache.ivy.plugins.repository.url.URLResource;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.helper.DefaultExecutor;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.selectors.FilenameSelector;
+
+/**
+ * Recursively executes build targets on sub-modules for a multi-module project.
+ */
+public class MetaBuildExecutor extends DefaultExecutor {
+
+	@Override
+	public void executeTargets(Project project, String[] targets)
+			throws BuildException {
+
+		// delegate to the ivy:buildlist task to compute an ordered list of
+		// submodules
+		FilenameSelector ivySelector = new FilenameSelector();
+		ivySelector.setProject(project);
+		ivySelector.setName("**/module.ivy");
+
+		FileSet ivyFiles = (FileSet) project.createDataType("fileset");
+		ivyFiles.setDir(project.getBaseDir());
+		ivyFiles.setExcludes("module.ivy"); // exclude the root module ivy.
+		ivyFiles.setIncludes(project.getProperty("submodule.dirs"));
+		ivyFiles.addFilename(ivySelector);
+
+		IvyBuildList buildList = new IvyBuildList();
+		buildList.setTaskName("meta:buildlist");
+		buildList.setProject(project);
+		buildList.setReference("build-path");
+		buildList.setIvyfilepath("module.ivy");
+		buildList.setSettingsRef(IvyInstanceHelper
+				.buildProjectIvyReference(project));
+		buildList.addFileset(ivyFiles);
+
+		buildList.execute();
+
+		// publish the parent module descriptor into the build-scoped
+		// repository, so that it can
+		// be used by submodules if needed
+		File moduleFile = new File(project.getBaseDir(), "module.ivy");
+		String buildRepo = project
+				.getProperty(EasyAntMagicNames.EASYANT_BUILD_REPOSITORY);
+		if (moduleFile.isFile() && buildRepo != null) {
+
+			project.log("Publishing module descriptor " + moduleFile.getPath()
+					+ " to build repository '" + buildRepo + "'");
+
+			IvyAntSettings projectSettings = IvyInstanceHelper
+					.getProjectIvyAntSettings(project);
+			IvySettings ivy = projectSettings.getConfiguredIvyInstance(
+					buildList).getSettings();
+
+			try {
+				URL ivyUrl = moduleFile.toURL();
+				ModuleDescriptorParser mdp = ModuleDescriptorParserRegistry
+						.getInstance().getParser(
+								new URLResource(moduleFile.toURL()));
+				ModuleDescriptor descriptor = mdp.parseDescriptor(ivy, ivyUrl,
+						true);
+				Artifact artifact = MDArtifact.newIvyArtifact(descriptor);
+				ivy.getResolver(buildRepo).publish(artifact, moduleFile, true);
+			} catch (Exception ioe) {
+				throw new BuildException("Error publishing meta-module file "
+						+ moduleFile.getAbsolutePath() + " to " + buildRepo,
+						ioe);
+			}
+
+		}
+
+		// hook for pre-module-targets
+		String preModuleTargets = project
+				.getProperty(EasyAntMagicNames.PRE_MODULE_TARGETS);
+		if (preModuleTargets == null) {
+			preModuleTargets = EasyAntConstants.DEFAULT_PRE_MODULE_TARGETS;
+		}
+
+		List<String> postTargetsToRun = new ArrayList<String>();
+		List<String> preTargetsToRun = new ArrayList<String>();
+		List<String> preModuleTargetList = Arrays.asList(preModuleTargets
+				.split(","));
+		for (int i = 0; i < targets.length; i++) {
+			if (preModuleTargetList.contains(targets[i])) {
+				// fill a list of targets to run BEFORE subproject delegation
+				preTargetsToRun.add(targets[i]);
+			} else {
+				// fill a list of target to run AFTER subproject delagation
+				// make sure target exists
+				if (project.getTargets().get(targets[i]) != null) {
+					postTargetsToRun.add(targets[i]);
+				} else {
+					project.log("Skipping undefined target '" + targets[i] + "'",
+							Project.MSG_VERBOSE);
+				}
+
+			}
+		}
+
+		// now call the default executor to include any extra
+		// targets defined in the root module.ant
+		super.executeTargets(project, preTargetsToRun.toArray(new String[] {}));
+
+		// delegate to the ea:submodule task to execute the list of targets on
+		// all modules in the build list
+		SubModule subModule = new SubModule();
+		subModule.setTaskName("meta:submodule");
+		subModule.setProject(project);
+
+		Boolean useBuildRepository = project
+				.getProperty(EasyAntMagicNames.USE_BUILD_REPOSITORY) != null ? Boolean
+				.parseBoolean(project
+						.getProperty(EasyAntMagicNames.USE_BUILD_REPOSITORY))
+				: true;
+		subModule.setUseBuildRepository(useBuildRepository);
+
+		subModule.setBuildpathRef(new Reference(project, "build-path"));
+		subModule.setTargets(new TargetList(targets));
+		subModule.execute();
+
+		// now call the default executor to include any extra targets defined in
+		// the root module.ant
+		super
+				.executeTargets(project, postTargetsToRun
+						.toArray(new String[] {}));
+	}
+
+}

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/MetaBuildExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/MetaBuildExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/core/ant/MetaBuildExecutor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain