incubator-easyant-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jlboud...@apache.org
Subject svn commit: r1389079 [2/2] - in /incubator/easyant/core/trunk/src/main/java/org/apache/easyant: core/ core/ant/ core/parser/ core/report/ core/services/impl/ man/ tasks/ tasks/findclasspath/
Date Sun, 23 Sep 2012 15:28:04 GMT
Modified: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SubModule.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SubModule.java?rev=1389079&r1=1389078&r2=1389079&view=diff
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SubModule.java (original)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SubModule.java Sun Sep 23 15:28:03 2012
@@ -57,662 +57,603 @@ import org.apache.tools.ant.util.StringU
  */
 public class SubModule extends Task {
 
-	private boolean failOnError = true;
-	private boolean verbose = false;
-	private String moduleFile = EasyAntConstants.DEFAULT_BUILD_MODULE;
-
-	private Path buildpath;
-	private TargetList targets = null;
-	private boolean useBuildRepository = false;
-	private boolean overwrite = true;
-
-	private boolean inheritRefs = false;
-	private Vector properties = new Vector();
-	private Vector references = new Vector();
-	private Vector propertySets = new Vector();
-
-	public void execute() throws BuildException {
-		if (buildpath == null) {
-			throw new BuildException("No buildpath specified");
-		}
-		final String[] filenames = buildpath.list();
-		final int count = filenames.length;
-		if (count < 1) {
-			log("No sub-builds to iterate on", Project.MSG_WARN);
-			return;
-		}
-
-		ProjectUtils.replaceMainLogger(getProject(), new MultiModuleLogger());
-
-		BuildException buildException = null;
-		for (int i = 0; i < count; ++i) {
-			File file = null;
-			String subdirPath = null;
-			Throwable thrownException = null;
-			try {
-				File directory = null;
-				file = new File(filenames[i]);
-				if (file.isDirectory()) {
-					if (verbose) {
-						subdirPath = file.getPath();
-						log("Entering directory: " + subdirPath + "\n",
-								Project.MSG_INFO);
-					}
-					file = new File(file, moduleFile);
-				}
-				directory = file.getParentFile();
-				execute(file, directory);
-				if (verbose && subdirPath != null) {
-					log("Leaving directory: " + subdirPath + "\n",
-							Project.MSG_INFO);
-				}
-			} catch (RuntimeException ex) {
-				if (!(getProject().isKeepGoingMode())) {
-					if (verbose && subdirPath != null) {
-						log("Leaving directory: " + subdirPath + "\n",
-								Project.MSG_INFO);
-					}
-					throw ex; // throw further
-				}
-				thrownException = ex;
-			} catch (Throwable ex) {
-				if (!(getProject().isKeepGoingMode())) {
-					if (verbose && subdirPath != null) {
-						log("Leaving directory: " + subdirPath + "\n",
-								Project.MSG_INFO);
-					}
-					throw new BuildException(ex);
-				}
-				thrownException = ex;
-			}
-			if (thrownException != null) {
-				if (thrownException instanceof BuildException) {
-					log("File '" + file + "' failed with message '"
-							+ thrownException.getMessage() + "'.",
-							Project.MSG_ERR);
-					// only the first build exception is reported
-					if (buildException == null) {
-						buildException = (BuildException) thrownException;
-					}
-				} else {
-					log("Target '" + file + "' failed with message '"
-							+ thrownException.getMessage() + "'.",
-							Project.MSG_ERR);
-					thrownException.printStackTrace(System.err);
-					if (buildException == null) {
-						buildException = new BuildException(thrownException);
-					}
-				}
-				if (verbose && subdirPath != null) {
-					log("Leaving directory: " + subdirPath + "\n",
-							Project.MSG_INFO);
-				}
-			}
-		}
-		// check if one of the builds failed in keep going mode
-		if (buildException != null) {
-			throw buildException;
-		}
-	}
-
-	/**
-	 * Runs the given target on the provided build file.
-	 * 
-	 * @param file
-	 *            the build file to execute
-	 * @param directory
-	 *            the directory of the current iteration
-	 * @throws BuildException
-	 *             is the file cannot be found, read, is a directory, or the
-	 *             target called failed, but only if <code>failOnError</code> is
-	 *             <code>true</code>. Otherwise, a warning log message is simply
-	 *             output.
-	 */
-	private void execute(File file, File directory) throws BuildException {
-		if (!file.exists() || file.isDirectory() || !file.canRead()) {
-			String msg = "Invalid file: " + file;
-			if (failOnError) {
-				throw new BuildException(msg);
-			}
-			log(msg, Project.MSG_WARN);
-			return;
-		}
-
-		Project subModule = configureSubModule(file, directory);
-		subModule.fireSubBuildStarted();
-
-		try {
-			// buildFile should be in the same directory of buildModule
-			File buildfile = new File(directory,
-					EasyAntConstants.DEFAULT_BUILD_FILE);
-			if (buildfile.exists()) {
-				subModule.setNewProperty(MagicNames.ANT_FILE,
-						buildfile.getAbsolutePath());
-			}
-			subModule.setNewProperty(EasyAntMagicNames.EASYANT_FILE,
-					file.getAbsolutePath());
-
-	        ProjectHelper helper = ProjectHelper.getProjectHelper();
-	        File mainscript = ProjectUtils.emulateMainScript(getProject());
-	        Location mainscriptLocation = new Location(mainscript.getAbsolutePath());
-	        helper.getImportStack().addElement(mainscript);
-	        subModule.addReference(ProjectHelper.PROJECTHELPER_REFERENCE, helper);
-
-			LoadModule lm = new LoadModule();
-			lm.setBuildModule(file);
-			lm.setBuildFile(buildfile);
-			lm.setTaskName(EasyAntConstants.EASYANT_TASK_NAME);
-			lm.setProject(subModule);
-			lm.setOwningTarget(ProjectUtils.createTopLevelTarget());
-			lm.setLocation(new Location(mainscript.toString()));
-			lm.setUseBuildRepository(useBuildRepository);
-			lm.execute();
-
-			filterTargets(subModule);
-			printExecutingTargetMsg(subModule);
-
-			if (targets != null && !targets.isEmpty()) {
-				subModule.executeTargets(targets);
-				if (useBuildRepository) {
-
-					File artifactsDir = subModule.resolveFile(subModule
-							.getProperty("target.artifacts"));
-					if (artifactsDir.isDirectory()) {
-
-						// this property set by LoadModule task when it
-						// configures the build repo
-						String resolver = subModule
-								.getProperty(EasyAntMagicNames.EASYANT_BUILD_REPOSITORY);
-
-						subModule.log("Publishing in build scoped repository",
-								Project.MSG_INFO);
-						// Publish on build scoped repository
-						IvyPublish ivyPublish = new IvyPublish();
-						ivyPublish.setSettingsRef(IvyInstanceHelper
-								.buildProjectIvyReference(subModule));
-						ivyPublish.setResolver(resolver);
-						// TODO: this should be more flexible!
-						ivyPublish
-								.setArtifactspattern("${target.artifacts}/[artifact](-[classifier]).[ext]");
-						// not all sub-build targets will generate ivy
-						// artifacts. we don't want to fail
-						// a successful build just because there's nothing to
-						// publish.
-						ivyPublish.setWarnonmissing(false);
-						ivyPublish.setHaltonmissing(false);
-						ivyPublish.setProject(subModule);
-						ivyPublish.setOwningTarget(getOwningTarget());
-						ivyPublish.setLocation(getLocation());
-						ivyPublish.setOverwrite(overwrite);
-						ivyPublish
-								.setTaskName("publish-buildscoped-repository");
-						ivyPublish.execute();
-					} else {
-						subModule.log("Skipping publish because "
-								+ artifactsDir.getPath()
-								+ " is not a directory", Project.MSG_VERBOSE);
-					}
-				}
-			} else {
-				subModule
-						.log("Skipping sub-project build because no matching targets were found",
-								Project.MSG_VERBOSE);
-			}
-			subModule.fireSubBuildFinished(null);
-		} catch (BuildException e) {
-			subModule.fireSubBuildFinished(e);
-			throw e;
-		} finally {
-			// add execution times for the current submodule to parent
-			// project references for access from MetaBuildExecutor
-			storeExecutionTimes(getProject(), subModule);
-		}
-
-	}
-
-	private Project configureSubModule(File file, File directory) {
-		Project subModule = getProject().createSubProject();
-		for (int i = 0; i < getProject().getBuildListeners().size(); i++) {
-			BuildListener buildListener = (BuildListener) getProject()
-					.getBuildListeners().elementAt(i);
-			subModule.addBuildListener(buildListener);
-		}
-		// explicitly add the execution timer to time
-		// sub builds
-		subModule.addBuildListener(new SubBuildExecutionTimer());
-		
-
-		// copy all User properties
-		addAlmostAll(getProject().getUserProperties(), subModule,
-				PropertyType.USER);
-
-		// copy easyantIvyInstance
-		IvyAntSettings ivyAntSettings = IvyInstanceHelper
-				.getEasyAntIvyAntSettings(getProject());
-		subModule.addReference(EasyAntMagicNames.EASYANT_IVY_INSTANCE,
-				ivyAntSettings);
-
-		// inherit meta.target directory, for shared build repository.
-		String metaTarget = getProject().getProperty("meta.target");
-		if (metaTarget != null) {
-			File metaDir = getProject().resolveFile(metaTarget);
-			subModule.setNewProperty("meta.target",
-					metaDir.getAbsolutePath());
-		}
-		
-		subModule.initProperties();
-		
-		//copy nested properties
-		Enumeration e = propertySets.elements();
-		while (e.hasMoreElements()) {
-			PropertySet ps = (PropertySet) e.nextElement();
-			addAlmostAll(ps.getProperties(), subModule, PropertyType.PLAIN);
-		}
-
-		overrideProperties(subModule);
-		addReferences(subModule);
-		
-		subModule.setName(file.getName());
-		subModule.setBaseDir(directory);
-		return subModule;
-	}
-
-	private void storeExecutionTimes(Project parent, Project child) {
-		List<ExecutionResult> allresults = (List<ExecutionResult>) parent
-				.getReference(SubBuildExecutionTimer.EXECUTION_TIMER_SUBBUILD_RESULTS);
-		if (allresults == null) {
-			allresults = new ArrayList<ExecutionResult>();
-			parent.addReference(
-					SubBuildExecutionTimer.EXECUTION_TIMER_SUBBUILD_RESULTS,
-					allresults);
-		}
-		List<ExecutionResult> childResults = (List<ExecutionResult>) child
-				.getReference(SubBuildExecutionTimer.EXECUTION_TIMER_SUBBUILD_RESULTS);
-		if (childResults != null)
-			allresults.addAll(childResults);
-	}
-
-	/**
-	 * Filter the active set of targets to only those defined in the given
-	 * project.
-	 */
-	private void filterTargets(Project subProject) {
-		Set<?> keys = subProject.getTargets().keySet();
-		for (Iterator<String> it = targets.iterator(); it.hasNext();) {
-			String target = it.next();
-			if (!keys.contains(target) && target.trim().length() > 0) {
-				subProject.log("Skipping undefined target '" + target + "'",
-						Project.MSG_VERBOSE);
-				it.remove();
-			}
-		}
-	}
-
-	/**
-	 * Print a message when executing the target
-	 * 
-	 * @param subProject
-	 *            a subproject where the log will be printed
-	 */
-	private void printExecutingTargetMsg(Project subProject) {
-		final String HEADER = "======================================================================";
-		StringBuilder sb = new StringBuilder();
-		sb.append(HEADER).append(StringUtils.LINE_SEP);
-		sb.append("Executing ").append(targets).append(" on ")
-				.append(subProject.getName());
-		sb.append(StringUtils.LINE_SEP).append(HEADER);
-		subProject.log(sb.toString());
-	}
-
-	/**
-	 * Copies all properties from the given table to the new project - omitting
-	 * those that have already been set in the new project as well as properties
-	 * named basedir or ant.file.
-	 * 
-	 * @param props
-	 *            properties <code>Hashtable</code> to copy to the new project.
-	 * @param the
-	 *            type of property to set (a plain Ant property, a user property
-	 *            or an inherited property).
-	 * @since Ant 1.8.0
-	 */
-	private void addAlmostAll(Hashtable<?, ?> props, Project subProject,
-			PropertyType type) {
-		Enumeration<?> e = props.keys();
-		while (e.hasMoreElements()) {
-			String key = e.nextElement().toString();
-			if (MagicNames.PROJECT_BASEDIR.equals(key)
-					|| MagicNames.ANT_FILE.equals(key)) {
-				// basedir and ant.file get special treatment in execute()
-				continue;
-			}
-
-			String value = props.get(key).toString();
-			if (type == PropertyType.PLAIN) {
-				// don't re-set user properties, avoid the warning message
-				if (subProject.getProperty(key) == null) {
-					// no user property
-					subProject.setNewProperty(key, value);
-				}
-			} else if (type == PropertyType.USER) {
-				subProject.setUserProperty(key, value);
-			} else if (type == PropertyType.INHERITED) {
-				subProject.setInheritedProperty(key, value);
-			}
-		}
-	}
-
-	private static final class PropertyType {
-		private PropertyType() {
-		}
-
-		private static final PropertyType PLAIN = new PropertyType();
-		private static final PropertyType INHERITED = new PropertyType();
-		private static final PropertyType USER = new PropertyType();
-	}
-
-	/**
-	 * The target to call on the different sub-builds. Set to "" to execute the
-	 * default target.
-	 * 
-	 * @param target
-	 *            the target
-	 *            <p>
-	 */
-	// REVISIT: Defaults to the target name that contains this task if not
-	// specified.
-	public void setTarget(String target) {
-		setTargets(new TargetList(target));
-	}
-
-	/**
-	 * The targets to call on the different sub-builds.
-	 * 
-	 * @param target
-	 *            a list of targets to execute
-	 */
-	public void setTargets(TargetList targets) {
-		this.targets = targets;
-	}
-
-	/**
-	 * Set the buildpath to be used to find sub-projects.
-	 * 
-	 * @param s
-	 *            an Ant Path object containing the buildpath.
-	 */
-	public void setBuildpath(Path s) {
-		getBuildpath().append(s);
-	}
-
-	/**
-	 * Gets the implicit build path, creating it if <code>null</code>.
-	 * 
-	 * @return the implicit build path.
-	 */
-	private Path getBuildpath() {
-		if (buildpath == null) {
-			buildpath = new Path(getProject());
-		}
-		return buildpath;
-	}
-
-	/**
-	 * Buildpath to use, by reference.
-	 * 
-	 * @param r
-	 *            a reference to an Ant Path object containing the buildpath.
-	 */
-	public void setBuildpathRef(Reference r) {
-		createBuildpath().setRefid(r);
-	}
-
-	/**
-	 * Creates a nested build path, and add it to the implicit build path.
-	 * 
-	 * @return the newly created nested build path.
-	 */
-	public Path createBuildpath() {
-		return getBuildpath().createPath();
-	}
-
-	/**
-	 * Enable/ disable verbose log messages showing when each sub-build path is
-	 * entered/ exited. The default value is "false".
-	 * 
-	 * @param on
-	 *            true to enable verbose mode, false otherwise (default).
-	 */
-	public void setVerbose(boolean on) {
-		this.verbose = on;
-	}
-
-	/**
-	 * Sets whether to fail with a build exception on error, or go on.
-	 * 
-	 * @param failOnError
-	 *            the new value for this boolean flag.
-	 */
-	public void setFailonerror(boolean failOnError) {
-		this.failOnError = failOnError;
-	}
-
-	/**
-	 * Sets whether a submodule should use build repository or not
-	 * 
-	 * @param useBuildRepository
-	 *            the new value for this boolean flag
-	 */
-	public void setUseBuildRepository(boolean useBuildRepository) {
-		this.useBuildRepository = useBuildRepository;
-	}
-
-	/**
-	 * Set whether publish operations for the
-	 * {@link #setUseBuildRepository(boolean) build-scoped repository} should
-	 * overwrite existing artifacts. Defaults to <code>true</code> if
-	 * unspecified.
-	 */
-	public void setOverwrite(boolean overwrite) {
-		this.overwrite = overwrite;
-	}
-
-	/**
-	 * Corresponds to <code>&lt;ant&gt;</code>'s <code>inheritrefs</code>
-	 * attribute.
-	 * 
-	 * @param b
-	 *            the new value for this boolean flag.
-	 */
-	public void setInheritrefs(boolean b) {
-		this.inheritRefs = b;
-	}
-
-	/**
-	 * Corresponds to <code>&lt;ant&gt;</code>'s nested
-	 * <code>&lt;property&gt;</code> element.
-	 * 
-	 * @param p
-	 *            the property to pass on explicitly to the sub-build.
-	 */
-	public void addProperty(Property p) {
-		properties.addElement(p);
-	}
-
-	/**
-	 * Corresponds to <code>&lt;ant&gt;</code>'s nested
-	 * <code>&lt;reference&gt;</code> element.
-	 * 
-	 * @param r
-	 *            the reference to pass on explicitly to the sub-build.
-	 */
-	public void addReference(Ant.Reference r) {
-		references.addElement(r);
-	}
-
-	/**
-	 * Corresponds to <code>&lt;ant&gt;</code>'s nested
-	 * <code>&lt;propertyset&gt;</code> element.
-	 * 
-	 * @param ps
-	 *            the propertset
-	 */
-	public void addPropertyset(PropertySet ps) {
-		propertySets.addElement(ps);
-	}
-
-	/**
-	 * Override the properties in the new project with the one explicitly
-	 * defined as nested elements here.
-	 * 
-	 * @param subproject a subproject
-	 * @throws BuildException
-	 *             under unknown circumstances.
-	 */
-	private void overrideProperties(Project subproject) throws BuildException {
-		// remove duplicate properties - last property wins
-		// Needed for backward compatibility
-		Set set = new HashSet();
-		for (int i = properties.size() - 1; i >= 0; --i) {
-			Property p = (Property) properties.get(i);
-			if (p.getName() != null && !p.getName().equals("")) {
-				if (set.contains(p.getName())) {
-					properties.remove(i);
-				} else {
-					set.add(p.getName());
-				}
-			}
-		}
-		Enumeration e = properties.elements();
-		while (e.hasMoreElements()) {
-			Property p = (Property) e.nextElement();
-			p.setProject(subproject);
-			p.execute();
-		}
-
-		getProject().copyInheritedProperties(subproject);
-	}
-
-	/**
-	 * Add the references explicitly defined as nested elements to the new
-	 * project. Also copy over all references that don't override existing
-	 * references in the new project if inheritrefs has been requested.
-	 * 
-	 * @param subproject a subproject
-	 * @throws BuildException
-	 *             if a reference does not have a refid.
-	 */
-	private void addReferences(Project subproject) throws BuildException {
-		Hashtable thisReferences = (Hashtable) getProject().getReferences()
-				.clone();
-		Hashtable newReferences = subproject.getReferences();
-		Enumeration e;
-		if (references.size() > 0) {
-			for (e = references.elements(); e.hasMoreElements();) {
-				org.apache.tools.ant.taskdefs.Ant.Reference ref = (org.apache.tools.ant.taskdefs.Ant.Reference) e.nextElement();
-				String refid = ref.getRefId();
-				if (refid == null) {
-					throw new BuildException("the refid attribute is required"
-							+ " for reference elements");
-				}
-				if (!thisReferences.containsKey(refid)) {
-					log("Parent project doesn't contain any reference '"
-							+ refid + "'", Project.MSG_WARN);
-					continue;
-				}
-
-				thisReferences.remove(refid);
-				String toRefid = ref.getToRefid();
-				if (toRefid == null) {
-					toRefid = refid;
-				}
-				copyReference(subproject, refid, toRefid);
-			}
-		}
-
-		// Now add all references that are not defined in the
-		// subproject, if inheritRefs is true
-		if (inheritRefs) {
-			for (e = thisReferences.keys(); e.hasMoreElements();) {
-				String key = (String) e.nextElement();
-				if (newReferences.containsKey(key)) {
-					continue;
-				}
-				copyReference(subproject, key, key);
-				subproject.inheritIDReferences(getProject());
-			}
-		}
-	}
-
-	/**
-	 * Try to clone and reconfigure the object referenced by oldkey in the
-	 * parent project and add it to the new project with the key newkey.
-	 * 
-	 * <p>
-	 * If we cannot clone it, copy the referenced object itself and keep our
-	 * fingers crossed.
-	 * </p>
-	 * 
-	 * @param oldKey
-	 *            the reference id in the current project.
-	 * @param newKey
-	 *            the reference id in the new project.
-	 */
-	private void copyReference(Project subproject, String oldKey, String newKey) {
-		Object orig = getProject().getReference(oldKey);
-		if (orig == null) {
-			log("No object referenced by " + oldKey + ". Can't copy to "
-					+ newKey, Project.MSG_WARN);
-			return;
-		}
-
-		Class c = orig.getClass();
-		Object copy = orig;
-		try {
-			Method cloneM = c.getMethod("clone", new Class[0]);
-			if (cloneM != null) {
-				copy = cloneM.invoke(orig, new Object[0]);
-				log("Adding clone of reference " + oldKey, Project.MSG_DEBUG);
-			}
-		} catch (Exception e) {
-			// not Clonable
-		}
-
-		if (copy instanceof ProjectComponent) {
-			((ProjectComponent) copy).setProject(subproject);
-		} else {
-			try {
-				Method setProjectM = c.getMethod("setProject",
-						new Class[] { Project.class });
-				if (setProjectM != null) {
-					setProjectM.invoke(copy, new Object[] { subproject });
-				}
-			} catch (NoSuchMethodException e) {
-				// ignore this if the class being referenced does not have
-				// a set project method.
-			} catch (Exception e2) {
-				String msg = "Error setting new project instance for "
-						+ "reference with id " + oldKey;
-				throw new BuildException(msg, e2, getLocation());
-			}
-		}
-		subproject.addReference(newKey, copy);
-	}
-
-	/**
-	 * A Vector or target names, which can be constructed from a simple
-	 * comma-separated list of values.
-	 */
-	public static class TargetList extends Vector<String> {
-		private static final long serialVersionUID = 2302999727821991487L;
-
-		public TargetList(String commaSeparated) {
-			this(commaSeparated.split(","));
-		}
-
-		public TargetList(String... targets) {
-			for (String target : targets)
-				add(target);
-		}
-	}
+    private boolean failOnError = true;
+    private boolean verbose = false;
+    private String moduleFile = EasyAntConstants.DEFAULT_BUILD_MODULE;
+
+    private Path buildpath;
+    private TargetList targets = null;
+    private boolean useBuildRepository = false;
+    private boolean overwrite = true;
+
+    private boolean inheritRefs = false;
+    private Vector<Property> properties = new Vector<Property>();
+    private Vector<Ant.Reference> references = new Vector<Ant.Reference>();
+    private Vector<PropertySet> propertySets = new Vector<PropertySet>();
+
+    public void execute() throws BuildException {
+        if (buildpath == null) {
+            throw new BuildException("No buildpath specified");
+        }
+        final String[] filenames = buildpath.list();
+        final int count = filenames.length;
+        if (count < 1) {
+            log("No sub-builds to iterate on", Project.MSG_WARN);
+            return;
+        }
+
+        ProjectUtils.replaceMainLogger(getProject(), new MultiModuleLogger());
+
+        BuildException buildException = null;
+        for (int i = 0; i < count; ++i) {
+            File file = null;
+            String subdirPath = null;
+            Throwable thrownException = null;
+            try {
+                File directory = null;
+                file = new File(filenames[i]);
+                if (file.isDirectory()) {
+                    if (verbose) {
+                        subdirPath = file.getPath();
+                        log("Entering directory: " + subdirPath + "\n", Project.MSG_INFO);
+                    }
+                    file = new File(file, moduleFile);
+                }
+                directory = file.getParentFile();
+                execute(file, directory);
+                if (verbose && subdirPath != null) {
+                    log("Leaving directory: " + subdirPath + "\n", Project.MSG_INFO);
+                }
+            } catch (RuntimeException ex) {
+                if (!(getProject().isKeepGoingMode())) {
+                    if (verbose && subdirPath != null) {
+                        log("Leaving directory: " + subdirPath + "\n", Project.MSG_INFO);
+                    }
+                    throw ex; // throw further
+                }
+                thrownException = ex;
+            } catch (Throwable ex) {
+                if (!(getProject().isKeepGoingMode())) {
+                    if (verbose && subdirPath != null) {
+                        log("Leaving directory: " + subdirPath + "\n", Project.MSG_INFO);
+                    }
+                    throw new BuildException(ex);
+                }
+                thrownException = ex;
+            }
+            if (thrownException != null) {
+                if (thrownException instanceof BuildException) {
+                    log("File '" + file + "' failed with message '" + thrownException.getMessage() + "'.",
+                            Project.MSG_ERR);
+                    // only the first build exception is reported
+                    if (buildException == null) {
+                        buildException = (BuildException) thrownException;
+                    }
+                } else {
+                    log("Target '" + file + "' failed with message '" + thrownException.getMessage() + "'.",
+                            Project.MSG_ERR);
+                    thrownException.printStackTrace(System.err);
+                    if (buildException == null) {
+                        buildException = new BuildException(thrownException);
+                    }
+                }
+                if (verbose && subdirPath != null) {
+                    log("Leaving directory: " + subdirPath + "\n", Project.MSG_INFO);
+                }
+            }
+        }
+        // check if one of the builds failed in keep going mode
+        if (buildException != null) {
+            throw buildException;
+        }
+    }
+
+    /**
+     * Runs the given target on the provided build file.
+     * 
+     * @param file
+     *            the build file to execute
+     * @param directory
+     *            the directory of the current iteration
+     * @throws BuildException
+     *             is the file cannot be found, read, is a directory, or the target called failed, but only if
+     *             <code>failOnError</code> is <code>true</code>. Otherwise, a warning log message is simply output.
+     */
+    private void execute(File file, File directory) throws BuildException {
+        if (!file.exists() || file.isDirectory() || !file.canRead()) {
+            String msg = "Invalid file: " + file;
+            if (failOnError) {
+                throw new BuildException(msg);
+            }
+            log(msg, Project.MSG_WARN);
+            return;
+        }
+
+        Project subModule = configureSubModule(file, directory);
+        subModule.fireSubBuildStarted();
+
+        try {
+            // buildFile should be in the same directory of buildModule
+            File buildfile = new File(directory, EasyAntConstants.DEFAULT_BUILD_FILE);
+            if (buildfile.exists()) {
+                subModule.setNewProperty(MagicNames.ANT_FILE, buildfile.getAbsolutePath());
+            }
+            subModule.setNewProperty(EasyAntMagicNames.EASYANT_FILE, file.getAbsolutePath());
+
+            ProjectHelper helper = ProjectHelper.getProjectHelper();
+            File mainscript = ProjectUtils.emulateMainScript(getProject());
+            helper.getImportStack().addElement(mainscript);
+            subModule.addReference(ProjectHelper.PROJECTHELPER_REFERENCE, helper);
+
+            LoadModule lm = new LoadModule();
+            lm.setBuildModule(file);
+            lm.setBuildFile(buildfile);
+            lm.setTaskName(EasyAntConstants.EASYANT_TASK_NAME);
+            lm.setProject(subModule);
+            lm.setOwningTarget(ProjectUtils.createTopLevelTarget());
+            lm.setLocation(new Location(mainscript.toString()));
+            lm.setUseBuildRepository(useBuildRepository);
+            lm.execute();
+
+            filterTargets(subModule);
+            printExecutingTargetMsg(subModule);
+
+            if (targets != null && !targets.isEmpty()) {
+                subModule.executeTargets(targets);
+                if (useBuildRepository) {
+
+                    File artifactsDir = subModule.resolveFile(subModule.getProperty("target.artifacts"));
+                    if (artifactsDir.isDirectory()) {
+
+                        // this property set by LoadModule task when it
+                        // configures the build repo
+                        String resolver = subModule.getProperty(EasyAntMagicNames.EASYANT_BUILD_REPOSITORY);
+
+                        subModule.log("Publishing in build scoped repository", Project.MSG_INFO);
+                        // Publish on build scoped repository
+                        IvyPublish ivyPublish = new IvyPublish();
+                        ivyPublish.setSettingsRef(IvyInstanceHelper.buildProjectIvyReference(subModule));
+                        ivyPublish.setResolver(resolver);
+                        // TODO: this should be more flexible!
+                        ivyPublish.setArtifactspattern("${target.artifacts}/[artifact](-[classifier]).[ext]");
+                        // not all sub-build targets will generate ivy
+                        // artifacts. we don't want to fail
+                        // a successful build just because there's nothing to
+                        // publish.
+                        ivyPublish.setWarnonmissing(false);
+                        ivyPublish.setHaltonmissing(false);
+                        ivyPublish.setProject(subModule);
+                        ivyPublish.setOwningTarget(getOwningTarget());
+                        ivyPublish.setLocation(getLocation());
+                        ivyPublish.setOverwrite(overwrite);
+                        ivyPublish.setTaskName("publish-buildscoped-repository");
+                        ivyPublish.execute();
+                    } else {
+                        subModule.log("Skipping publish because " + artifactsDir.getPath() + " is not a directory",
+                                Project.MSG_VERBOSE);
+                    }
+                }
+            } else {
+                subModule.log("Skipping sub-project build because no matching targets were found", Project.MSG_VERBOSE);
+            }
+            subModule.fireSubBuildFinished(null);
+        } catch (BuildException e) {
+            subModule.fireSubBuildFinished(e);
+            throw e;
+        } finally {
+            // add execution times for the current submodule to parent
+            // project references for access from MetaBuildExecutor
+            storeExecutionTimes(getProject(), subModule);
+        }
+
+    }
+
+    private Project configureSubModule(File file, File directory) {
+        Project subModule = getProject().createSubProject();
+        for (int i = 0; i < getProject().getBuildListeners().size(); i++) {
+            BuildListener buildListener = (BuildListener) getProject().getBuildListeners().elementAt(i);
+            subModule.addBuildListener(buildListener);
+        }
+        // explicitly add the execution timer to time
+        // sub builds
+        subModule.addBuildListener(new SubBuildExecutionTimer());
+
+        // copy all User properties
+        addAlmostAll(getProject().getUserProperties(), subModule, PropertyType.USER);
+
+        // copy easyantIvyInstance
+        IvyAntSettings ivyAntSettings = IvyInstanceHelper.getEasyAntIvyAntSettings(getProject());
+        subModule.addReference(EasyAntMagicNames.EASYANT_IVY_INSTANCE, ivyAntSettings);
+
+        // inherit meta.target directory, for shared build repository.
+        String metaTarget = getProject().getProperty("meta.target");
+        if (metaTarget != null) {
+            File metaDir = getProject().resolveFile(metaTarget);
+            subModule.setNewProperty("meta.target", metaDir.getAbsolutePath());
+        }
+
+        subModule.initProperties();
+
+        // copy nested properties
+        for (PropertySet ps : propertySets) {
+            addAlmostAll(ps.getProperties(), subModule, PropertyType.PLAIN);
+        }
+
+        overrideProperties(subModule);
+        addReferences(subModule);
+
+        subModule.setName(file.getName());
+        subModule.setBaseDir(directory);
+        return subModule;
+    }
+
+    private void storeExecutionTimes(Project parent, Project child) {
+        List<ExecutionResult> allresults = (List<ExecutionResult>) parent
+                .getReference(SubBuildExecutionTimer.EXECUTION_TIMER_SUBBUILD_RESULTS);
+        if (allresults == null) {
+            allresults = new ArrayList<ExecutionResult>();
+            parent.addReference(SubBuildExecutionTimer.EXECUTION_TIMER_SUBBUILD_RESULTS, allresults);
+        }
+        List<ExecutionResult> childResults = (List<ExecutionResult>) child
+                .getReference(SubBuildExecutionTimer.EXECUTION_TIMER_SUBBUILD_RESULTS);
+        if (childResults != null)
+            allresults.addAll(childResults);
+    }
+
+    /**
+     * Filter the active set of targets to only those defined in the given project.
+     */
+    private void filterTargets(Project subProject) {
+        Set<?> keys = subProject.getTargets().keySet();
+        for (Iterator<String> it = targets.iterator(); it.hasNext();) {
+            String target = it.next();
+            if (!keys.contains(target) && target.trim().length() > 0) {
+                subProject.log("Skipping undefined target '" + target + "'", Project.MSG_VERBOSE);
+                it.remove();
+            }
+        }
+    }
+
+    /**
+     * Print a message when executing the target
+     * 
+     * @param subProject
+     *            a subproject where the log will be printed
+     */
+    private void printExecutingTargetMsg(Project subProject) {
+        final String HEADER = "======================================================================";
+        StringBuilder sb = new StringBuilder();
+        sb.append(HEADER).append(StringUtils.LINE_SEP);
+        sb.append("Executing ").append(targets).append(" on ").append(subProject.getName());
+        sb.append(StringUtils.LINE_SEP).append(HEADER);
+        subProject.log(sb.toString());
+    }
+
+    /**
+     * Copies all properties from the given table to the new project - omitting those that have already been set in the
+     * new project as well as properties named basedir or ant.file.
+     * 
+     * @param props
+     *            properties <code>Hashtable</code> to copy to the new project.
+     * @param the
+     *            type of property to set (a plain Ant property, a user property or an inherited property).
+     * @since Ant 1.8.0
+     */
+    private void addAlmostAll(Hashtable<?, ?> props, Project subProject, PropertyType type) {
+        Enumeration<?> e = props.keys();
+        while (e.hasMoreElements()) {
+            String key = e.nextElement().toString();
+            if (MagicNames.PROJECT_BASEDIR.equals(key) || MagicNames.ANT_FILE.equals(key)) {
+                // basedir and ant.file get special treatment in execute()
+                continue;
+            }
+
+            String value = props.get(key).toString();
+            if (type == PropertyType.PLAIN) {
+                // don't re-set user properties, avoid the warning message
+                if (subProject.getProperty(key) == null) {
+                    // no user property
+                    subProject.setNewProperty(key, value);
+                }
+            } else if (type == PropertyType.USER) {
+                subProject.setUserProperty(key, value);
+            } else if (type == PropertyType.INHERITED) {
+                subProject.setInheritedProperty(key, value);
+            }
+        }
+    }
+
+    private static final class PropertyType {
+        private PropertyType() {
+        }
+
+        private static final PropertyType PLAIN = new PropertyType();
+        private static final PropertyType INHERITED = new PropertyType();
+        private static final PropertyType USER = new PropertyType();
+    }
+
+    /**
+     * The target to call on the different sub-builds. Set to "" to execute the default target.
+     * 
+     * @param target
+     *            the target
+     *            <p>
+     */
+    // REVISIT: Defaults to the target name that contains this task if not
+    // specified.
+    public void setTarget(String target) {
+        setTargets(new TargetList(target));
+    }
+
+    /**
+     * The targets to call on the different sub-builds.
+     * 
+     * @param target
+     *            a list of targets to execute
+     */
+    public void setTargets(TargetList targets) {
+        this.targets = targets;
+    }
+
+    /**
+     * Set the buildpath to be used to find sub-projects.
+     * 
+     * @param s
+     *            an Ant Path object containing the buildpath.
+     */
+    public void setBuildpath(Path s) {
+        getBuildpath().append(s);
+    }
+
+    /**
+     * Gets the implicit build path, creating it if <code>null</code>.
+     * 
+     * @return the implicit build path.
+     */
+    private Path getBuildpath() {
+        if (buildpath == null) {
+            buildpath = new Path(getProject());
+        }
+        return buildpath;
+    }
+
+    /**
+     * Buildpath to use, by reference.
+     * 
+     * @param r
+     *            a reference to an Ant Path object containing the buildpath.
+     */
+    public void setBuildpathRef(Reference r) {
+        createBuildpath().setRefid(r);
+    }
+
+    /**
+     * Creates a nested build path, and add it to the implicit build path.
+     * 
+     * @return the newly created nested build path.
+     */
+    public Path createBuildpath() {
+        return getBuildpath().createPath();
+    }
+
+    /**
+     * Enable/ disable verbose log messages showing when each sub-build path is entered/ exited. The default value is
+     * "false".
+     * 
+     * @param on
+     *            true to enable verbose mode, false otherwise (default).
+     */
+    public void setVerbose(boolean on) {
+        this.verbose = on;
+    }
+
+    /**
+     * Sets whether to fail with a build exception on error, or go on.
+     * 
+     * @param failOnError
+     *            the new value for this boolean flag.
+     */
+    public void setFailonerror(boolean failOnError) {
+        this.failOnError = failOnError;
+    }
+
+    /**
+     * Sets whether a submodule should use build repository or not
+     * 
+     * @param useBuildRepository
+     *            the new value for this boolean flag
+     */
+    public void setUseBuildRepository(boolean useBuildRepository) {
+        this.useBuildRepository = useBuildRepository;
+    }
+
+    /**
+     * Set whether publish operations for the {@link #setUseBuildRepository(boolean) build-scoped repository} should
+     * overwrite existing artifacts. Defaults to <code>true</code> if unspecified.
+     */
+    public void setOverwrite(boolean overwrite) {
+        this.overwrite = overwrite;
+    }
+
+    /**
+     * Corresponds to <code>&lt;ant&gt;</code>'s <code>inheritrefs</code> attribute.
+     * 
+     * @param b
+     *            the new value for this boolean flag.
+     */
+    public void setInheritrefs(boolean b) {
+        this.inheritRefs = b;
+    }
+
+    /**
+     * Corresponds to <code>&lt;ant&gt;</code>'s nested <code>&lt;property&gt;</code> element.
+     * 
+     * @param p
+     *            the property to pass on explicitly to the sub-build.
+     */
+    public void addProperty(Property p) {
+        properties.addElement(p);
+    }
+
+    /**
+     * Corresponds to <code>&lt;ant&gt;</code>'s nested <code>&lt;reference&gt;</code> element.
+     * 
+     * @param r
+     *            the reference to pass on explicitly to the sub-build.
+     */
+    public void addReference(Ant.Reference r) {
+        references.addElement(r);
+    }
+
+    /**
+     * Corresponds to <code>&lt;ant&gt;</code>'s nested <code>&lt;propertyset&gt;</code> element.
+     * 
+     * @param ps
+     *            the propertset
+     */
+    public void addPropertyset(PropertySet ps) {
+        propertySets.addElement(ps);
+    }
+
+    /**
+     * Override the properties in the new project with the one explicitly defined as nested elements here.
+     * 
+     * @param subproject
+     *            a subproject
+     * @throws BuildException
+     *             under unknown circumstances.
+     */
+    private void overrideProperties(Project subproject) throws BuildException {
+        // remove duplicate properties - last property wins
+        // Needed for backward compatibility
+        Set<String> set = new HashSet<String>();
+        for (int i = properties.size() - 1; i >= 0; --i) {
+            Property p = (Property) properties.get(i);
+            if (p.getName() != null && !p.getName().equals("")) {
+                if (set.contains(p.getName())) {
+                    properties.remove(i);
+                } else {
+                    set.add(p.getName());
+                }
+            }
+        }
+        for (Property p : properties) {
+            p.setProject(subproject);
+            p.execute();
+        }
+
+        getProject().copyInheritedProperties(subproject);
+    }
+
+    /**
+     * Add the references explicitly defined as nested elements to the new project. Also copy over all references that
+     * don't override existing references in the new project if inheritrefs has been requested.
+     * 
+     * @param subproject
+     *            a subproject
+     * @throws BuildException
+     *             if a reference does not have a refid.
+     */
+    private void addReferences(Project subproject) throws BuildException {
+        Hashtable<String, Object> thisReferences = (Hashtable<String, Object>) getProject().getReferences().clone();
+        Hashtable<String, Object> newReferences = (Hashtable<String, Object>) subproject.getReferences();
+        Enumeration<?> e;
+        for (Ant.Reference ref : references) {
+            String refid = ref.getRefId();
+            if (refid == null) {
+                throw new BuildException("the refid attribute is required" + " for reference elements");
+            }
+            if (!thisReferences.containsKey(refid)) {
+                log("Parent project doesn't contain any reference '" + refid + "'", Project.MSG_WARN);
+                continue;
+            }
+
+            thisReferences.remove(refid);
+            String toRefid = ref.getToRefid();
+            if (toRefid == null) {
+                toRefid = refid;
+            }
+            copyReference(subproject, refid, toRefid);
+        }
+
+        // Now add all references that are not defined in the
+        // subproject, if inheritRefs is true
+        if (inheritRefs) {
+            for (e = thisReferences.keys(); e.hasMoreElements();) {
+                String key = (String) e.nextElement();
+                if (newReferences.containsKey(key)) {
+                    continue;
+                }
+                copyReference(subproject, key, key);
+                subproject.inheritIDReferences(getProject());
+            }
+        }
+    }
+
+    /**
+     * Try to clone and reconfigure the object referenced by oldkey in the parent project and add it to the new project
+     * with the key newkey.
+     * 
+     * <p>
+     * If we cannot clone it, copy the referenced object itself and keep our fingers crossed.
+     * </p>
+     * 
+     * @param oldKey
+     *            the reference id in the current project.
+     * @param newKey
+     *            the reference id in the new project.
+     */
+    private void copyReference(Project subproject, String oldKey, String newKey) {
+        Object orig = getProject().getReference(oldKey);
+        if (orig == null) {
+            log("No object referenced by " + oldKey + ". Can't copy to " + newKey, Project.MSG_WARN);
+            return;
+        }
+
+        Class<?> c = orig.getClass();
+        Object copy = orig;
+        try {
+            Method cloneM = c.getMethod("clone", new Class[0]);
+            if (cloneM != null) {
+                copy = cloneM.invoke(orig, new Object[0]);
+                log("Adding clone of reference " + oldKey, Project.MSG_DEBUG);
+            }
+        } catch (Exception e) {
+            // not Clonable
+        }
+
+        if (copy instanceof ProjectComponent) {
+            ((ProjectComponent) copy).setProject(subproject);
+        } else {
+            try {
+                Method setProjectM = c.getMethod("setProject", new Class[] { Project.class });
+                if (setProjectM != null) {
+                    setProjectM.invoke(copy, new Object[] { subproject });
+                }
+            } catch (NoSuchMethodException e) {
+                // ignore this if the class being referenced does not have
+                // a set project method.
+            } catch (Exception e2) {
+                String msg = "Error setting new project instance for " + "reference with id " + oldKey;
+                throw new BuildException(msg, e2, getLocation());
+            }
+        }
+        subproject.addReference(newKey, copy);
+    }
+
+    /**
+     * A Vector or target names, which can be constructed from a simple comma-separated list of values.
+     */
+    public static class TargetList extends Vector<String> {
+        private static final long serialVersionUID = 2302999727821991487L;
+
+        public TargetList(String commaSeparated) {
+            this(commaSeparated.split(","));
+        }
+
+        public TargetList(String... targets) {
+            for (String target : targets)
+                add(target);
+        }
+    }
 }

