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 jl...@apache.org on 2012/09/23 15:28:04 UTC
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/
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><ant></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><ant></code>'s nested
- * <code><property></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><ant></code>'s nested
- * <code><reference></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><ant></code>'s nested
- * <code><propertyset></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><ant></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><ant></code>'s nested <code><property></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><ant></code>'s nested <code><reference></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><ant></code>'s nested <code><propertyset></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;
}
-
-
-
}