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 [24/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/patches/extendsIvyFile-ivy-r766667.patch
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/patches/extendsIvyFile-ivy-r766667.patch?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/patches/extendsIvyFile-ivy-r766667.patch (added)
+++ incubator/easyant/core/trunk/src/main/patches/extendsIvyFile-ivy-r766667.patch Thu Feb 17 17:01:07 2011
@@ -0,0 +1,677 @@
+Index: src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java
+===================================================================
+--- src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java (révision 772962)
++++ src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java (copie de travail)
+@@ -31,6 +31,7 @@
+
+ import org.apache.ivy.Ivy;
+ import org.apache.ivy.core.IvyContext;
++import org.apache.ivy.core.cache.ResolutionCacheManager;
+ import org.apache.ivy.core.module.descriptor.Configuration;
+ import org.apache.ivy.core.module.descriptor.ConfigurationAware;
+ import org.apache.ivy.core.module.descriptor.DefaultArtifact;
+@@ -40,6 +41,7 @@
+ import org.apache.ivy.core.module.descriptor.DefaultIncludeRule;
+ import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+ import org.apache.ivy.core.module.descriptor.DependencyArtifactDescriptor;
++import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+ import org.apache.ivy.core.module.descriptor.ExcludeRule;
+ import org.apache.ivy.core.module.descriptor.IncludeRule;
+ import org.apache.ivy.core.module.descriptor.License;
+@@ -49,15 +51,23 @@
+ import org.apache.ivy.core.module.id.ArtifactId;
+ import org.apache.ivy.core.module.id.ModuleId;
+ import org.apache.ivy.core.module.id.ModuleRevisionId;
++import org.apache.ivy.core.resolve.ResolveData;
++import org.apache.ivy.core.resolve.ResolveEngine;
++import org.apache.ivy.core.resolve.ResolveOptions;
++import org.apache.ivy.core.resolve.ResolvedModuleRevision;
+ import org.apache.ivy.plugins.conflict.ConflictManager;
+ import org.apache.ivy.plugins.conflict.FixedConflictManager;
+ import org.apache.ivy.plugins.matcher.PatternMatcher;
+ import org.apache.ivy.plugins.namespace.Namespace;
+ import org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser;
+ import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
++import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
+ import org.apache.ivy.plugins.parser.ParserSettings;
+ import org.apache.ivy.plugins.repository.Resource;
+ import org.apache.ivy.plugins.repository.url.URLResource;
++import org.apache.ivy.plugins.resolver.CacheResolver;
++import org.apache.ivy.plugins.resolver.DependencyResolver;
++import org.apache.ivy.plugins.resolver.util.ResolvedResource;
+ import org.apache.ivy.util.Message;
+ import org.apache.ivy.util.XMLHelper;
+ import org.apache.ivy.util.extendable.ExtendableItemHelper;
+@@ -139,14 +149,10 @@
+ DefaultModuleDescriptor dmd = (DefaultModuleDescriptor) md;
+ ns = dmd.getNamespace();
+ }
+- XmlModuleDescriptorUpdater.update(is, res, destFile,
+- new UpdateOptions()
+- .setSettings(IvyContext.getContext().getSettings())
+- .setStatus(md.getStatus())
+- .setRevision(md.getResolvedModuleRevisionId().getRevision())
+- .setPubdate(md.getResolvedPublicationDate())
+- .setUpdateBranch(false)
+- .setNamespace(ns));
++ XmlModuleDescriptorUpdater.update(is, res, destFile, new UpdateOptions().setSettings(
++ IvyContext.getContext().getSettings()).setStatus(md.getStatus()).setRevision(
++ md.getResolvedModuleRevisionId().getRevision()).setPubdate(
++ md.getResolvedPublicationDate()).setUpdateBranch(false).setNamespace(ns));
+ } catch (SAXException e) {
+ ParseException ex = new ParseException("exception occured while parsing " + res, 0);
+ ex.initCause(e);
+@@ -181,37 +187,48 @@
+ public static final int EXCLUDE = 9;
+
+ public static final int DEPS = 10;
+-
++
+ public static final int DESCRIPTION = 11;
+
+ public static final int EXTRA_INFO = 12;
+-
++
+ private State() {
+ }
+ }
+
+- protected static final List ALLOWED_VERSIONS = Arrays.asList(
+- new String[] {"1.0", "1.1", "1.2", "1.3", "1.4", "2.0"});
++ protected static final List ALLOWED_VERSIONS = Arrays.asList(new String[] {"1.0", "1.1",
++ "1.2", "1.3", "1.4", "2.0"});
+
+ /* how and what do we have to parse */
+ private ParserSettings settings;
++
+ private boolean validate = true;
++
+ private URL descriptorURL;
++
+ private InputStream descriptorInput;
+
+-
+ /* Parsing state */
+ private int state = State.NONE;
++
+ private PatternMatcher defaultMatcher;
++
+ private DefaultDependencyDescriptor dd;
++
+ private ConfigurationAware confAware;
++
+ private MDArtifact artifact;
++
+ private String conf;
++
+ private boolean artifactsDeclared = false;
++
+ private StringBuffer buffer;
++
+ private String descriptorVersion;
++
+ private String[] publicationsDefaultConf;
+-
++
+ public Parser(ModuleDescriptorParser parser, ParserSettings ivySettings) {
+ super(parser);
+ settings = ivySettings;
+@@ -229,8 +246,7 @@
+ this.validate = validate;
+ }
+
+- public void parse() throws ParseException,
+- IOException {
++ public void parse() throws ParseException, IOException {
+ try {
+ URL schemaURL = validate ? getSchemaURL() : null;
+ if (descriptorURL != null) {
+@@ -241,14 +257,15 @@
+ checkConfigurations();
+ replaceConfigurationWildcards();
+ getMd().setModuleArtifact(
+- DefaultArtifact.newIvyArtifact(
+- getMd().getResolvedModuleRevisionId(), getMd().getPublicationDate()));
++ DefaultArtifact.newIvyArtifact(getMd().getResolvedModuleRevisionId(), getMd()
++ .getPublicationDate()));
+ if (!artifactsDeclared) {
+ String[] confs = getMd().getConfigurationsNames();
+ for (int i = 0; i < confs.length; i++) {
+- getMd().addArtifact(confs[i],
+- new MDArtifact(getMd(), getMd().getModuleRevisionId().getName(),
+- "jar", "jar"));
++ getMd().addArtifact(
++ confs[i],
++ new MDArtifact(getMd(), getMd().getModuleRevisionId().getName(), "jar",
++ "jar"));
+ }
+ }
+ getMd().check();
+@@ -269,16 +286,19 @@
+ throws SAXException {
+ try {
+ if (state == State.DESCRIPTION) {
+- //make sure we don't interpret any tag while in description tag
++ // make sure we don't interpret any tag while in description tag
+ buffer.append("<" + qName + ">");
+ return;
+ } else if ("ivy-module".equals(qName)) {
+ ivyModuleStarted(attributes);
+ } else if ("info".equals(qName)) {
+ infoStarted(attributes);
++ } else if (state == State.INFO && "extends".equals(qName)) {
++ extendsStarted(attributes);
+ } else if (state == State.INFO && "license".equals(qName)) {
+- getMd().addLicense(new License(settings.substitute(attributes.getValue("name")),
+- settings.substitute(attributes.getValue("url"))));
++ getMd().addLicense(
++ new License(settings.substitute(attributes.getValue("name")), settings
++ .substitute(attributes.getValue("url"))));
+ } else if (state == State.INFO && "description".equals(qName)) {
+ getMd().setHomePage(settings.substitute(attributes.getValue("homepage")));
+ state = State.DESCRIPTION;
+@@ -299,7 +319,8 @@
+ } else if ("conflicts".equals(qName)) {
+ if (!descriptorVersion.startsWith("1.")) {
+ Message.deprecated("using conflicts section is deprecated: "
+- + "please use hints section instead. Ivy file URL: " + descriptorURL);
++ + "please use hints section instead. Ivy file URL: "
++ + descriptorURL);
+ }
+ state = State.CONFLICT;
+ checkConfigurations();
+@@ -341,6 +362,185 @@
+ }
+ }
+
++ protected String getDefaultParentLocation() {
++ return "../ivy.xml";
++ }
++
++ protected void extendsStarted(Attributes attributes) throws ParseException {
++ String parentOrganisation = attributes.getValue("organisation");
++ String parentModule = attributes.getValue("name");
++ String parentRevision = attributes.getValue("revision");
++ String location = attributes.getValue("location") != null ? attributes
++ .getValue("location") : getDefaultParentLocation();
++ ModuleDescriptor parent = null;
++
++ String extendType = attributes.getValue("extendType") != null ? attributes.getValue(
++ "extendType").toLowerCase() : "all";
++
++ List/* <String> */extendTypes = Arrays.asList(extendType.split(","));
++
++ try {
++ Message.debug("Trying to parse included ivy file :" + location);
++ parent = parseOtherIvyFileOnFileSystem(location);
++ } catch (ParseException e) {
++ Message.warn("Unable to parse included ivy file : " + location);
++ } catch (IOException e) {
++ Message.warn("Unable to parse included ivy file : " + location);
++ }
++
++ // if the included ivy file is not found on file system, tries to resolve using
++ // repositories
++ if (parent == null) {
++ try {
++ Message
++ .debug("Trying to parse included ivy file by asking repository for module :"
++ + parentOrganisation
++ + "#"
++ + parentModule
++ + ";"
++ + parentRevision);
++ parent = parseOtherIvyFile(parentOrganisation, parentModule, parentRevision);
++ } catch (ParseException e) {
++ Message.warn("Unable to parse included ivy file for " + parentOrganisation
++ + "#" + parentModule + ";" + parentRevision);
++ }
++ }
++
++ if (parent == null) {
++ throw new ParseException("Unable to parse included ivy file for "
++ + parentOrganisation + "#" + parentModule + ";" + parentRevision, 0);
++ }
++
++ ResolutionCacheManager cacheManager = settings.getResolutionCacheManager();
++
++ File ivyFileInCache = cacheManager.getResolvedIvyFileInCache(parent
++ .getResolvedModuleRevisionId());
++ //Generate the parent cache file if necessary
++ if (parent.getResource() != null
++ && !parent.getResource().getName().equals(ivyFileInCache.toURI().toString())) {
++ try {
++ parent.toIvyFile(ivyFileInCache);
++ } catch (ParseException e) {
++ throw new ParseException("Unable to create cache file for "
++ + parentOrganisation + "#" + parentModule + ";" + parentRevision
++ + " Reason:" + e.getLocalizedMessage(), 0);
++ } catch (IOException e) {
++ throw new ParseException("Unable to create cache file for "
++ + parentOrganisation + "#" + parentModule + ";" + parentRevision
++ + " Reason :" + e.getLocalizedMessage(), 0);
++ }
++ }
++ mergeWithOtherModuleDescriptor(extendTypes, parent);
++ }
++
++ protected void mergeWithOtherModuleDescriptor(List/* <String> */extendTypes,
++ ModuleDescriptor parent) {
++
++ if (extendTypes.contains("all")) {
++ mergeAll(parent);
++ } else {
++ if (extendTypes.contains("configurations")) {
++ mergeConfigurations(parent.getConfigurations());
++ }
++
++ if (extendTypes.contains("dependencies")) {
++ mergeDependencies(parent.getDependencies());
++ }
++
++ if (extendTypes.contains("description")) {
++ mergeDescription(parent.getDescription());
++ }
++ }
++
++ }
++
++ protected void mergeAll(ModuleDescriptor parent) {
++ mergeConfigurations(parent.getConfigurations());
++ mergeDependencies(parent.getDependencies());
++ mergeDescription(parent.getDescription());
++ }
++
++ protected void mergeConfigurations(Configuration[] configurations) {
++ for (int i = 0; i < configurations.length; i++) {
++ Configuration configuration = configurations[i];
++ Message.debug("Merging configuration with: " + configuration.getName());
++ // TODO: Here we need to merge configuration
++ getMd().addConfiguration(configuration);
++ }
++ }
++
++ protected void mergeDependencies(DependencyDescriptor[] dependencies) {
++ for (int i = 0; i < dependencies.length; i++) {
++ DependencyDescriptor dependencyDescriptor = dependencies[i];
++ Message.debug("Merging dependency with: "
++ + dependencyDescriptor.getDependencyRevisionId().toString());
++ // TODO: Here we need to merge dependencies
++ getMd().addDependency(dependencyDescriptor);
++ }
++ }
++
++ protected void mergeDescription(String description) {
++ if (getMd().getDescription() == null)
++ getMd().setDescription(description);
++ }
++
++ protected ModuleDescriptor parseOtherIvyFileOnFileSystem(String location)
++ throws ParseException, IOException {
++ URL url = null;
++ ModuleDescriptor parent = null;
++ url = getSettings().getRelativeUrlResolver().getURL(descriptorURL, location);
++ Message.debug("Trying to load included ivy file from " + url.toString());
++ URLResource res = new URLResource(url);
++ ModuleDescriptorParser parser = ModuleDescriptorParserRegistry.getInstance().getParser(
++ res);
++
++ parent = parser.parseDescriptor(getSettings(), url, isValidate());
++ return parent;
++ }
++
++ protected ModuleDescriptor parseOtherIvyFile(String parentOrganisation,
++ String parentModule, String parentRevision) throws ParseException {
++ ModuleId parentModuleId = new ModuleId(parentOrganisation, parentModule);
++ ModuleRevisionId parentMrid = new ModuleRevisionId(parentModuleId, parentRevision);
++
++ // try to load parent module in cache
++ File cacheFile = settings.getResolutionCacheManager().getResolvedIvyFileInCache(
++ ModuleRevisionId.newInstance(parentMrid, Ivy.getWorkingRevision()));
++ if (cacheFile.exists() && cacheFile.length() > 0) {
++ ModuleDescriptor md;
++ try {
++ Message.debug("Trying to load included ivy file from cache");
++ URL parentUrl = cacheFile.toURI().toURL();
++ md = parseOtherIvyFileOnFileSystem(parentUrl.toString());
++ return md;
++ } catch (IOException e) {
++ // do nothing
++ Message.error(e.getLocalizedMessage());
++ }
++ }
++
++ DependencyDescriptor dd = new DefaultDependencyDescriptor(parentMrid, true);
++ ResolveData data = IvyContext.getContext().getResolveData();
++ if (data == null) {
++ ResolveEngine engine = IvyContext.getContext().getIvy().getResolveEngine();
++ ResolveOptions options = new ResolveOptions();
++ options.setDownload(false);
++ data = new ResolveData(engine, options);
++ }
++
++ DependencyResolver resolver = getSettings().getResolver(parentMrid);
++ if (resolver == null) {
++ // TODO: Throw exception here?
++ return null;
++ } else {
++ ResolvedModuleRevision otherModule = resolver.getDependency(dd, data);
++ if (otherModule == null)
++ throw new ParseException("Unable to find " + parentMrid.toString(), 0);
++ return otherModule.getDescriptor();
++ }
++
++ }
++
+ protected void publicationsStarted(Attributes attributes) {
+ state = State.PUB;
+ artifactsDeclared = true;
+@@ -407,28 +607,27 @@
+ addError("unknown matcher: " + matcherName);
+ return;
+ }
+- getMd().addDependencyDescriptorMediator(
+- new ModuleId(org, mod), matcher,
++ getMd().addDependencyDescriptorMediator(new ModuleId(org, mod), matcher,
+ new OverrideDependencyDescriptorMediator(branch, rev));
+ }
+
+- protected void includeConfStarted(Attributes attributes)
+- throws SAXException, IOException, ParserConfigurationException, ParseException {
++ protected void includeConfStarted(Attributes attributes) throws SAXException, IOException,
++ ParserConfigurationException, ParseException {
+ URL url = settings.getRelativeUrlResolver().getURL(descriptorURL,
+- settings.substitute(attributes.getValue("file")),
+- settings.substitute(attributes.getValue("url")));
+-
++ settings.substitute(attributes.getValue("file")),
++ settings.substitute(attributes.getValue("url")));
++
+ if (url == null) {
+ throw new SAXException("include tag must have a file or an url attribute");
+ }
+-
++
+ // create a new temporary parser to read the configurations from
+ // the specified file.
+ Parser parser = new Parser(getModuleDescriptorParser(), settings);
+ parser.setInput(url);
+- parser.setMd(new DefaultModuleDescriptor(getModuleDescriptorParser(),
+- new URLResource(url)));
+- XMLHelper.parse(url , null, parser);
++ parser.setMd(new DefaultModuleDescriptor(getModuleDescriptorParser(), new URLResource(
++ url)));
++ XMLHelper.parse(url, null, parser);
+
+ // add the configurations from this temporary parser to this module descriptor
+ Configuration[] configs = parser.getModuleDescriptor().getConfigurations();
+@@ -441,8 +640,7 @@
+ setDefaultConfMapping(parser.getDefaultConfMapping());
+ }
+ if (parser.getMd().isMappingOverride()) {
+- Message.debug("enabling mapping-override from imported configurations"
+- + " file");
++ Message.debug("enabling mapping-override from imported configurations" + " file");
+ getMd().setMappingOverride(true);
+ }
+ }
+@@ -454,18 +652,16 @@
+ String visibility = settings.substitute(attributes.getValue("visibility"));
+ String ext = settings.substitute(attributes.getValue("extends"));
+ String transitiveValue = attributes.getValue("transitive");
+- boolean transitive = (transitiveValue == null) ? true : Boolean
+- .valueOf(attributes.getValue("transitive")).booleanValue();
++ boolean transitive = (transitiveValue == null) ? true : Boolean.valueOf(
++ attributes.getValue("transitive")).booleanValue();
+ String deprecated = attributes.getValue("deprecated");
+- Configuration configuration = new Configuration(conf,
+- Configuration.Visibility
+- .getVisibility(visibility == null ? "public"
+- : visibility), settings.substitute(attributes
+- .getValue("description")), ext == null ? null : ext
+- .split(","), transitive, deprecated);
++ Configuration configuration = new Configuration(conf, Configuration.Visibility
++ .getVisibility(visibility == null ? "public" : visibility), settings
++ .substitute(attributes.getValue("description")), ext == null ? null
++ : ext.split(","), transitive, deprecated);
+ ExtendableItemHelper.fillExtraAttributes(settings, configuration, attributes,
+- new String[] {"name", "visibility", "extends", "transitive",
+- "description", "deprecated"});
++ new String[] {"name", "visibility", "extends", "transitive", "description",
++ "deprecated"});
+ getMd().addConfiguration(configuration);
+ break;
+ case State.PUB:
+@@ -511,8 +707,8 @@
+ }
+ boolean force = Boolean.valueOf(settings.substitute(attributes.getValue("force")))
+ .booleanValue();
+- boolean changing = Boolean.valueOf(
+- settings.substitute(attributes.getValue("changing"))).booleanValue();
++ boolean changing = Boolean
++ .valueOf(settings.substitute(attributes.getValue("changing"))).booleanValue();
+
+ String transitiveValue = settings.substitute(attributes.getValue("transitive"));
+ boolean transitive = (transitiveValue == null) ? true : Boolean.valueOf(
+@@ -524,14 +720,11 @@
+ String rev = settings.substitute(attributes.getValue("rev"));
+ String revConstraint = settings.substitute(attributes.getValue("revConstraint"));
+ revConstraint = revConstraint == null ? rev : revConstraint;
+- Map extraAttributes = ExtendableItemHelper.getExtraAttributes(
+- settings, attributes, DEPENDENCY_REGULAR_ATTRIBUTES);
+- dd = new DefaultDependencyDescriptor(
+- getMd(),
+- ModuleRevisionId.newInstance(org, name, branch, rev, extraAttributes),
+- ModuleRevisionId.newInstance(
+- org, name, branchConstraint, revConstraint, extraAttributes),
+- force, changing, transitive);
++ Map extraAttributes = ExtendableItemHelper.getExtraAttributes(settings, attributes,
++ DEPENDENCY_REGULAR_ATTRIBUTES);
++ dd = new DefaultDependencyDescriptor(getMd(), ModuleRevisionId.newInstance(org, name,
++ branch, rev, extraAttributes), ModuleRevisionId.newInstance(org, name,
++ branchConstraint, revConstraint, extraAttributes), force, changing, transitive);
+ getMd().addDependency(dd);
+ String confs = settings.substitute(attributes.getValue("conf"));
+ if (confs != null && confs.length() > 0) {
+@@ -539,7 +732,7 @@
+ }
+ }
+
+- protected void artifactStarted(String qName, Attributes attributes)
++ protected void artifactStarted(String qName, Attributes attributes)
+ throws MalformedURLException {
+ if (state == State.PUB) {
+ // this is a published artifact
+@@ -551,8 +744,8 @@
+ ext = ext != null ? ext : type;
+ String url = settings.substitute(attributes.getValue("url"));
+ artifact = new MDArtifact(getMd(), artName, type, ext, url == null ? null
+- : new URL(url), ExtendableItemHelper.getExtraAttributes(
+- settings, attributes, new String[] {"ext", "type", "name", "conf"}));
++ : new URL(url), ExtendableItemHelper.getExtraAttributes(settings,
++ attributes, new String[] {"ext", "type", "name", "conf"}));
+ String confs = settings.substitute(attributes.getValue("conf"));
+ // only add confs if they are specified. if they aren't, endElement will
+ // handle this
+@@ -597,12 +790,10 @@
+
+ protected void configurationStarted(Attributes attributes) {
+ state = State.CONF;
+- setDefaultConfMapping(settings
+- .substitute(attributes.getValue("defaultconfmapping")));
+- getMd()
+- .setMappingOverride(Boolean.valueOf(
+- settings.substitute(attributes.getValue("confmappingoverride")))
+- .booleanValue());
++ setDefaultConfMapping(settings.substitute(attributes.getValue("defaultconfmapping")));
++ getMd().setMappingOverride(
++ Boolean.valueOf(settings.substitute(attributes.getValue("confmappingoverride")))
++ .booleanValue());
+ }
+
+ protected void infoStarted(Attributes attributes) {
+@@ -611,28 +802,30 @@
+ String module = settings.substitute(attributes.getValue("module"));
+ String revision = settings.substitute(attributes.getValue("revision"));
+ String branch = settings.substitute(attributes.getValue("branch"));
+- getMd().setModuleRevisionId(ModuleRevisionId.newInstance(org, module, branch,
+- revision, ExtendableItemHelper.getExtraAttributes(settings, attributes,
+- new String[] {
+- "organisation", "module", "revision", "status", "publication",
+- "branch", "namespace", "default", "resolver"})));
++ getMd().setModuleRevisionId(
++ ModuleRevisionId.newInstance(org, module, branch, revision, ExtendableItemHelper
++ .getExtraAttributes(settings, attributes, new String[] {"organisation",
++ "module", "revision", "status", "publication", "branch",
++ "namespace", "default", "resolver"})));
+
+ String namespace = settings.substitute(attributes.getValue("namespace"));
+ if (namespace != null) {
+ Namespace ns = settings.getNamespace(namespace);
+ if (ns == null) {
+- Message.warn("namespace not found for " + getMd().getModuleRevisionId()
+- + ": " + namespace);
++ Message.warn("namespace not found for " + getMd().getModuleRevisionId() + ": "
++ + namespace);
+ } else {
+ getMd().setNamespace(ns);
+ }
+ }
+
+ String status = settings.substitute(attributes.getValue("status"));
+- getMd().setStatus(status == null ? settings.getStatusManager().getDefaultStatus()
+- : status);
+- getMd().setDefault(Boolean.valueOf(settings.substitute(attributes.getValue("default")))
+- .booleanValue());
++ getMd().setStatus(
++ status == null ? settings.getStatusManager().getDefaultStatus() : status);
++ getMd()
++ .setDefault(
++ Boolean.valueOf(settings.substitute(attributes.getValue("default")))
++ .booleanValue());
+ String pubDate = settings.substitute(attributes.getValue("publication"));
+ if (pubDate != null && pubDate.length() > 0) {
+ try {
+@@ -662,12 +855,13 @@
+ + " as default matcher");
+ defaultMatcher = settings.getMatcher(PatternMatcher.EXACT_OR_REGEXP);
+ }
+-
++
+ for (int i = 0; i < attributes.getLength(); i++) {
+ if (attributes.getQName(i).startsWith("xmlns:")) {
+- getMd().addExtraAttributeNamespace(
+- attributes.getQName(i).substring("xmlns:".length()),
+- attributes.getValue(i));
++ getMd()
++ .addExtraAttributeNamespace(
++ attributes.getQName(i).substring("xmlns:".length()),
++ attributes.getValue(i));
+ }
+ }
+ }
+@@ -678,13 +872,13 @@
+ parseRule(tag, attributes);
+ }
+
+- protected void addIncludeRule(String tag, Attributes attributes)
++ protected void addIncludeRule(String tag, Attributes attributes)
+ throws MalformedURLException {
+ state = State.ARTIFACT_INCLUDE;
+ parseRule(tag, attributes);
+ }
+
+- protected void addExcludeRule(String tag, Attributes attributes)
++ protected void addExcludeRule(String tag, Attributes attributes)
+ throws MalformedURLException {
+ state = State.ARTIFACT_EXCLUDE;
+ parseRule(tag, attributes);
+@@ -707,7 +901,7 @@
+ ext = ext != null ? ext : type;
+ if (state == State.DEP_ARTIFACT) {
+ String url = settings.substitute(attributes.getValue("url"));
+- Map extraAtt = ExtendableItemHelper.getExtraAttributes(settings, attributes,
++ Map extraAtt = ExtendableItemHelper.getExtraAttributes(settings, attributes,
+ new String[] {"name", "type", "ext", "url", "conf"});
+ confAware = new DefaultDependencyArtifactDescriptor(dd, name, type, ext,
+ url == null ? null : new URL(url), extraAtt);
+@@ -718,7 +912,7 @@
+ String module = settings.substitute(attributes.getValue("module"));
+ module = module == null ? PatternMatcher.ANY_EXPRESSION : module;
+ ArtifactId aid = new ArtifactId(new ModuleId(org, module), name, type, ext);
+- Map extraAtt = ExtendableItemHelper.getExtraAttributes(settings, attributes,
++ Map extraAtt = ExtendableItemHelper.getExtraAttributes(settings, attributes,
+ new String[] {"org", "module", "name", "type", "ext", "matcher", "conf"});
+ confAware = new DefaultIncludeRule(aid, matcher, extraAtt);
+ } else { // _state == ARTIFACT_EXCLUDE || EXCLUDE
+@@ -728,7 +922,7 @@
+ String module = settings.substitute(attributes.getValue("module"));
+ module = module == null ? PatternMatcher.ANY_EXPRESSION : module;
+ ArtifactId aid = new ArtifactId(new ModuleId(org, module), name, type, ext);
+- Map extraAtt = ExtendableItemHelper.getExtraAttributes(settings, attributes,
++ Map extraAtt = ExtendableItemHelper.getExtraAttributes(settings, attributes,
+ new String[] {"org", "module", "name", "type", "ext", "matcher", "conf"});
+ confAware = new DefaultExcludeRule(aid, matcher, extraAtt);
+ }
+@@ -780,20 +974,17 @@
+ return matcher;
+ }
+
+-
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ if (buffer != null) {
+ buffer.append(ch, start, length);
+- }
++ }
+ }
+
+-
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (state == State.PUB && "artifact".equals(qName)
+ && artifact.getConfigurations().length == 0) {
+- String[] confs = publicationsDefaultConf == null
+- ? getMd().getConfigurationsNames()
+- : publicationsDefaultConf;
++ String[] confs = publicationsDefaultConf == null ? getMd().getConfigurationsNames()
++ : publicationsDefaultConf;
+ for (int i = 0; i < confs.length; i++) {
+ artifact.addConfiguration(confs[i].trim());
+ getMd().addArtifact(confs[i].trim(), artifact);
+Index: src/java/org/apache/ivy/plugins/parser/xml/ivy.xsd
+===================================================================
+--- src/java/org/apache/ivy/plugins/parser/xml/ivy.xsd (révision 772962)
++++ src/java/org/apache/ivy/plugins/parser/xml/ivy.xsd (copie de travail)
+@@ -60,6 +60,15 @@
+ <xs:element name="info">
+ <xs:complexType>
+ <xs:sequence>
++ <xs:element name="extends" minOccurs="0" maxOccurs="unbounded">
++ <xs:complexType>
++ <xs:attribute name="organisation" type="xs:string" use="required"/>
++ <xs:attribute name="name" type="xs:string" use="required"/>
++ <xs:attribute name="revision" type="xs:string" use="required"/>
++ <xs:attribute name="location" type="xs:string" />
++ <xs:attribute name="extendType" type="xs:string" />
++ </xs:complexType>
++ </xs:element>
+ <xs:element name="license" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+@@ -141,7 +150,7 @@
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+- <xs:attribute name="defaultconf" type="xs:string"/>
++ <xs:attribute name="defaultconf" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="dependencies" minOccurs="0">
+@@ -220,7 +229,7 @@
+ <xs:attribute name="org" type="xs:string"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="branch" type="xs:string"/>
+- <xs:attribute name="branchConstraint" type="xs:string"/>
++ <xs:attribute name="branchConstraint" type="xs:string"/>
+ <xs:attribute name="rev" type="xs:string" use="required"/>
+ <xs:attribute name="revConstraint" type="xs:string"/>
+ <xs:attribute name="force" type="xs:boolean"/>
Added: incubator/easyant/core/trunk/src/main/patches/extendsIvyFile-ivy-r886938.patch
URL: http://svn.apache.org/viewvc/incubator/easyant/core/trunk/src/main/patches/extendsIvyFile-ivy-r886938.patch?rev=1071697&view=auto
==============================================================================
--- incubator/easyant/core/trunk/src/main/patches/extendsIvyFile-ivy-r886938.patch (added)
+++ incubator/easyant/core/trunk/src/main/patches/extendsIvyFile-ivy-r886938.patch Thu Feb 17 17:01:07 2011
@@ -0,0 +1,948 @@
+Index: src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java
+===================================================================
+--- src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java (revision 887799)
++++ src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java (working copy)
+@@ -31,6 +31,7 @@
+
+ import org.apache.ivy.Ivy;
+ import org.apache.ivy.core.IvyContext;
++import org.apache.ivy.core.cache.ResolutionCacheManager;
+ import org.apache.ivy.core.module.descriptor.Configuration;
+ import org.apache.ivy.core.module.descriptor.ConfigurationAware;
+ import org.apache.ivy.core.module.descriptor.DefaultArtifact;
+@@ -40,6 +41,7 @@
+ import org.apache.ivy.core.module.descriptor.DefaultIncludeRule;
+ import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+ import org.apache.ivy.core.module.descriptor.DependencyArtifactDescriptor;
++import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+ import org.apache.ivy.core.module.descriptor.ExcludeRule;
+ import org.apache.ivy.core.module.descriptor.IncludeRule;
+ import org.apache.ivy.core.module.descriptor.License;
+@@ -49,15 +51,21 @@
+ import org.apache.ivy.core.module.id.ArtifactId;
+ import org.apache.ivy.core.module.id.ModuleId;
+ import org.apache.ivy.core.module.id.ModuleRevisionId;
++import org.apache.ivy.core.resolve.ResolveData;
++import org.apache.ivy.core.resolve.ResolveEngine;
++import org.apache.ivy.core.resolve.ResolveOptions;
++import org.apache.ivy.core.resolve.ResolvedModuleRevision;
+ import org.apache.ivy.plugins.conflict.ConflictManager;
+ import org.apache.ivy.plugins.conflict.FixedConflictManager;
+ import org.apache.ivy.plugins.matcher.PatternMatcher;
+ import org.apache.ivy.plugins.namespace.Namespace;
+ import org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser;
+ import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
++import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
+ import org.apache.ivy.plugins.parser.ParserSettings;
+ import org.apache.ivy.plugins.repository.Resource;
+ import org.apache.ivy.plugins.repository.url.URLResource;
++import org.apache.ivy.plugins.resolver.DependencyResolver;
+ import org.apache.ivy.util.Message;
+ import org.apache.ivy.util.XMLHelper;
+ import org.apache.ivy.util.extendable.ExtendableItemHelper;
+@@ -269,13 +277,15 @@
+ throws SAXException {
+ try {
+ if (state == State.DESCRIPTION) {
+- //make sure we don't interpret any tag while in description tag
++ // make sure we don't interpret any tag while in description tag
+ buffer.append("<" + qName + ">");
+ return;
+ } else if ("ivy-module".equals(qName)) {
+ ivyModuleStarted(attributes);
+ } else if ("info".equals(qName)) {
+ infoStarted(attributes);
++ } else if (state == State.INFO && "extends".equals(qName)) {
++ extendsStarted(attributes);
+ } else if (state == State.INFO && "license".equals(qName)) {
+ getMd().addLicense(new License(settings.substitute(attributes.getValue("name")),
+ settings.substitute(attributes.getValue("url"))));
+@@ -341,6 +351,200 @@
+ }
+ }
+
++ protected String getDefaultParentLocation() {
++ return "../ivy.xml";
++ }
++
++ protected void extendsStarted(Attributes attributes) throws ParseException {
++ String parentOrganisation = attributes.getValue("organisation");
++ String parentModule = attributes.getValue("module");
++ String parentRevision = attributes.getValue("revision");
++ String location = attributes.getValue("location") != null ? attributes
++ .getValue("location") : getDefaultParentLocation();
++ ModuleDescriptor parent = null;
++
++ String extendType = attributes.getValue("extendType") != null ? attributes.getValue(
++ "extendType").toLowerCase() : "all";
++
++ List/* <String> */extendTypes = Arrays.asList(extendType.split(","));
++
++ try {
++ Message.debug("Trying to parse included ivy file :" + location);
++ parent = parseOtherIvyFileOnFileSystem(location);
++
++ //verify that the parsed descriptor is the correct parent module.
++ ModuleId expected = new ModuleId(parentOrganisation, parentModule);
++ ModuleId pid = parent.getModuleRevisionId().getModuleId();
++ if (!expected.equals(pid)) {
++ Message.verbose("Ignoring parent Ivy file " + location + "; expected "
++ + expected + " but found " + pid);
++ parent = null;
++ }
++
++ } catch (ParseException e) {
++ Message.warn("Unable to parse included ivy file " + location + ": "
++ + e.getMessage());
++ } catch (IOException e) {
++ Message.warn("Unable to parse included ivy file " + location + ": "
++ + e.getMessage());
++ }
++
++ // if the included ivy file is not found on file system, tries to resolve using
++ // repositories
++ if (parent == null) {
++ try {
++ Message.debug(
++ "Trying to parse included ivy file by asking repository for module :"
++ + parentOrganisation
++ + "#"
++ + parentModule
++ + ";"
++ + parentRevision);
++ parent = parseOtherIvyFile(parentOrganisation, parentModule, parentRevision);
++ } catch (ParseException e) {
++ Message.warn("Unable to parse included ivy file for " + parentOrganisation
++ + "#" + parentModule + ";" + parentRevision);
++ }
++ }
++
++ if (parent == null) {
++ throw new ParseException("Unable to parse included ivy file for "
++ + parentOrganisation + "#" + parentModule + ";" + parentRevision, 0);
++ }
++
++ ResolutionCacheManager cacheManager = settings.getResolutionCacheManager();
++
++ File ivyFileInCache = cacheManager.getResolvedIvyFileInCache(parent
++ .getResolvedModuleRevisionId());
++ //Generate the parent cache file if necessary
++ if (parent.getResource() != null
++ && !parent.getResource().getName().equals(ivyFileInCache.toURI().toString())) {
++ try {
++ parent.toIvyFile(ivyFileInCache);
++ } catch (ParseException e) {
++ throw new ParseException("Unable to create cache file for "
++ + parentOrganisation + "#" + parentModule + ";" + parentRevision
++ + " Reason:" + e.getLocalizedMessage(), 0);
++ } catch (IOException e) {
++ throw new ParseException("Unable to create cache file for "
++ + parentOrganisation + "#" + parentModule + ";" + parentRevision
++ + " Reason :" + e.getLocalizedMessage(), 0);
++ }
++ }
++ mergeWithOtherModuleDescriptor(extendTypes, parent);
++ }
++
++ protected void mergeWithOtherModuleDescriptor(List/* <String> */extendTypes,
++ ModuleDescriptor parent) {
++
++ if (extendTypes.contains("all")) {
++ mergeAll(parent);
++ } else {
++ if (extendTypes.contains("configurations")) {
++ mergeConfigurations(parent.getConfigurations());
++ }
++
++ if (extendTypes.contains("dependencies")) {
++ mergeDependencies(parent.getDependencies());
++ }
++
++ if (extendTypes.contains("description")) {
++ mergeDescription(parent.getDescription());
++ }
++ }
++
++ }
++
++ protected void mergeAll(ModuleDescriptor parent) {
++ mergeConfigurations(parent.getConfigurations());
++ mergeDependencies(parent.getDependencies());
++ mergeDescription(parent.getDescription());
++ }
++
++ protected void mergeConfigurations(Configuration[] configurations) {
++ for (int i = 0; i < configurations.length; i++) {
++ Configuration configuration = configurations[i];
++ Message.debug("Merging configuration with: " + configuration.getName());
++ // TODO: Here we need to merge configuration
++ getMd().addConfiguration(configuration);
++ }
++ }
++
++ protected void mergeDependencies(DependencyDescriptor[] dependencies) {
++ for (int i = 0; i < dependencies.length; i++) {
++ DependencyDescriptor dependencyDescriptor = dependencies[i];
++ Message.debug("Merging dependency with: "
++ + dependencyDescriptor.getDependencyRevisionId().toString());
++ // TODO: Here we need to merge dependencies
++ getMd().addDependency(dependencyDescriptor);
++ }
++ }
++
++ protected void mergeDescription(String description) {
++ String current = getMd().getDescription();
++ if (current == null || current.trim().length() == 0) {
++ getMd().setDescription(description);
++ }
++ }
++
++ protected ModuleDescriptor parseOtherIvyFileOnFileSystem(String location)
++ throws ParseException, IOException {
++ URL url = null;
++ ModuleDescriptor parent = null;
++ url = getSettings().getRelativeUrlResolver().getURL(descriptorURL, location);
++ Message.debug("Trying to load included ivy file from " + url.toString());
++ URLResource res = new URLResource(url);
++ ModuleDescriptorParser parser = ModuleDescriptorParserRegistry.getInstance().getParser(
++ res);
++
++ parent = parser.parseDescriptor(getSettings(), url, isValidate());
++ return parent;
++ }
++
++ protected ModuleDescriptor parseOtherIvyFile(String parentOrganisation,
++ String parentModule, String parentRevision) throws ParseException {
++ ModuleId parentModuleId = new ModuleId(parentOrganisation, parentModule);
++ ModuleRevisionId parentMrid = new ModuleRevisionId(parentModuleId, parentRevision);
++
++ // try to load parent module in cache
++ File cacheFile = settings.getResolutionCacheManager().getResolvedIvyFileInCache(
++ ModuleRevisionId.newInstance(parentMrid, Ivy.getWorkingRevision()));
++ if (cacheFile.exists() && cacheFile.length() > 0) {
++ ModuleDescriptor md;
++ try {
++ Message.debug("Trying to load included ivy file from cache");
++ URL parentUrl = cacheFile.toURI().toURL();
++ md = parseOtherIvyFileOnFileSystem(parentUrl.toString());
++ return md;
++ } catch (IOException e) {
++ // do nothing
++ Message.error(e.getLocalizedMessage());
++ }
++ }
++
++ DependencyDescriptor dd = new DefaultDependencyDescriptor(parentMrid, true);
++ ResolveData data = IvyContext.getContext().getResolveData();
++ if (data == null) {
++ ResolveEngine engine = IvyContext.getContext().getIvy().getResolveEngine();
++ ResolveOptions options = new ResolveOptions();
++ options.setDownload(false);
++ data = new ResolveData(engine, options);
++ }
++
++ DependencyResolver resolver = getSettings().getResolver(parentMrid);
++ if (resolver == null) {
++ // TODO: Throw exception here?
++ return null;
++ } else {
++ ResolvedModuleRevision otherModule = resolver.getDependency(dd, data);
++ if (otherModule == null) {
++ throw new ParseException("Unable to find " + parentMrid.toString(), 0);
++ }
++ return otherModule.getDescriptor();
++ }
++
++ }
++
+ protected void publicationsStarted(Attributes attributes) {
+ state = State.PUB;
+ artifactsDeclared = true;
+Index: src/java/org/apache/ivy/plugins/parser/xml/ivy.xsd
+===================================================================
+--- src/java/org/apache/ivy/plugins/parser/xml/ivy.xsd (revision 887799)
++++ src/java/org/apache/ivy/plugins/parser/xml/ivy.xsd (working copy)
+@@ -60,6 +60,15 @@
+ <xs:element name="info">
+ <xs:complexType>
+ <xs:sequence>
++ <xs:element name="extends" minOccurs="0" maxOccurs="unbounded">
++ <xs:complexType>
++ <xs:attribute name="organisation" type="xs:string" use="required"/>
++ <xs:attribute name="module" type="xs:string" use="required"/>
++ <xs:attribute name="revision" type="xs:string" use="required"/>
++ <xs:attribute name="location" type="xs:string" />
++ <xs:attribute name="extendType" type="xs:string" />
++ </xs:complexType>
++ </xs:element>
+ <xs:element name="license" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+Index: test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java
+===================================================================
+--- test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java (revision 887799)
++++ test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java (working copy)
+@@ -31,7 +31,6 @@
+ import org.apache.ivy.core.module.descriptor.Configuration;
+ import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
+ import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+-import org.apache.ivy.core.module.descriptor.DependencyDescriptorMediator;
+ import org.apache.ivy.core.module.descriptor.ExcludeRule;
+ import org.apache.ivy.core.module.descriptor.License;
+ import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+@@ -46,6 +45,8 @@
+ import org.apache.ivy.plugins.matcher.GlobPatternMatcher;
+ import org.apache.ivy.plugins.matcher.PatternMatcher;
+ import org.apache.ivy.plugins.parser.AbstractModuleDescriptorParserTester;
++import org.apache.ivy.plugins.resolver.FileSystemResolver;
++import org.apache.ivy.util.FileUtil;
+ import org.apache.ivy.util.XMLHelper;
+
+ public class XmlModuleDescriptorParserTest extends AbstractModuleDescriptorParserTester {
+@@ -55,6 +56,8 @@
+ super.setUp();
+
+ this.settings = new IvySettings();
++ //prevent test from polluting local cache
++ settings.setDefaultCache(new File("build/cache"));
+ }
+
+ public void testSimple() throws Exception {
+@@ -78,7 +81,7 @@
+ assertNotNull(md.getDependencies());
+ assertEquals(0, md.getDependencies().length);
+ }
+-
++
+ public void testNamespaces() throws Exception {
+ ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(settings,
+ getClass().getResource("test-namespaces.xml"), true);
+@@ -1018,4 +1021,333 @@
+ // expected
+ }
+ }
++
++ public void testExtendsAll() throws Exception {
++ //default extends type is 'all' when no extendsType attribute is specified.
++ ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(settings,
++ getClass().getResource("test-extends-all.xml"), true);
++ assertNotNull(md);
++
++ assertEquals("myorg", md.getModuleRevisionId().getOrganisation());
++ assertEquals("mymodule", md.getModuleRevisionId().getName());
++ assertEquals(Ivy.getWorkingRevision(), md.getModuleRevisionId().getRevision());
++ assertEquals("integration", md.getStatus());
++
++ //verify that the parent description was merged.
++ assertEquals("Parent module description.", md.getDescription());
++
++ //verify that the parent and child configurations were merged together.
++ final Configuration[] expectedConfs = { new Configuration("default"),
++ new Configuration("conf1"), new Configuration("conf2") };
++ assertNotNull(md.getConfigurations());
++ assertEquals(Arrays.asList(expectedConfs), Arrays
++ .asList(md.getConfigurations()));
++
++ //verify parent and child dependencies were merged together.
++ DependencyDescriptor[] deps = md.getDependencies();
++ assertNotNull(deps);
++ assertEquals(2, deps.length);
++
++ assertEquals(Arrays.asList(new String[]{ "default" }),
++ Arrays.asList(deps[0].getModuleConfigurations()));
++ ModuleRevisionId dep = deps[0].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule1", dep.getModuleId().getName());
++ assertEquals("1.0", dep.getRevision());
++
++ assertEquals(Arrays.asList(new String[]{ "conf1", "conf2" }),
++ Arrays.asList(deps[1].getModuleConfigurations()));
++ dep = deps[1].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule2", dep.getModuleId().getName());
++ assertEquals("2.0", dep.getRevision());
++
++ //verify only child publications are present
++ Artifact[] artifacts = md.getAllArtifacts();
++ assertNotNull(artifacts);
++ assertEquals(1, artifacts.length);
++ assertEquals("mymodule", artifacts[0].getName());
++ assertEquals("jar", artifacts[0].getType());
++ }
++
++ public void testExtendsDependencies() throws Exception {
++ //descriptor specifies that only parent dependencies should be included
++ ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(settings,
++ getClass().getResource("test-extends-dependencies.xml"), true);
++ assertNotNull(md);
++
++ assertEquals("myorg", md.getModuleRevisionId().getOrganisation());
++ assertEquals("mymodule", md.getModuleRevisionId().getName());
++ assertEquals(Ivy.getWorkingRevision(), md.getModuleRevisionId().getRevision());
++ assertEquals("integration", md.getStatus());
++
++ //verify that the parent description was ignored.
++ assertEquals("", md.getDescription());
++
++ //verify that the parent configurations were ignored.
++ final Configuration[] expectedConfs = { new Configuration("default") };
++ assertNotNull(md.getConfigurations());
++ assertEquals(Arrays.asList(expectedConfs), Arrays
++ .asList(md.getConfigurations()));
++
++ //verify parent dependencies were merged.
++ DependencyDescriptor[] deps = md.getDependencies();
++ assertNotNull(deps);
++ assertEquals(2, deps.length);
++
++ assertEquals(Arrays.asList(new String[]{ "default" }),
++ Arrays.asList(deps[0].getModuleConfigurations()));
++ ModuleRevisionId dep = deps[0].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule1", dep.getModuleId().getName());
++ assertEquals("1.0", dep.getRevision());
++
++ assertEquals(Arrays.asList(new String[]{ "default" }),
++ Arrays.asList(deps[1].getModuleConfigurations()));
++ dep = deps[1].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule2", dep.getModuleId().getName());
++ assertEquals("2.0", dep.getRevision());
++
++ //verify only child publications are present
++ Artifact[] artifacts = md.getAllArtifacts();
++ assertNotNull(artifacts);
++ assertEquals(1, artifacts.length);
++ assertEquals("mymodule", artifacts[0].getName());
++ assertEquals("jar", artifacts[0].getType());
++ }
++
++ public void testExtendsConfigurations() throws Exception {
++ //descriptor specifies that only parent configurations should be included
++ ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(settings,
++ getClass().getResource("test-extends-configurations.xml"), true);
++ assertNotNull(md);
++
++ assertEquals("myorg", md.getModuleRevisionId().getOrganisation());
++ assertEquals("mymodule", md.getModuleRevisionId().getName());
++ assertEquals(Ivy.getWorkingRevision(), md.getModuleRevisionId().getRevision());
++ assertEquals("integration", md.getStatus());
++
++ //verify that the parent description was ignored.
++ assertEquals("", md.getDescription());
++
++ //verify that the parent and child configurations were merged together.
++ final Configuration[] expectedConfs = { new Configuration("default"),
++ new Configuration("conf1"), new Configuration("conf2") };
++ assertNotNull(md.getConfigurations());
++ assertEquals(Arrays.asList(expectedConfs), Arrays
++ .asList(md.getConfigurations()));
++
++ //verify parent dependencies were ignored.
++ DependencyDescriptor[] deps = md.getDependencies();
++ assertNotNull(deps);
++ assertEquals(1, deps.length);
++
++ assertEquals(Arrays.asList(new String[]{ "conf1", "conf2" }),
++ Arrays.asList(deps[0].getModuleConfigurations()));
++ ModuleRevisionId dep = deps[0].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule2", dep.getModuleId().getName());
++ assertEquals("2.0", dep.getRevision());
++
++ //verify only child publications are present
++ Artifact[] artifacts = md.getAllArtifacts();
++ assertNotNull(artifacts);
++ assertEquals(1, artifacts.length);
++ assertEquals("mymodule", artifacts[0].getName());
++ assertEquals("jar", artifacts[0].getType());
++ }
++
++ public void testExtendsDescription() throws Exception {
++ //descriptor specifies that only parent description should be included
++ ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(settings,
++ getClass().getResource("test-extends-description.xml"), true);
++ assertNotNull(md);
++
++ assertEquals("myorg", md.getModuleRevisionId().getOrganisation());
++ assertEquals("mymodule", md.getModuleRevisionId().getName());
++ assertEquals(Ivy.getWorkingRevision(), md.getModuleRevisionId().getRevision());
++ assertEquals("integration", md.getStatus());
++
++ //verify that the parent description was merged.
++ assertEquals("Parent module description.", md.getDescription());
++
++ //verify that the parent configurations were ignored.
++ final Configuration[] expectedConfs = { new Configuration("default") };
++ assertNotNull(md.getConfigurations());
++ assertEquals(Arrays.asList(expectedConfs), Arrays
++ .asList(md.getConfigurations()));
++
++ //verify parent dependencies were ignored.
++ DependencyDescriptor[] deps = md.getDependencies();
++ assertNotNull(deps);
++ assertEquals(1, deps.length);
++
++ assertEquals(Arrays.asList(new String[]{ "default" }),
++ Arrays.asList(deps[0].getModuleConfigurations()));
++ ModuleRevisionId dep = deps[0].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule2", dep.getModuleId().getName());
++ assertEquals("2.0", dep.getRevision());
++
++ //verify only child publications are present
++ Artifact[] artifacts = md.getAllArtifacts();
++ assertNotNull(artifacts);
++ assertEquals(1, artifacts.length);
++ assertEquals("mymodule", artifacts[0].getName());
++ assertEquals("jar", artifacts[0].getType());
++ }
++
++ public void testExtendsDescriptionWithOverride() throws Exception {
++ //descriptor specifies that only parent description should be included
++ ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(settings,
++ getClass().getResource("test-extends-description-override.xml"), true);
++ assertNotNull(md);
++
++ assertEquals("myorg", md.getModuleRevisionId().getOrganisation());
++ assertEquals("mymodule", md.getModuleRevisionId().getName());
++ assertEquals(Ivy.getWorkingRevision(), md.getModuleRevisionId().getRevision());
++ assertEquals("integration", md.getStatus());
++
++ //child description should always be preferred, even if extendType="description"
++ assertEquals("Child description overrides parent.", md.getDescription());
++
++ //verify that the parent configurations were ignored.
++ final Configuration[] expectedConfs = { new Configuration("default") };
++ assertNotNull(md.getConfigurations());
++ assertEquals(Arrays.asList(expectedConfs), Arrays
++ .asList(md.getConfigurations()));
++
++ //verify parent dependencies were ignored.
++ DependencyDescriptor[] deps = md.getDependencies();
++ assertNotNull(deps);
++ assertEquals(1, deps.length);
++
++ assertEquals(Arrays.asList(new String[]{ "default" }),
++ Arrays.asList(deps[0].getModuleConfigurations()));
++ ModuleRevisionId dep = deps[0].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule2", dep.getModuleId().getName());
++ assertEquals("2.0", dep.getRevision());
++
++ //verify only child publications are present
++ Artifact[] artifacts = md.getAllArtifacts();
++ assertNotNull(artifacts);
++ assertEquals(1, artifacts.length);
++ assertEquals("mymodule", artifacts[0].getName());
++ assertEquals("jar", artifacts[0].getType());
++ }
++
++ public void testExtendsMixed() throws Exception {
++ //descriptor specifies that parent configurations and dependencies should be included
++ ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(settings,
++ getClass().getResource("test-extends-mixed.xml"), true);
++ assertNotNull(md);
++
++ assertEquals("myorg", md.getModuleRevisionId().getOrganisation());
++ assertEquals("mymodule", md.getModuleRevisionId().getName());
++ assertEquals(Ivy.getWorkingRevision(), md.getModuleRevisionId().getRevision());
++ assertEquals("integration", md.getStatus());
++
++ //verify that the parent description was ignored.
++ assertEquals("", md.getDescription());
++
++ //verify that the parent and child configurations were merged together.
++ final Configuration[] expectedConfs = { new Configuration("default"),
++ new Configuration("conf1"), new Configuration("conf2") };
++ assertNotNull(md.getConfigurations());
++ assertEquals(Arrays.asList(expectedConfs), Arrays
++ .asList(md.getConfigurations()));
++
++ //verify parent and child dependencies were merged together.
++ DependencyDescriptor[] deps = md.getDependencies();
++ assertNotNull(deps);
++ assertEquals(2, deps.length);
++
++ assertEquals(Arrays.asList(new String[]{ "default" }),
++ Arrays.asList(deps[0].getModuleConfigurations()));
++ ModuleRevisionId dep = deps[0].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule1", dep.getModuleId().getName());
++ assertEquals("1.0", dep.getRevision());
++
++ assertEquals(Arrays.asList(new String[]{ "conf1", "conf2" }),
++ Arrays.asList(deps[1].getModuleConfigurations()));
++ dep = deps[1].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule2", dep.getModuleId().getName());
++ assertEquals("2.0", dep.getRevision());
++
++ //verify only child publications are present
++ Artifact[] artifacts = md.getAllArtifacts();
++ assertNotNull(artifacts);
++ assertEquals(1, artifacts.length);
++ assertEquals("mymodule", artifacts[0].getName());
++ assertEquals("jar", artifacts[0].getType());
++ }
++
++ public void testExtendsCached() throws Exception {
++ //configure a resolver to serve the parent descriptor, so that parse succeeds.
++ File resolveRoot = new File("build/tmp/xmlModuleDescriptorTest");
++ assertTrue(resolveRoot.exists() || resolveRoot.mkdirs());
++
++ FileUtil.copy(getClass().getResource("test-extends-parent.xml"),
++ new File(resolveRoot, "myorg/myparent/ivy.xml"), null);
++
++ FileSystemResolver resolver = new FileSystemResolver();
++ resolver.setSettings(settings);
++ resolver.setName("testExtendsCached");
++ resolver.addIvyPattern(resolveRoot.getAbsolutePath()
++ + "/[organisation]/[module]/[artifact].[ext]");
++
++ settings.addResolver(resolver);
++ settings.setDefaultResolver("testExtendsCached");
++
++ //descriptor extends a module without a location="..." attribute, so resolver lookup
++ //must be performed.
++ ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor(settings,
++ getClass().getResource("test-extends-cached.xml"), true);
++ assertNotNull(md);
++
++ assertEquals("myorg", md.getModuleRevisionId().getOrganisation());
++ assertEquals("mymodule", md.getModuleRevisionId().getName());
++ assertEquals(Ivy.getWorkingRevision(), md.getModuleRevisionId().getRevision());
++ assertEquals("integration", md.getStatus());
++
++ //verify that the parent description was merged.
++ assertEquals("Parent module description.", md.getDescription());
++
++ //verify that the parent and child configurations were merged together.
++ final Configuration[] expectedConfs = { new Configuration("default"),
++ new Configuration("conf1"), new Configuration("conf2") };
++ assertNotNull(md.getConfigurations());
++ assertEquals(Arrays.asList(expectedConfs), Arrays
++ .asList(md.getConfigurations()));
++
++ //verify parent and child dependencies were merged together.
++ DependencyDescriptor[] deps = md.getDependencies();
++ assertNotNull(deps);
++ assertEquals(2, deps.length);
++
++ assertEquals(Arrays.asList(new String[]{ "default" }),
++ Arrays.asList(deps[0].getModuleConfigurations()));
++ ModuleRevisionId dep = deps[0].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule1", dep.getModuleId().getName());
++ assertEquals("1.0", dep.getRevision());
++
++ assertEquals(Arrays.asList(new String[]{ "conf1", "conf2" }),
++ Arrays.asList(deps[1].getModuleConfigurations()));
++ dep = deps[1].getDependencyRevisionId();
++ assertEquals("myorg", dep.getModuleId().getOrganisation());
++ assertEquals("mymodule2", dep.getModuleId().getName());
++ assertEquals("2.0", dep.getRevision());
++
++ //verify only child publications are present
++ Artifact[] artifacts = md.getAllArtifacts();
++ assertNotNull(artifacts);
++ assertEquals(1, artifacts.length);
++ assertEquals("mymodule", artifacts[0].getName());
++ assertEquals("jar", artifacts[0].getType());
++ }
+ }
+Index: test/java/org/apache/ivy/plugins/parser/xml/test-extends-all.xml
+===================================================================
+--- test/java/org/apache/ivy/plugins/parser/xml/test-extends-all.xml (revision 0)
++++ test/java/org/apache/ivy/plugins/parser/xml/test-extends-all.xml (revision 0)
+@@ -0,0 +1,32 @@
++<!--
++ Licensed to the Apache Software Foundation (ASF) under one
++ or more contributor license agreements. See the NOTICE file
++ distributed with this work for additional information
++ regarding copyright ownership. The ASF licenses this file
++ to you 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.
++-->
++<ivy-module version="1.0">
++ <info organisation="myorg"
++ module="mymodule"
++ status="integration"
++ publication="20091206000000">
++ <extends organisation="myorg" module="myparent" revision="latest.revision" location="test-extends-parent.xml"/>
++ </info>
++ <configurations>
++ <conf name="conf2" visibility="private"/>
++ </configurations>
++ <dependencies>
++ <dependency name="mymodule2" rev="2.0" conf="conf1,conf2"/>
++ </dependencies>
++</ivy-module>
+Index: test/java/org/apache/ivy/plugins/parser/xml/test-extends-cached.xml
+===================================================================
+--- test/java/org/apache/ivy/plugins/parser/xml/test-extends-cached.xml (revision 0)
++++ test/java/org/apache/ivy/plugins/parser/xml/test-extends-cached.xml (revision 0)
+@@ -0,0 +1,32 @@
++<!--
++ Licensed to the Apache Software Foundation (ASF) under one
++ or more contributor license agreements. See the NOTICE file
++ distributed with this work for additional information
++ regarding copyright ownership. The ASF licenses this file
++ to you 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.
++-->
++<ivy-module version="1.0">
++ <info organisation="myorg"
++ module="mymodule"
++ status="integration"
++ publication="20091206000000">
++ <extends organisation="myorg" module="myparent" revision="latest.revision"/>
++ </info>
++ <configurations>
++ <conf name="conf2" visibility="private"/>
++ </configurations>
++ <dependencies>
++ <dependency name="mymodule2" rev="2.0" conf="conf1,conf2"/>
++ </dependencies>
++</ivy-module>
+Index: test/java/org/apache/ivy/plugins/parser/xml/test-extends-configurations.xml
+===================================================================
+--- test/java/org/apache/ivy/plugins/parser/xml/test-extends-configurations.xml (revision 0)
++++ test/java/org/apache/ivy/plugins/parser/xml/test-extends-configurations.xml (revision 0)
+@@ -0,0 +1,33 @@
++<!--
++ Licensed to the Apache Software Foundation (ASF) under one
++ or more contributor license agreements. See the NOTICE file
++ distributed with this work for additional information
++ regarding copyright ownership. The ASF licenses this file
++ to you 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.
++-->
++<ivy-module version="1.0">
++ <info organisation="myorg"
++ module="mymodule"
++ status="integration"
++ publication="20091206000000">
++ <extends organisation="myorg" module="myparent" revision="latest.revision"
++ location="test-extends-parent.xml" extendType="configurations"/>
++ </info>
++ <configurations>
++ <conf name="conf2" visibility="private"/>
++ </configurations>
++ <dependencies>
++ <dependency name="mymodule2" rev="2.0" conf="conf1,conf2"/>
++ </dependencies>
++</ivy-module>
+Index: test/java/org/apache/ivy/plugins/parser/xml/test-extends-dependencies.xml
+===================================================================
+--- test/java/org/apache/ivy/plugins/parser/xml/test-extends-dependencies.xml (revision 0)
++++ test/java/org/apache/ivy/plugins/parser/xml/test-extends-dependencies.xml (revision 0)
+@@ -0,0 +1,30 @@
++<!--
++ Licensed to the Apache Software Foundation (ASF) under one
++ or more contributor license agreements. See the NOTICE file
++ distributed with this work for additional information
++ regarding copyright ownership. The ASF licenses this file
++ to you 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.
++-->
++<ivy-module version="1.0">
++ <info organisation="myorg"
++ module="mymodule"
++ status="integration"
++ publication="20091206000000">
++ <extends organisation="myorg" module="myparent" revision="latest.revision"
++ location="test-extends-parent.xml" extendType="dependencies"/>
++ </info>
++ <dependencies>
++ <dependency name="mymodule2" rev="2.0" conf="default"/>
++ </dependencies>
++</ivy-module>
+Index: test/java/org/apache/ivy/plugins/parser/xml/test-extends-description-override.xml
+===================================================================
+--- test/java/org/apache/ivy/plugins/parser/xml/test-extends-description-override.xml (revision 0)
++++ test/java/org/apache/ivy/plugins/parser/xml/test-extends-description-override.xml (revision 0)
+@@ -0,0 +1,31 @@
++<!--
++ Licensed to the Apache Software Foundation (ASF) under one
++ or more contributor license agreements. See the NOTICE file
++ distributed with this work for additional information
++ regarding copyright ownership. The ASF licenses this file
++ to you 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.
++-->
++<ivy-module version="1.0">
++ <info organisation="myorg"
++ module="mymodule"
++ status="integration"
++ publication="20091206000000">
++ <extends organisation="myorg" module="myparent" revision="latest.revision"
++ location="test-extends-parent.xml" extendType="description"/>
++ <description>Child description overrides parent.</description>
++ </info>
++ <dependencies>
++ <dependency name="mymodule2" rev="2.0" conf="default"/>
++ </dependencies>
++</ivy-module>
+Index: test/java/org/apache/ivy/plugins/parser/xml/test-extends-description.xml
+===================================================================
+--- test/java/org/apache/ivy/plugins/parser/xml/test-extends-description.xml (revision 0)
++++ test/java/org/apache/ivy/plugins/parser/xml/test-extends-description.xml (revision 0)
+@@ -0,0 +1,30 @@
++<!--
++ Licensed to the Apache Software Foundation (ASF) under one
++ or more contributor license agreements. See the NOTICE file
++ distributed with this work for additional information
++ regarding copyright ownership. The ASF licenses this file
++ to you 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.
++-->
++<ivy-module version="1.0">
++ <info organisation="myorg"
++ module="mymodule"
++ status="integration"
++ publication="20091206000000">
++ <extends organisation="myorg" module="myparent" revision="latest.revision"
++ location="test-extends-parent.xml" extendType="description"/>
++ </info>
++ <dependencies>
++ <dependency name="mymodule2" rev="2.0" conf="default"/>
++ </dependencies>
++</ivy-module>
+Index: test/java/org/apache/ivy/plugins/parser/xml/test-extends-mixed.xml
+===================================================================
+--- test/java/org/apache/ivy/plugins/parser/xml/test-extends-mixed.xml (revision 0)
++++ test/java/org/apache/ivy/plugins/parser/xml/test-extends-mixed.xml (revision 0)
+@@ -0,0 +1,33 @@
++<!--
++ Licensed to the Apache Software Foundation (ASF) under one
++ or more contributor license agreements. See the NOTICE file
++ distributed with this work for additional information
++ regarding copyright ownership. The ASF licenses this file
++ to you 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.
++-->
++<ivy-module version="1.0">
++ <info organisation="myorg"
++ module="mymodule"
++ status="integration"
++ publication="20091206000000">
++ <extends organisation="myorg" module="myparent" revision="latest.revision"
++ location="test-extends-parent.xml" extendType="configurations,dependencies"/>
++ </info>
++ <configurations>
++ <conf name="conf2" visibility="private"/>
++ </configurations>
++ <dependencies>
++ <dependency name="mymodule2" rev="2.0" conf="conf1,conf2"/>
++ </dependencies>
++</ivy-module>
+Index: test/java/org/apache/ivy/plugins/parser/xml/test-extends-parent.xml
+===================================================================
+--- test/java/org/apache/ivy/plugins/parser/xml/test-extends-parent.xml (revision 0)
++++ test/java/org/apache/ivy/plugins/parser/xml/test-extends-parent.xml (revision 0)
+@@ -0,0 +1,34 @@
++<!--
++ Licensed to the Apache Software Foundation (ASF) under one
++ or more contributor license agreements. See the NOTICE file
++ distributed with this work for additional information
++ regarding copyright ownership. The ASF licenses this file
++ to you 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.
++-->
++<ivy-module version="1.0">
++ <info organisation="myorg"
++ module="myparent"
++ revision="myrev"
++ status="integration"
++ publication="20091206000000">
++ <description>Parent module description. </description>
++ </info>
++ <configurations>
++ <conf name="default"/>
++ <conf name="conf1" visibility="public"/>
++ </configurations>
++ <dependencies>
++ <dependency name="mymodule1" rev="1.0" conf="default"/>
++ </dependencies>
++</ivy-module>