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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/RepositoryReport.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/RepositoryReport.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/RepositoryReport.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/RepositoryReport.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,563 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.easyant.core.EasyAntMagicNames;
+import org.apache.easyant.core.menu.MenuGenerator;
+import org.apache.easyant.core.menu.MenuGeneratorRegistry;
+import org.apache.easyant.core.report.EasyAntReport;
+import org.apache.easyant.core.report.XmlEasyAntReportOutputter;
+import org.apache.easyant.core.services.PluginService;
+import org.apache.easyant.tasks.menu.MenuGeneratorUtils;
+import org.apache.ivy.Ivy;
+import org.apache.ivy.core.cache.ResolutionCacheManager;
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.resolve.ResolveOptions;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
+import org.apache.ivy.plugins.report.XmlReportOutputter;
+import org.apache.ivy.util.FileUtil;
+import org.apache.ivy.util.Message;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.XSLTProcess;
+import org.apache.tools.ant.types.Mapper;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.util.FileNameMapper;
+
+/**
+ * Generates a report of dependencies of a set of modules in the repository. The
+ * set of modules is specified using organisation/module and matcher.
+ */
+public class RepositoryReport extends AbstractEasyAntTask {
+	private String organisation = "*";
+
+	private String module;
+
+	private String branch;
+
+	private String revision = "latest.integration";
+
+	private String matcher = PatternMatcher.EXACT_OR_REGEXP;
+
+	private File todir;
+
+	private boolean graph = false;
+
+	private boolean dot = false;
+
+	private boolean xml = false;
+
+	private boolean xsl = true;
+
+	private boolean displaySubProperties = false;
+
+	private String xslFile;
+
+	private String outputname = "ivy-repository-report";
+
+	private String xslext = "html";
+
+    private String resolver;
+
+	private List<XSLTProcess.Param> params = new ArrayList<XSLTProcess.Param>();
+
+	private List<ReportMenu> menus = new ArrayList<ReportMenu>();
+
+	public void execute() throws BuildException {
+		Ivy ivy = getEasyAntIvyInstance();
+		IvySettings settings = ivy.getSettings();
+
+		ModuleRevisionId mrid = ModuleRevisionId.newInstance(organisation,
+				module, revision);
+
+		PluginService pluginService = (PluginService) getProject()
+				.getReference(EasyAntMagicNames.PLUGIN_SERVICE_INSTANCE);
+		try {
+			ModuleRevisionId[] mrids = pluginService.search(organisation,
+					module, revision, branch, matcher, resolver);
+			// replace all found revisions with the original requested revision
+			Set<ModuleRevisionId> modules = new HashSet<ModuleRevisionId>();
+			for (int i = 0; i < mrids.length; i++) {
+				modules.add(ModuleRevisionId.newInstance(mrids[i], revision));
+			}
+
+			String conf = "default";
+            XslReport xslReport = new XslReport();
+
+            ResolutionCacheManager cacheMgr = ivy.getResolutionCacheManager();
+            final String dotXsl = dot ? getDotStylePath(cacheMgr.getResolutionCacheRoot()) : null;
+            final String graphXsl = graph ? getGraphStylePath(cacheMgr.getResolutionCacheRoot()) : null;
+            final String reportXsl = xsl ? getXslPath() : null;
+
+			for (Iterator iterator = modules.iterator(); iterator.hasNext();) {
+				ModuleRevisionId moduleRevisionId = (ModuleRevisionId) iterator
+						.next();
+				ModuleDescriptor md = DefaultModuleDescriptor
+						.newCallerInstance(moduleRevisionId, conf.split(","),
+								true, false);
+				outputname = moduleRevisionId.getName();
+				String resolveId = ResolveOptions.getDefaultResolveId(md);
+				EasyAntReport easyAntReport = null;
+				try {
+					easyAntReport = pluginService.getPluginInfo(
+						moduleRevisionId, conf);
+				} catch (Exception e) {
+					throw new Exception("can't parse " + moduleRevisionId.toString(),e);
+				}
+				if (easyAntReport == null
+						|| easyAntReport.getResolveReport() == null) {
+					throw new Exception("impossible to generate graph for "
+							+ moduleRevisionId.toString()
+							+ ": can't find easyant report");
+				}
+
+				new XmlEasyAntReportOutputter().output(easyAntReport
+						.getResolveReport(), cacheMgr, new ResolveOptions(),
+						easyAntReport, displaySubProperties);
+				
+                File xmlSource = cacheMgr.getConfigurationResolveReportInCache(
+                        resolveId, "default");
+
+				if (graph) {
+                    xslReport.add(graphXsl, xmlSource, outputname, "graphml");
+				}
+				if (dot) {
+                    xslReport.add(dotXsl, xmlSource, outputname, "dot");
+				}
+                if (xsl) {
+                    xslReport.add(reportXsl, xmlSource, outputname, getXslext());
+                }
+				if (xml) {
+					FileUtil.copy(cacheMgr
+							.getConfigurationResolveReportInCache(resolveId,
+									"default"), new File(getTodir(), outputname
+							+ ".xml"), null);
+				}
+			}
+
+            //run XSL transform on accumulated source files
+            xslReport.generateAll();
+
+            if (xsl && xslFile == null) {
+                // Copy css for default report if required
+                File css;
+                if (todir != null) {
+                    css = new File(todir, "easyant-report.css");
+                } else {
+                    css = getProject().resolveFile("easyant-report.css");
+                }
+
+                if (!css.exists()) {
+                    Message.debug("copying report css to " + css.getAbsolutePath());
+                    FileUtil.copy(XmlEasyAntReportOutputter.class
+                            .getResourceAsStream("easyant-report.css"), css, null);
+                }
+            }
+
+		} catch (Exception e) {
+			throw new BuildException("impossible to generate graph for " + mrid
+					+ ": " + e, e);
+		}
+	}
+
+	private String getGraphStylePath(File cache) throws IOException {
+		// style should be a file (and not an url)
+		// so we have to copy it from classpath to cache
+		File style = new File(cache, "easyant-report-graph.xsl");
+		FileUtil.copy(XmlReportOutputter.class
+				.getResourceAsStream("easyant-report-graph.xsl"), style, null);
+		return style.getAbsolutePath();
+	}
+
+	private String getXslPath() throws IOException {
+		if (xslFile != null) {
+			return xslFile;
+		}
+		// style should be a file (and not an url)
+		// so we have to copy it from classpath to cache
+		ResolutionCacheManager cacheMgr = getEasyAntIvyInstance()
+				.getResolutionCacheManager();
+		File style = new File(cacheMgr.getResolutionCacheRoot(),
+				"easyant-report.xsl");
+		FileUtil.copy(XmlEasyAntReportOutputter.class
+				.getResourceAsStream("easyant-report.xsl"), style, null);
+		return style.getAbsolutePath();
+	}
+
+	private String getDotStylePath(File cache) throws IOException {
+		// style should be a file (and not an url)
+		// so we have to copy it from classpath to cache
+		File style = new File(cache, "easyant-report-dot.xsl");
+		FileUtil.copy(XmlEasyAntReportOutputter.class
+				.getResourceAsStream("easyant-report-dot.xsl"), style, null);
+		return style.getAbsolutePath();
+	}
+
+	public File getTodir() {
+		if (todir == null && getProject() != null) {
+			return getProject().getBaseDir();
+		}
+		return todir;
+	}
+
+	public void setTodir(File todir) {
+		this.todir = todir;
+	}
+
+	public boolean isGraph() {
+		return graph;
+	}
+
+	public void setGraph(boolean graph) {
+		this.graph = graph;
+	}
+
+	public String getXslfile() {
+		return xslFile;
+	}
+
+	public void setXslfile(String xslFile) {
+		this.xslFile = xslFile;
+	}
+
+	public boolean isXml() {
+		return xml;
+	}
+
+	public void setXml(boolean xml) {
+		this.xml = xml;
+	}
+
+	public boolean isXsl() {
+		return xsl;
+	}
+
+	public void setXsl(boolean xsl) {
+		this.xsl = xsl;
+	}
+
+	public String getXslext() {
+		return xslext;
+	}
+
+	public void setXslext(String xslext) {
+		this.xslext = xslext;
+	}
+
+	public XSLTProcess.Param createParam() {
+		XSLTProcess.Param result = new XSLTProcess.Param();
+		params.add(result);
+		return result;
+	}
+
+	public String getOutputname() {
+		return outputname;
+	}
+
+	public void setOutputname(String outputpattern) {
+		outputname = outputpattern;
+	}
+
+	public String getMatcher() {
+		return matcher;
+	}
+
+	public void setMatcher(String matcher) {
+		this.matcher = matcher;
+	}
+
+	public String getModule() {
+		return module;
+	}
+
+	public void setModule(String module) {
+		this.module = module;
+	}
+
+	public String getOrganisation() {
+		return organisation;
+	}
+
+	public void setOrganisation(String organisation) {
+		this.organisation = organisation;
+	}
+
+	public String getRevision() {
+		return revision;
+	}
+
+	public void setRevision(String revision) {
+		this.revision = revision;
+	}
+
+	public String getBranch() {
+		return branch;
+	}
+
+	public void setBranch(String branch) {
+		this.branch = branch;
+	}
+
+	public boolean isDot() {
+		return dot;
+	}
+
+	public void setDot(boolean dot) {
+		this.dot = dot;
+	}
+
+	public boolean isDisplaySubProperties() {
+		return displaySubProperties;
+	}
+
+	public void setDisplaySubProperties(boolean displaySubProperties) {
+		this.displaySubProperties = displaySubProperties;
+	}
+
+    public String getResolver() {
+        return resolver;
+    }
+
+    /**
+     * Specify which resolver to report against.  The default EasyAnt resolver will be used if unspecified.
+     * "*" means search all resolvers.
+     */
+    public void setResolver(String resolver) {
+        this.resolver = resolver;
+    }
+
+	/**
+	 * Add a menu generator context, to which menu entries will be published for each report file created.
+	 */
+	public ReportMenu createMenuGenerator() {
+		ReportMenu menu = new ReportMenu();
+		menus.add(menu);
+		return menu;
+	}
+
+	/**
+	 * Represents a single menu generator context, to which entries will be added as repository report files
+	 * are created.  The attribute {@link #setContext context} is required.  Additionally supports three optional nested
+	 * elements:
+	 * <ol>
+	 * <li><code>mapper</code> maps report file to menu item title and link path (both title and link path
+	 * will have the same value).  The mapped title and link path are arguments to {@link MenuGenerator#addEntry(String, String)}.</li>
+	 * <li><code>linkMapper</code> maps report file to menu item link.  <code>linkMapper</code> and <code>titleMapper</code>
+	 * can be used together as an alternative to <code>mapper</code>, in cases were the link and title for the menu entry
+	 * have different values.</li>
+	 * <li><code>titleMapper</code> maps report file to menu item title.  <code>linkMapper</code> and <code>titleMapper</code>
+	 * can be used together as an alternative to <code>mapper</code>, in cases were the link and title for the menu entry
+	 * have different values.</li>
+	 * </ol>
+	 * If none of the above elements are provided, 
+	 */
+	public class ReportMenu {
+
+		private Mapper titleMapper;
+		private Mapper linkMapper;
+
+		private String context;
+		private MenuGeneratorRegistry registry;
+
+		//TreeMap to sort menu entries in alphabetical order.  should this behavior be configurable somehow?
+		private Map<String,String> entries = new TreeMap<String,String>();
+
+		/**
+		 * Set the menu generator context name.  Entries will be added to this context for each generated report file.
+		 * @see MenuGenerateRegistry
+		 */
+		public void setContext(String context) {
+			this.context = context;
+		}
+
+		public Mapper createMapper() {
+			return createLinkMapper();
+		}
+
+		public void setMapper(String typeName, String from, String to) {
+			setLinkMapper(typeName, from, to);
+		}
+
+		public Mapper createTitleMapper() {
+			return titleMapper = new Mapper(getProject());
+		}
+
+		public void setTitleMapper(String typeName, String from, String to) {
+			configureMapper(createTitleMapper(), typeName, from, to);
+		}
+
+		public Mapper createLinkMapper() {
+			return linkMapper = new Mapper(getProject());
+		}
+
+		public void setLinkMapper(String typeName, String from, String to) {
+			configureMapper(createLinkMapper(), typeName, from, to);
+		}
+
+		public void addEntry(String reportPath) {
+			String link = map(reportPath, linkMapper, reportPath);
+			String title = map(reportPath, titleMapper, link);
+
+			entries.put(title, link);
+		}
+
+		public void generate() throws IOException {
+			for (Map.Entry<String,String> entry : entries.entrySet()) {
+				for (MenuGenerator generator : getRegistry().getMenuGenerators()) {
+					generator.addEntry(entry.getValue(), entry.getKey());
+				}
+			}
+		}
+
+		private MenuGeneratorRegistry getRegistry() {
+			if (registry == null) {
+				registry = MenuGeneratorUtils.getRegistryForContext(getProject(), context, false);
+			}
+			return registry;
+		}
+
+		private void configureMapper(Mapper mapper, String typeName, String from, String to) {
+			Mapper.MapperType type = new Mapper.MapperType();
+			type.setValue(typeName);
+
+			mapper.setType(type);
+			mapper.setFrom(from);
+			mapper.setTo(to);
+		}
+
+		private String map(String reportPath, Mapper mapper, String defaultValue) {
+			if (mapper != null) {
+				String[] mappedTitle = mapper.getImplementation().mapFileName(reportPath);
+				if (mappedTitle != null && mappedTitle.length > 0) {
+					return mappedTitle[0];
+				}
+			}
+			return defaultValue;
+		}
+
+	}
+
+    /** accumulates a set of input XML files and their transformed destination files */
+    private class XslReport {
+
+        private HashMap<String,XslMapper> reports = new HashMap<String,XslMapper>();
+
+        /**
+         * Add a rule to transform <code>source</code> using stylesheet <code>xslPath</code>,
+         * storing the result at location <code>destination</code>.<code>extension</code>
+         */
+        public void add(String xslPath, File source, String destination, String extension) throws IOException {
+            XslMapper mapper = reports.get(xslPath);
+            if (mapper == null) {
+                reports.put(xslPath, mapper = new XslMapper(xslPath, extension));
+            }
+            mapper.add(source, destination);
+        }
+
+        /**
+         * Run all transforms previously configured by calls to {@link #add(String, java.io.File, String, String)}
+         */
+        public void generateAll() throws IOException {
+            for (XslMapper report : reports.values())
+                report.generate();
+        }
+
+        /** transforms a set of input files using a single XSL stylesheet */
+        private class XslMapper extends Path implements FileNameMapper {
+
+            //maps input file to destination file name
+            private HashMap<String,String> map = new HashMap<String,String>();
+            private String xslPath;
+            private String extension;
+
+            public XslMapper(String xslPath, String extension) {
+                super(RepositoryReport.this.getProject());
+                this.xslPath = xslPath;
+                this.extension = extension;
+            }
+
+            public void generate() throws IOException {
+                XSLTProcess xslt = new XSLTProcess();
+                xslt.setTaskName(getTaskName());
+                xslt.setProject(getProject());
+                xslt.init();
+
+                xslt.setDestdir(getTodir());
+                xslt.setUseImplicitFileset(false);
+                xslt.add((ResourceCollection)this);
+                xslt.add((FileNameMapper)this);
+                xslt.setStyle(xslPath);
+
+                XSLTProcess.Param param = xslt.createParam();
+                param.setName("extension");
+                param.setExpression(extension);
+
+                // add the provided XSLT parameters
+                for (Iterator it = params.iterator(); it.hasNext();) {
+                    param = (XSLTProcess.Param) it.next();
+                    XSLTProcess.Param realParam = xslt.createParam();
+                    realParam.setName(param.getName());
+                    realParam.setExpression(param.getExpression());
+                }
+
+                xslt.execute();
+
+	            for (ReportMenu menu : menus) {
+		            menu.generate();
+	            }
+            }
+
+            /**
+             * add the XML file <code>source</code> to this path, mapping to the output file
+             * <code>destionation</code> (without base directory or extension)
+             */
+            public void add(File source, String destination) {
+                map.put(source.getPath(), destination + "." + extension);
+                createPathElement().setLocation(source);
+	            for (ReportMenu menu : menus) {
+		            menu.addEntry(destination);
+	            }
+            }
+
+            public void setFrom(String s) {}
+            public void setTo(String s) {}
+
+            public String[] mapFileName(String s) {
+                s = map.get(new File(s).getPath());
+                return s == null ? null : new String[]{ s };
+            }
+        }
+
+    }
+
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SearchModule.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SearchModule.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SearchModule.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SearchModule.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,197 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks;
+
+import java.util.Vector;
+
+import org.apache.easyant.core.EasyAntConstants;
+import org.apache.ivy.Ivy;
+import org.apache.ivy.ant.IvyTask;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.resolve.ResolvedModuleRevision;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.input.InputHandler;
+import org.apache.tools.ant.input.InputRequest;
+import org.apache.tools.ant.input.MultipleChoiceInputRequest;
+
+public class SearchModule extends IvyTask {
+
+	private String organisation;
+
+	private String module;
+
+	private String branch = PatternMatcher.ANY_EXPRESSION;
+
+	private String revision;
+
+	private String matcher = PatternMatcher.EXACT_OR_REGEXP;
+
+	private String propertyPrefix;
+	private String resolver;
+
+	public void doExecute() throws BuildException {
+		if (getOrganisation() == null) {
+			throw new BuildException(
+					"no organisation provided for SearchModule task");
+		}
+		if (getModule() == null) {
+			throw new BuildException(
+					"no module name provided for SearchModule task");
+		}
+		if (getRevision() == null) {
+			throw new BuildException(
+					"no revision provided for SearchModule task");
+		}
+
+		if (getPropertyPrefix() == null) {
+			throw new BuildException(
+					"no property prefix provided provided for SearchModule task");
+		}
+		Ivy ivy = getIvyInstance();
+		IvySettings settings = ivy.getSettings();
+
+		// search all modules revision matching the requested criteria
+		DependencyResolver resolverToCheck;
+		if (getResolver() != null) {
+			resolverToCheck = settings.getResolver(getResolver());
+		} else {
+			resolverToCheck = settings.getDefaultResolver();
+		}
+		ModuleRevisionId mridToSearch = ModuleRevisionId.newInstance(
+				getOrganisation(), getModule(), getBranch(), getRevision());
+		ModuleRevisionId[] mrids = ivy.getSearchEngine().listModules(
+				resolverToCheck, mridToSearch, settings.getMatcher(matcher));
+
+		// diplay the list
+		Vector<String> choices = new Vector<String>();
+		for (int i = 0; i < mrids.length; i++) {
+			choices.add(String.valueOf(i));
+			StringBuilder sb = new StringBuilder();
+			sb.append(i).append(": ");
+			sb.append(mrids[i].getName());
+			sb.append(" v").append(mrids[i].getRevision());
+			// hide organization if its the default one
+			if (!mrids[i].getOrganisation().equals(
+					EasyAntConstants.EASYANT_SKELETONS_ORGANISATION))
+				sb.append(" by ").append(mrids[i].getOrganisation());
+			// Get the description
+			ResolvedModuleRevision rmr = ivy.findModule(mrids[i]);
+			if (rmr.getDescriptor().getDescription() != null
+					&& !rmr.getDescriptor().getDescription().equals("")) {
+				sb.append(" (").append(rmr.getDescriptor().getDescription())
+						.append(")");
+			}
+			log(sb.toString());
+
+		}
+		
+		
+		// ask end user to select a module
+		//TODO handle a default value
+		Integer value = new Integer(getInput("Choose a number:", null, choices));
+		ModuleRevisionId moduleToRetrieve = mrids[value];
+
+		// set final properties
+		getProject().setProperty(getPropertyPrefix() + ".org",
+				moduleToRetrieve.getOrganisation());
+		getProject().setProperty(getPropertyPrefix() + ".module",
+				moduleToRetrieve.getName());
+		getProject().setProperty(getPropertyPrefix() + ".rev",
+				moduleToRetrieve.getRevision());
+
+	}
+
+	protected String getInput(String message, String defaultvalue, Vector<String> choices) {
+		InputRequest request = null;
+		request = new MultipleChoiceInputRequest(message, choices);
+		request.setDefaultValue(defaultvalue);
+
+		InputHandler h = getProject().getInputHandler();
+
+		h.handleInput(request);
+
+		String value = request.getInput();
+		if ((value == null || value.trim().length() == 0)
+				&& defaultvalue != null) {
+			value = defaultvalue;
+		}
+		return value;
+
+	}
+
+	public String getMatcher() {
+		return matcher;
+	}
+
+	public void setMatcher(String matcher) {
+		this.matcher = matcher;
+	}
+
+	public String getModule() {
+		return module;
+	}
+
+	public void setModule(String module) {
+		this.module = module;
+	}
+
+	public String getOrganisation() {
+		return organisation;
+	}
+
+	public void setOrganisation(String organisation) {
+		this.organisation = organisation;
+	}
+
+	public String getRevision() {
+		return revision;
+	}
+
+	public void setRevision(String revision) {
+		this.revision = revision;
+	}
+
+	public String getBranch() {
+		return branch;
+	}
+
+	public void setBranch(String branch) {
+		this.branch = branch;
+	}
+
+	public String getPropertyPrefix() {
+		return propertyPrefix;
+	}
+
+	public void setPropertyPrefix(String propertyPrefix) {
+		this.propertyPrefix = propertyPrefix;
+	}
+
+	public String getResolver() {
+		return resolver;
+	}
+
+	public void setResolver(String resolver) {
+		this.resolver = resolver;
+	}
+
+}

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

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

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

Added: 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=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SubModule.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/SubModule.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,560 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Vector;
+
+import org.apache.easyant.core.EasyAntConstants;
+import org.apache.easyant.core.EasyAntMagicNames;
+import org.apache.easyant.core.ant.listerners.MultiModuleLogger;
+import org.apache.easyant.core.ivy.IvyInstanceHelper;
+import org.apache.ivy.ant.IvyAntSettings;
+import org.apache.ivy.ant.IvyPublish;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.BuildLogger;
+import org.apache.tools.ant.DefaultLogger;
+import org.apache.tools.ant.Location;
+import org.apache.tools.ant.MagicNames;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.Target;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.util.StringUtils;
+
+/**
+ * This task is used to manage orchestration of submodules.
+ */
+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;
+
+	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;
+		}
+
+		// Change the default output logger
+		PrintStream out = System.out;
+		PrintStream err = System.err;
+		int currentLogLevel = Project.MSG_INFO;
+		log("removing current logger", Project.MSG_DEBUG);
+		// since BuildLogger doesn't offer any way to get the out / err print
+		// streams we should use reflection
+		// TODO: we should find a better way to do this
+		for (Iterator<?> i = getProject().getBuildListeners().iterator(); i
+				.hasNext();) {
+			BuildListener l = (BuildListener) i.next();
+			if (l instanceof DefaultLogger) {
+				Field fields[];
+				//case of classes extending DefaultLogger
+				if (l.getClass().getSuperclass() == DefaultLogger.class) {
+					fields = l.getClass().getSuperclass().getDeclaredFields();
+				} else {
+					fields = l.getClass().getDeclaredFields();
+				}
+				
+				for (int j = 0; j < fields.length; j++) {
+					try {
+						if (fields[j].getType().equals(PrintStream.class)
+								&& fields[j].getName().equals("out")) {
+							fields[j].setAccessible(true);
+							out = (PrintStream) fields[j].get(l);
+							fields[j].setAccessible(false);
+						}
+						if (fields[j].getType().equals(PrintStream.class)
+								&& fields[j].getName().equals("err")) {
+							fields[j].setAccessible(true);
+							err = (PrintStream) fields[j].get(l);
+							fields[j].setAccessible(false);
+						}
+						if (fields[j].getName().equals("msgOutputLevel")) {
+							fields[j].setAccessible(true);
+							currentLogLevel = (Integer) fields[j].get(l);
+							fields[j].setAccessible(false);
+						}
+					} catch (IllegalAccessException ex) {
+						throw new BuildException(ex);
+					}
+				}
+			}
+			getProject().removeBuildListener(l);
+
+		}
+		log("Initializing BigProjectLogger", Project.MSG_DEBUG);
+		// Intanciate the new logger
+		BuildLogger bl = new MultiModuleLogger();
+		bl.setOutputPrintStream(out);
+		bl.setErrorPrintStream(err);
+		bl.setMessageOutputLevel(currentLogLevel);
+		getProject().setProjectReference(bl);
+		getProject().addBuildListener(bl);
+
+		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 = getProject().createSubProject();
+
+		subModule.setJavaVersionProperty();
+
+		for (int i = 0; i < getProject().getBuildListeners().size(); i++) {
+			BuildListener buildListener = (BuildListener) getProject()
+					.getBuildListeners().elementAt(i);
+			subModule.addBuildListener(buildListener);
+		}
+
+		subModule.setName(file.getName());
+		subModule.setBaseDir(directory);
+
+		subModule.fireSubBuildStarted();
+
+		try {
+			// Emulate an empty project
+			// import task check that projectHelper is at toplevel by checking
+			// the
+			// size of projectHelper.getImportTask()
+			ProjectHelper projectHelper = ProjectHelper.getProjectHelper();
+			File mainscript;
+			try {
+				mainscript = File.createTempFile(
+						EasyAntConstants.EASYANT_TASK_NAME, null);
+				mainscript.deleteOnExit();
+			} catch (IOException e1) {
+				throw new BuildException("Can't create temp file", e1);
+			}
+
+			@SuppressWarnings("unchecked")
+			Vector<File> imports = projectHelper.getImportStack();
+			imports.addElement(mainscript);
+			subModule.addReference(ProjectHelper.PROJECTHELPER_REFERENCE,
+					projectHelper);
+
+			// copy all User properties
+			addAlmostAll(getProject().getUserProperties(), subModule,
+					PropertyType.USER);
+
+			// copy easyantIvyInstance
+			IvyAntSettings ivyAntSettings = IvyInstanceHelper.getEasyAntIvyAntSettings(getProject());
+			subModule.addReference(EasyAntMagicNames.EASYANT_IVY_INSTANCE,
+					ivyAntSettings);
+
+			// 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());
+
+			// 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());
+			}
+
+			// Used to emulate top level target
+			Target topLevel = new Target();
+			topLevel.setName("");
+
+			LoadModule lm = new LoadModule();
+			lm.setBuildModule(file);
+			lm.setBuildFile(buildfile);
+			lm.setTaskName(EasyAntConstants.EASYANT_TASK_NAME);
+			lm.setProject(subModule);
+			lm.setOwningTarget(topLevel);
+			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.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;
+		}
+
+	}
+
+	/**
+	 * 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;
+	}
+
+	/**
+	 * 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);
+		}
+	}
+}

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

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

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

Added: 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=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/AbstractFindClassPathStrategy.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/AbstractFindClassPathStrategy.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,146 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.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;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.DataType;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Reference;
+
+public abstract class AbstractFindClassPathStrategy extends DataType {
+	public String pathid;
+	protected Path path;
+	private AbstractFindClassPathStrategy nextStrategy;
+	
+	
+	public boolean check() {
+		boolean result=doCheck();
+		if (!result) {
+			if (getNextStrategy()== null) {
+				return false;
+			} else {
+				return getNextStrategy().check();	
+			}
+			
+		} else {
+			return true;
+		}
+		
+	}
+	
+	protected abstract boolean doCheck();
+	
+	/**
+	 * Utilitary method to load cachepath
+	 * 
+	 * @param organisation
+	 *            organisation name
+	 * @param module
+	 *            module name
+	 * @param revision
+	 *            revision number
+	 * @param conf
+	 *            configuration name
+	 * @param ivyRef
+	 *            ivy instance reference
+	 */
+	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(" conf=").append(conf);
+		log(sb.toString(), Project.MSG_DEBUG);
+		IvyCachePath pluginCachePath = new IvyCachePath();
+		pluginCachePath.setOrganisation(organisation);
+		pluginCachePath.setModule(module);
+		pluginCachePath.setRevision(revision);
+		pluginCachePath.setConf(conf);
+		pluginCachePath.setPathid(getPathid());
+		pluginCachePath.setLog(LogOptions.LOG_DOWNLOAD_ONLY);
+		pluginCachePath.setInline(true);
+
+		pluginCachePath.setSettingsRef(ivyRef);
+		initTask(pluginCachePath).execute();
+
+	}
+	
+	/**
+	 * Utilitary method to build the classpath
+	 * 
+	 * @return a path
+	 */
+	protected Path getPath() {
+		if (path == null) {
+			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
+	 * @return the configured task
+	 */
+	protected Task initTask(Task task) {
+		task.setLocation(getLocation());
+		task.setProject(getProject());
+		//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() {
+		return IvyInstanceHelper.buildProjectIvyReference(getProject());
+	}
+
+	public String getPathid() {
+		return pathid;
+	}
+
+	public void setPathid(String pathid) {
+		this.pathid = pathid;
+	}
+	
+	public AbstractFindClassPathStrategy getNextStrategy() {
+		return nextStrategy;
+	}
+
+	public void setNextStrategy(AbstractFindClassPathStrategy nextStrategy) {
+		this.nextStrategy = nextStrategy;
+	}
+	
+	
+
+
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/BasicConfigurationStrategy.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/BasicConfigurationStrategy.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/BasicConfigurationStrategy.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/BasicConfigurationStrategy.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,89 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks.findclasspath;
+
+import org.apache.easyant.core.EasyAntMagicNames;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.Reference;
+
+public class BasicConfigurationStrategy extends AbstractFindClassPathStrategy{
+	private String organisation;
+	private String module;
+	private String revision;
+	private String conf = "default";
+	protected String settingsRef;
+
+	protected boolean doCheck() {
+		log("Checking plugin configuration ...",Project.MSG_VERBOSE);
+		loadCachePath(getOrganisation(), getModule(), getRevision(), getConf(),
+				getSettingsReference());
+		return true;
+	}
+
+	public String getOrganisation() {
+		return organisation;
+	}
+
+	public void setOrganisation(String organisation) {
+		this.organisation = organisation;
+	}
+
+	public String getModule() {
+		return module;
+	}
+
+	public void setModule(String module) {
+		this.module = module;
+	}
+
+	public String getRevision() {
+		return revision;
+	}
+
+	public void setRevision(String revision) {
+		this.revision = revision;
+	}
+
+	public String getConf() {
+		return conf;
+	}
+
+	public void setConf(String conf) {
+		this.conf = conf;
+	}
+
+	public String getSettingsRef() {
+		if (settingsRef == null) {
+			settingsRef= EasyAntMagicNames.EASYANT_IVY_INSTANCE;
+		}
+		return settingsRef;
+	}
+
+	public void setSettingsRef(String settingsRef) {
+		this.settingsRef = settingsRef;
+	}
+	
+	public Reference getSettingsReference() {
+		return new Reference(getProject(),getSettingsRef());
+	}
+	
+	
+	
+
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/EnvironmentStrategy.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/EnvironmentStrategy.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/EnvironmentStrategy.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/EnvironmentStrategy.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,83 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks.findclasspath;
+
+import java.io.File;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.FileSet;
+
+public class EnvironmentStrategy extends AbstractFindClassPathStrategy {
+
+	String env;
+	String layout = "/lib";
+	String filter;
+
+	public String getEnv() {
+		return env;
+	}
+
+	public void setEnv(String env) {
+		this.env = env;
+	}
+	
+
+	public String getLayout() {
+		return layout;
+	}
+
+	public void setLayout(String layout) {
+		this.layout = layout;
+	}
+	
+
+	public String getFilter() {
+		return filter;
+	}
+
+	public void setFilter(String filter) {
+		this.filter = filter;
+	}
+
+	/**
+	 * check environment variable
+	 * 
+	 * @return return true if the environment variable exist
+	 */
+	protected boolean doCheck() {
+		log("Checking environment variable ...", Project.MSG_VERBOSE);
+
+		if (getEnv() != null && System.getenv(getEnv()) != null) {
+			log(getEnv() + " found !", Project.MSG_VERBOSE);
+			File libDir = new File(System.getenv(getEnv()),getLayout());
+			FileSet fileSet = new FileSet();
+			fileSet.setDir(libDir);
+			fileSet.setIncludes(getFilter());
+			fileSet.setProject(getProject());
+			fileSet.setLocation(getLocation());
+
+			getPath().addFileset(fileSet);
+			getProject().addReference(getPathid(), getPath());
+			return true;
+		}
+		return false;
+
+	}
+
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/FindClasspathTask.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/FindClasspathTask.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/FindClasspathTask.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/FindClasspathTask.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,133 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks.findclasspath;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.easyant.tasks.AbstractEasyAntTask;
+import org.apache.tools.ant.BuildException;
+
+/**
+ * This task provides a mechanism to build a plugin classpath depending on
+ * rules.
+ */
+public class FindClasspathTask extends AbstractEasyAntTask {
+	private String pathid;
+	private String organisation;
+	private String module;
+	private String revision;
+	private String conf = "default";
+
+	private AbstractFindClassPathStrategy currentStrategy;
+	private List<AbstractFindClassPathStrategy> strategies = new ArrayList<AbstractFindClassPathStrategy>();
+
+	public void execute() throws BuildException {
+		//define the default strategy if there is no nested strategy
+		if (getStrategies().size() == 0) {
+			add(createStrategy(new ProjectDependencyStrategy()));
+			add(createStrategy(new BasicConfigurationStrategy()));
+		}
+		// Process the chain
+		getStrategies().get(0).check();
+	}
+
+	public String getPathid() {
+		return pathid;
+	}
+
+	public void setPathid(String pathid) {
+		this.pathid = pathid;
+	}
+
+	public String getOrganisation() {
+		return organisation;
+	}
+
+	public void setOrganisation(String organisation) {
+		this.organisation = organisation;
+	}
+
+	public String getModule() {
+		return module;
+	}
+
+	public void setModule(String module) {
+		this.module = module;
+	}
+
+	public String getRevision() {
+		return revision;
+	}
+
+	public void setRevision(String revision) {
+		this.revision = revision;
+	}
+
+	public String getConf() {
+		return conf;
+	}
+
+	public void setConf(String conf) {
+		this.conf = conf;
+	}
+
+	public List<AbstractFindClassPathStrategy> getStrategies() {
+		return strategies;
+	}
+
+	public void setStrategies(List<AbstractFindClassPathStrategy> strategies) {
+		this.strategies = strategies;
+	}
+
+	public void add(AbstractFindClassPathStrategy strategy) {
+		if (currentStrategy != null) {
+			currentStrategy.setNextStrategy(strategy);
+		}
+		currentStrategy = strategy;
+		preconfigureStrategy(strategy);
+		getStrategies().add(strategy);
+	}
+
+	protected void preconfigureStrategy(AbstractFindClassPathStrategy strategy) {
+		strategy.setPathid(getPathid());
+		if (strategy instanceof BasicConfigurationStrategy) {
+			BasicConfigurationStrategy basicStrategy = (BasicConfigurationStrategy) strategy;
+			if (basicStrategy.getOrganisation() == null) {
+				basicStrategy.setOrganisation(getOrganisation());
+			}
+			if (basicStrategy.getModule() == null) {
+				basicStrategy.setModule(getModule());
+
+			}
+			if (basicStrategy.getRevision() == null) {
+				basicStrategy.setRevision(getRevision());
+			}
+			if (basicStrategy.getConf() == null) {
+				basicStrategy.setConf(getConf());
+			}
+		}
+	}
+	
+	protected AbstractFindClassPathStrategy createStrategy(AbstractFindClassPathStrategy strategy) {
+		strategy.setProject(getProject());
+		return strategy;
+	}
+
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/ProjectDependencyStrategy.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/ProjectDependencyStrategy.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/ProjectDependencyStrategy.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/findclasspath/ProjectDependencyStrategy.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,167 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks.findclasspath;
+
+import java.io.File;
+
+import org.apache.easyant.core.ivy.IvyInstanceHelper;
+import org.apache.ivy.ant.IvyPostResolveTask;
+import org.apache.ivy.core.cache.ResolutionCacheManager;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.resolve.ResolveOptions;
+import org.apache.ivy.plugins.report.XmlReportParser;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+
+public class ProjectDependencyStrategy extends BasicConfigurationStrategy {
+
+	/**
+	 * check if project dependencies matches with expected module
+	 * 
+	 * @return return true if project dependencies matches with expected module
+	 */
+	@Override
+	protected boolean doCheck() {
+		log("Checking project dependencies ...", Project.MSG_VERBOSE);
+		CheckProjectDependencies checkProjectDependencies = new CheckProjectDependencies();
+		checkProjectDependencies.setSettingsRef(getSettingsReference());
+		checkProjectDependencies.setOrganisationToFind(getOrganisation());
+		checkProjectDependencies.setModuleToFind(getModule());
+		checkProjectDependencies.setRevisionToFind(getRevision());
+		checkProjectDependencies.setConfToFind(getConf());
+		initTask(checkProjectDependencies).execute();
+		return checkProjectDependencies.checkProjectDependencies();
+	}
+
+	@Override
+	public String getSettingsRef() {
+		if (settingsRef == null) {
+			settingsRef = IvyInstanceHelper.getProjectIvyInstanceName(getProject());
+		}
+		return settingsRef;
+	}
+
+	private class CheckProjectDependencies extends IvyPostResolveTask {
+
+		private String organisationToFind;
+		private String moduleToFind;
+		private String revisionToFind;
+		private String confToFind;
+
+		public String getOrganisationToFind() {
+			return organisationToFind;
+		}
+
+		public void setOrganisationToFind(String organisationToFind) {
+			this.organisationToFind = organisationToFind;
+		}
+
+		public String getModuleToFind() {
+			return moduleToFind;
+		}
+
+		public void setModuleToFind(String moduleToFind) {
+			this.moduleToFind = moduleToFind;
+		}
+
+		public String getRevisionToFind() {
+			return revisionToFind;
+		}
+
+		public void setRevisionToFind(String revisionToFind) {
+			this.revisionToFind = revisionToFind;
+		}
+
+		public String getConfToFind() {
+			return confToFind;
+		}
+
+		public void setConfToFind(String confToFind) {
+			this.confToFind = confToFind;
+		}
+
+		@Override
+		public void doExecute() throws BuildException {
+			prepareAndCheck();
+		}
+
+		public boolean checkProjectDependencies() {
+			execute();
+			try {
+				ResolutionCacheManager cacheMgr = getIvyInstance()
+						.getResolutionCacheManager();
+				String[] confs = splitConfs(getConf());
+				String resolveId = getResolveId();
+				if (resolveId == null) {
+					resolveId = ResolveOptions
+							.getDefaultResolveId(getResolvedModuleId());
+				}
+				XmlReportParser parser = new XmlReportParser();
+				for (int i = 0; i < confs.length; i++) {
+					File report = cacheMgr
+							.getConfigurationResolveReportInCache(resolveId,
+									confs[i]);
+					parser.parse(report);
+
+					Artifact[] artifacts = parser.getArtifacts();
+					for (int j = 0; j < artifacts.length; j++) {
+						Artifact artifact = artifacts[j];
+						ModuleRevisionId mrid = artifact.getModuleRevisionId();
+						if (mrid.getOrganisation().equals(
+								getOrganisationToFind())) {
+							if (mrid.getName().equals(getModuleToFind())) {
+								log(mrid.getOrganisation() + "#"
+										+ mrid.getName()
+										+ " found in project dependencies !",
+										Project.MSG_DEBUG);
+								// use this version
+								loadCachePath(getOrganisationToFind(),
+										getModuleToFind(), mrid.getRevision(),
+										getConfToFind(), getSettingsReference());
+								return true;
+							} else {
+								// if only organization is found in project
+								// dependencies use the same version with the
+								// required module
+								log(
+										"Only organisation : "
+												+ mrid.getOrganisation()
+												+ " was found in project dependencies !",
+										Project.MSG_DEBUG);
+								loadCachePath(mrid.getOrganisation(),
+										getModuleToFind(), mrid.getRevision(),
+										getConfToFind(), getSettingsReference());
+								return true;
+
+							}
+						}
+
+					}
+				}
+			} catch (Exception ex) {
+				throw new BuildException(
+						"impossible to check project dependencies: " + ex, ex);
+			}
+			return false;
+		}
+
+	}
+
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/AbstractMenuGeneratorTask.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/AbstractMenuGeneratorTask.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/AbstractMenuGeneratorTask.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/AbstractMenuGeneratorTask.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,60 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks.menu;
+
+import org.apache.easyant.core.EasyAntMagicNames;
+import org.apache.easyant.core.menu.MenuGeneratorRegistry;
+import org.apache.tools.ant.Task;
+
+/**
+ * Abstract class for MenuGenerator. 
+ * This task provides a few methods to retrieve the right MenuGeneratorRegistry
+ * for a given context. 
+ * If you're planning to write your own MenuGeneratorTask we strongly recommend you to extend this task.
+ */
+public abstract class AbstractMenuGeneratorTask extends Task{
+	
+	private String context="default";
+
+	/**
+	 * Get or create if necessary a MenuGeneratorRegistry for a given context;
+	 * @param context a string representing a given context
+	 * @return a MenuGeneratorRegistry
+	 */
+	public MenuGeneratorRegistry getMenuGeneratorForContext(String context) {
+		return MenuGeneratorUtils.getRegistryForContext(getProject(), context, true);
+	}
+
+	/**
+	 * Get the context
+	 * @return a context
+	 */
+	public String getContext() {
+		return context;
+	}
+
+	/**
+	 * Set the context
+	 * @param context a context
+	 */
+	public void setContext(String context) {
+		this.context = context;
+	}
+
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/AddMenuEntryTask.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/AddMenuEntryTask.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/AddMenuEntryTask.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/AddMenuEntryTask.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,119 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks.menu;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.easyant.core.menu.MenuGeneratorRegistry;
+import org.apache.tools.ant.BuildException;
+
+/**
+ * This task provides capabilities to add menu entries.
+ * This class is also responsible of finding the right {@link MenuGeneratorRegistry}
+ * and to propagate the generation to all registered implementations. 
+ *
+ */
+public class AddMenuEntryTask extends AbstractMenuGeneratorTask {
+
+	private String title;
+	private String targetLink;
+
+	private List<MenuEntry> menuEntries = new ArrayList<MenuEntry>();
+
+	@Override
+	public void execute() throws BuildException {
+		if (getTitle() == null && getTargetLink() == null && menuEntries.size() == 0) {
+			throw new BuildException("You must specfify a title and a target link as argument or as a nested element using a menuentry datatype !");
+		}
+		
+        try {
+            //handle argument
+            if (getTitle() != null && getTargetLink() != null) {
+                getMenuGeneratorForContext(getContext()).addEntry(getTitle(),
+                        getTargetLink());
+            }
+            //handle nested menuentry
+            for (MenuEntry menuItem : getMenuEntries()) {
+                getMenuGeneratorForContext(getContext()).addEntry(
+                        menuItem.getTitle(), menuItem.getTargetLink());
+            }
+        } catch (IOException ioe) {
+            throw new BuildException("Error writing menu entry: " + ioe.getMessage(), ioe);
+        }
+	}
+
+	/**
+	 * Get the title of the {@link MenuEntry}
+	 * @return a title
+	 */
+	public String getTitle() {
+		return title;
+	}
+
+	/**
+	 * Set the title of the {@link MenuEntry}
+	 * @param title a title
+	 */
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	/**
+	 * Get the target link of the {@link MenuEntry}
+	 * @return the target url
+	 */
+	public String getTargetLink() {
+		return targetLink;
+	}
+
+	/**
+	 * Set the target link of the {@link MenuEntry}
+	 * @param targetLink the target url
+	 */
+	public void setTargetLink(String targetLink) {
+		this.targetLink = targetLink;
+	}
+
+	/**
+	 * Get a list of nested {@link MenuEntry}
+	 * @return a list of {@link MenuEntry}
+	 */
+	public List<MenuEntry> getMenuEntries() {
+		return menuEntries;
+	}
+
+	/**
+	 * Set a list of nested {@link MenuEntry}
+	 * @param menuEntries a list of {@link MenuEntry}
+	 */
+	public void setMenuEntries(List<MenuEntry> menuEntries) {
+		this.menuEntries = menuEntries;
+	}
+
+	/**
+	 * Add a given {@link MenuEntry} 
+	 * @param menuEntry a given {@link MenuEntry}
+	 */
+	public void add(MenuEntry menuEntry) {
+		getMenuEntries().add(menuEntry);
+	}
+
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/EndMenuTask.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/EndMenuTask.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/EndMenuTask.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/EndMenuTask.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,40 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks.menu;
+
+import org.apache.easyant.core.menu.MenuGeneratorRegistry;
+import org.apache.tools.ant.BuildException;
+
+import java.io.IOException;
+
+public class EndMenuTask extends AbstractMenuGeneratorTask {
+    @Override
+    public void execute() throws BuildException {
+        String context = getContext();
+        if (context == null) {
+            throw new BuildException("context attribute is required");
+        }
+        MenuGeneratorRegistry registry = getMenuGeneratorForContext(context);
+        try {
+            registry.endMenu();
+        } catch (IOException ioe) {
+            throw new BuildException("Error ending menu " + context, ioe);
+        }
+    }
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/MenuEntry.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/MenuEntry.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/MenuEntry.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/MenuEntry.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,58 @@
+/* 
+ *  Copyright 2008-2010 the EasyAnt project
+ * 
+ *  See the NOTICE file distributed with this work for additional information
+ *  regarding copyright ownership. 
+ * 
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing, software 
+ *  distributed under the License is distributed on an "AS IS" BASIS, 
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and 
+ *  limitations under the License.
+ */
+package org.apache.easyant.tasks.menu;
+
+import org.apache.tools.ant.types.DataType;
+
+/**
+ * This {@link DataType} is a representation of an entry in a menu
+ */
+public class MenuEntry extends DataType {
+	private String title;
+	private String targetLink;
+	/**
+	 * Get the title
+	 * @return a title
+	 */
+	public String getTitle() {
+		return title;
+	}
+	/**
+	 * Set the title
+	 * @param title a title
+	 */
+	public void setTitle(String title) {
+		this.title = title;
+	}
+	/**
+	 * Get the target link
+	 * @return a target url
+	 */
+	public String getTargetLink() {
+		return targetLink;
+	}
+	/**
+	 * Set the target link
+	 * @param targetLink a target link
+	 */
+	public void setTargetLink(String targetLink) {
+		this.targetLink = targetLink;
+	}
+	
+}

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

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

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

Added: incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/MenuGeneratorUtils.java
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/MenuGeneratorUtils.java?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/MenuGeneratorUtils.java (added)
+++ incubator/easyant/core/trunk/src/main/java/org/apache/easyant/tasks/menu/MenuGeneratorUtils.java Thu Feb 17 17:01:07 2011
@@ -0,0 +1,30 @@
+package org.apache.easyant.tasks.menu;
+
+import org.apache.easyant.core.EasyAntMagicNames;
+import org.apache.easyant.core.menu.MenuGeneratorRegistry;
+import org.apache.tools.ant.Project;
+
+public class MenuGeneratorUtils {
+
+	public static MenuGeneratorRegistry createRegistryForContext(Project project, String context) {
+		MenuGeneratorRegistry menuGeneratorRegistry = new MenuGeneratorRegistry(context);
+		project.addReference(getReferenceId(context), menuGeneratorRegistry);
+        return menuGeneratorRegistry;
+	}
+
+	public static MenuGeneratorRegistry getRegistryForContext(Project project, String context, boolean create) {
+		MenuGeneratorRegistry registry = (MenuGeneratorRegistry) project.getReference(getReferenceId(context));
+		if (registry != null) {
+			return registry;
+		} else if (create) {
+			return createRegistryForContext(project, context);
+		} else {
+			throw new IllegalArgumentException("No menu generators are registered for " + context);
+		}
+	}
+
+	private static final String getReferenceId(String context) {
+		return context + EasyAntMagicNames.MENU_GENERATOR_REGISTRY_REF;
+	}
+
+}

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

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

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