Modified: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/AbstractFindClassPathStrategy.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/AbstractFindClassPathStrategy.java?rev=1389079&r1=1389078&r2=1389079&view=diff
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/AbstractFindClassPathStrategy.java (original)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/AbstractFindClassPathStrategy.java Sun Sep 23 15:28:03 2012
@@ -17,7 +17,6 @@
  */
 package org.apache.easyant.tasks.findclasspath;
 
-import org.apache.easyant.core.EasyAntMagicNames;
 import org.apache.easyant.core.ivy.IvyInstanceHelper;
 import org.apache.ivy.ant.IvyCachePath;
 import org.apache.ivy.core.LogOptions;
@@ -31,25 +30,24 @@ public abstract class AbstractFindClassP
     public String pathid;
     protected Path path;
     private AbstractFindClassPathStrategy nextStrategy;
-    
-    
+
     public boolean check() {
-        boolean result=doCheck();
+        boolean result = doCheck();
         if (!result) {
-            if (getNextStrategy()== null) {
+            if (getNextStrategy() == null) {
                 return false;
             } else {
-                return getNextStrategy().check();   
+                return getNextStrategy().check();
             }
-            
+
         } else {
             return true;
         }
-        
+
     }
-    
+
     protected abstract boolean doCheck();
-    
+
     /**
      * Utilitary method to load cachepath
      * 
@@ -64,13 +62,11 @@ public abstract class AbstractFindClassP
      * @param ivyRef
      *            ivy instance reference
      */
-    protected void loadCachePath(String organisation, String module,
-            String revision, String conf, Reference ivyRef) {
+    protected void loadCachePath(String organisation, String module, String revision, String conf, Reference ivyRef) {
         StringBuilder sb = new StringBuilder();
         sb.append("Building classpath (").append(getPathid()).append(")");
         sb.append(" with ");
-        sb.append(organisation).append("#").append(module).append(";").append(
-                revision);
+        sb.append(organisation).append("#").append(module).append(";").append(revision);
         sb.append(" conf=").append(conf);
         log(sb.toString(), Project.MSG_DEBUG);
         IvyCachePath pluginCachePath = new IvyCachePath();
@@ -86,7 +82,7 @@ public abstract class AbstractFindClassP
         initTask(pluginCachePath).execute();
 
     }
-    
+
     /**
      * Utilitary method to build the classpath
      * 
@@ -97,26 +93,29 @@ public abstract class AbstractFindClassP
             path = new Path(getProject());
             path.setPath(getPathid());
             path.setLocation(getLocation());
-            
+
         }
         return path;
     }
-    
+
     /**
      * Utilitary method to configure a task with the current one
-     * @param task task to configure
+     * 
+     * @param task
+     *            task to configure
      * @return the configured task
      */
     protected Task initTask(Task task) {
         task.setLocation(getLocation());
         task.setProject(getProject());
-        //task.setTaskName(getTaskName());
-        //task.setOwningTarget(getOwningTarget());
+        // task.setTaskName(getTaskName());
+        // task.setOwningTarget(getOwningTarget());
         return task;
     }
 
     /**
      * Get a reference of the project ivy instance
+     * 
      * @return a reference of the project ivy instance
      */
     protected Reference getProjectIvyReference() {
@@ -130,7 +129,7 @@ public abstract class AbstractFindClassP
     public void setPathid(String pathid) {
         this.pathid = pathid;
     }
-    
+
     public AbstractFindClassPathStrategy getNextStrategy() {
         return nextStrategy;
     }
@@ -138,8 +137,5 @@ public abstract class AbstractFindClassP
     public void setNextStrategy(AbstractFindClassPathStrategy nextStrategy) {
         this.nextStrategy = nextStrategy;
     }
-    
-    
-
 
 }



Mime
View raw message