Author: maartenc Date: Fri May 7 20:00:48 2010 New Revision: 942195 URL: http://svn.apache.org/viewvc?rev=942195&view=rev Log: NEW: Support ivy.xml parent mechanism (IVY-742) (thanks to Jason Trump and Jean-Louis Boudart) Added: ant/ivy/core/trunk/doc/ivyfile/extends.html (with props) ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultExtendsDescriptor.java (with props) ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ExtendsDescriptor.java (with props) ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/InheritableItem.java (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-extends-merged.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-extends-minimal-merged.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-extends-minimal.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-extends-multiconf.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-extends-all.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-extends-cached.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-extends-configurations.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-extends-dependencies.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-extends-description-override.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-extends-description.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-extends-mixed.xml (with props) ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-extends-parent.xml (with props) Modified: ant/ivy/core/trunk/CHANGES.txt ant/ivy/core/trunk/doc/ivyfile/info.html ant/ivy/core/trunk/doc/toc.json ant/ivy/core/trunk/doc/use/deliver.html ant/ivy/core/trunk/doc/use/publish.html ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDeliver.java ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyPublish.java ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverEngine.java ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverOptions.java ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/Configuration.java ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultDependencyDescriptor.java ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DependencyDescriptor.java ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishOptions.java ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/UpdateOptions.java ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorUpdater.java ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriter.java ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/ivy.xsd ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyDeliverTest.java ant/ivy/core/trunk/test/java/org/apache/ivy/ant/IvyPublishTest.java ant/ivy/core/trunk/test/java/org/apache/ivy/ant/ivy-multiconf.xml ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java Modified: ant/ivy/core/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/CHANGES.txt (original) +++ ant/ivy/core/trunk/CHANGES.txt Fri May 7 20:00:48 2010 @@ -24,6 +24,7 @@ for detailed view of each issue, please Jeffrey Blattman Jasper Blues Jim Bonanno + Jean-Louis Boudart Dave Brosius Matthieu Brouillard Carlton Brown @@ -111,6 +112,7 @@ for detailed view of each issue, please - DOCUMENTATION: ivy-doc.xsl does not show configurations (IVY-1151) (thanks to Jasper Blues) - DOCUMENTATION: Added documentation of the 'changing' attribute on the ivy:resolve Ant task (IVY-1180) +- NEW: Support ivy.xml parent mechanism (IVY-742) (thanks to Jason Trump and Jean-Louis Boudart) - NEW: Make ivy.xml available (IVY-1158) - IMPROVEMENT: Support changing="true" for inline retrieve (IVY-1180) Added: ant/ivy/core/trunk/doc/ivyfile/extends.html URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/ivyfile/extends.html?rev=942195&view=auto ============================================================================== --- ant/ivy/core/trunk/doc/ivyfile/extends.html (added) +++ ant/ivy/core/trunk/doc/ivyfile/extends.html Fri May 7 20:00:48 2010 @@ -0,0 +1,66 @@ + + + + + + + + + + + + + Propchange: ant/ivy/core/trunk/doc/ivyfile/extends.html ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: ant/ivy/core/trunk/doc/ivyfile/info.html URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/ivyfile/info.html?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/doc/ivyfile/info.html (original) +++ ant/ivy/core/trunk/doc/ivyfile/info.html Fri May 7 20:00:48 2010 @@ -57,6 +57,8 @@ Gives identification and basic informati ElementDescriptionCardinality + extendsidentifies a parent Ivy file from which this descriptor inherits content + 0..n licensecontains information about the licenses of the described module 0..n ivyauthordescribes who has contributed to write the ivy file Modified: ant/ivy/core/trunk/doc/toc.json URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/toc.json?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/doc/toc.json (original) +++ ant/ivy/core/trunk/doc/toc.json Fri May 7 20:00:48 2010 @@ -424,6 +424,13 @@ "title":"info", "children": [ { + "id":"ivyfile/extends", + "title":"extends", + "children": [ + + ] + }, + { "id":"ivyfile/license", "title":"license", "children": [ Modified: ant/ivy/core/trunk/doc/use/deliver.html URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/use/deliver.html?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/doc/use/deliver.html (original) +++ ant/ivy/core/trunk/doc/use/deliver.html Fri May 7 20:00:48 2010 @@ -99,6 +99,8 @@ It can also be useful if you want to tri No. Defaults to default ivy value (as configured in configuration file) replacedynamicrevtrue to replace dynmic revisions by static ones in the delivered file, false to avoid this replacement (since 1.3) No. Defaults to true + mergeif a descriptor extends a parent, merge the inherited information directly into the delivered descriptor. The extends element itself will be commented out in the delivered descriptor. (since 2.2) + No. Defaults to true. settingsRefA reference to the ivy settings that must be used by this task (since 2.0) No, 'ivy.instance' is taken by default. confcomma-separated list of configurations to include in the delivered file. Accepts wildcards. (since 2.0) Modified: ant/ivy/core/trunk/doc/use/publish.html URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/use/publish.html?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/doc/use/publish.html (original) +++ ant/ivy/core/trunk/doc/use/publish.html Fri May 7 20:00:48 2010 @@ -60,6 +60,8 @@ The source artifact pattern can be speci No. Defaults to false updatetrue to update ivy file metadata (revision, branch, publication date and status) before publishing, false otherwise. This is usually not necessary when using deliver before publish. No. Defaults to false + mergeif this descriptor extends a parent, merge the inherited information directly into this descriptor on publish. The extends element itself will be commented out in the published descriptor. (since 2.2) + No. Defaults to true validatetrue to force ivy files validation against ivy.xsd, false to force no validation No. Defaults to default ivy value (as configured in [[settings settings file]]) replacedynamicrevtrue to replace dynamic revisions by static ones in the delivered file, false to avoid this replacement (since 1.3) Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDeliver.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDeliver.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDeliver.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyDeliver.java Fri May 7 20:00:48 2010 @@ -206,6 +206,8 @@ public class IvyDeliver extends IvyTask private String pubBranch; private boolean generateRevConstraint = true; + + private boolean merge = true; public void setCache(File cache) { cacheAttributeNotSupported(); @@ -315,6 +317,14 @@ public class IvyDeliver extends IvyTask this.generateRevConstraint = generateRevConstraint; } + public boolean isMerge() { + return merge; + } + + public void setMerge(boolean merge) { + this.merge = merge; + } + public void doExecute() throws BuildException { Ivy ivy = getIvyInstance(); IvySettings settings = ivy.getSettings(); @@ -394,6 +404,7 @@ public class IvyDeliver extends IvyTask drResolver, doValidate(settings), replacedynamicrev, splitConfs(conf)) .setResolveId(resolveId) .setGenerateRevConstraint(generateRevConstraint) + .setMerge(merge) .setPubBranch(pubBranch); if (mrid == null) { ivy.deliver(pubRevision, deliverpattern, options); Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyPublish.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyPublish.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyPublish.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyPublish.java Fri May 7 20:00:48 2010 @@ -72,6 +72,8 @@ public class IvyPublish extends IvyTask private boolean overwrite = false; private boolean update = false; + + private boolean merge = true; private boolean replacedynamicrev = true; @@ -208,6 +210,14 @@ public class IvyPublish extends IvyTask this.replacedynamicrev = replacedynamicrev; } + public boolean isMerge() { + return merge; + } + + public void setMerge(boolean merge) { + this.merge = merge; + } + public void doExecute() throws BuildException { Ivy ivy = getIvyInstance(); IvySettings settings = ivy.getSettings(); @@ -291,6 +301,7 @@ public class IvyPublish extends IvyTask deliver.setStatus(getStatus()); deliver.setValidate(doValidate(settings)); deliver.setReplacedynamicrev(isReplacedynamicrev()); + deliver.setMerge(merge); deliver.setConf(conf); deliver.execute(); @@ -308,6 +319,7 @@ public class IvyPublish extends IvyTask .setValidate(doValidate(settings)) .setOverwrite(overwrite) .setUpdate(update) + .setMerge(merge) .setWarnOnMissing(warnonmissing) .setHaltOnMissing(haltonmissing) .setConfs(splitConfs(conf))); Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverEngine.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverEngine.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverEngine.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverEngine.java Fri May 7 20:00:48 2010 @@ -192,6 +192,8 @@ public class DeliverEngine { .setBranch(options.getPubBranch()) .setPubdate(options.getPubdate()) .setGenerateRevConstraint(options.isGenerateRevConstraint()) + .setMerge(options.isMerge()) + .setMergedDescriptor(md) .setConfsToExclude((String[]) confsToRemove .toArray(new String[confsToRemove.size()]))); } catch (SAXException ex) { Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverOptions.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverOptions.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverOptions.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverOptions.java Fri May 7 20:00:48 2010 @@ -46,7 +46,9 @@ public class DeliverOptions { * applicable, false to never generate the revConstraint attribute. */ private boolean generateRevConstraint = true; - + + /** true to merge parent descriptor elements into delivered child descriptor */ + private boolean merge = true; /** * Returns an instance of DeliverOptions with options corresponding to default values taken from @@ -237,10 +239,19 @@ public class DeliverOptions { return this; } - + public boolean isMerge() { + return merge; + } + + public DeliverOptions setMerge(boolean merge) { + this.merge = merge; + return this; + } + public String toString() { return "status=" + status + " pubdate=" + pubdate + " validate=" + validate + " resolveDynamicRevisions=" + resolveDynamicRevisions + + " merge=" + merge + " resolveId=" + resolveId + " pubBranch=" + pubBranch; Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/Configuration.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/Configuration.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/Configuration.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/Configuration.java Fri May 7 20:00:48 2010 @@ -21,14 +21,16 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; +import java.util.Map; import java.util.Set; +import org.apache.ivy.core.module.id.ModuleRevisionId; import org.apache.ivy.util.extendable.DefaultExtendableItem; /** * Represents a module configuration */ -public class Configuration extends DefaultExtendableItem { +public class Configuration extends DefaultExtendableItem implements InheritableItem { public static final class Visibility { public static final Visibility PUBLIC = new Visibility("public"); @@ -77,6 +79,8 @@ public class Configuration extends Defau private boolean transitive = true; private String deprecated; + + private ModuleRevisionId sourceModule; /** * Creates a new configuration. @@ -86,6 +90,12 @@ public class Configuration extends Defau public Configuration(String name) { this(name, Visibility.PUBLIC, null, null, true, null); } + + public Configuration(Configuration source, ModuleRevisionId sourceModule) { + this(source.getAttributes(), source.getQualifiedExtraAttributes(), source.getName(), + source.getVisibility(), source.getDescription(), source.getExtends(), + source.isTransitive(), source.getDeprecated(), sourceModule); + } /** * Creates a new configuration. @@ -99,6 +109,14 @@ public class Configuration extends Defau */ public Configuration(String name, Visibility visibility, String description, String[] ext, boolean transitive, String deprecated) { + this(null, null, name, visibility, description, ext, transitive, deprecated, null); + } + + private Configuration(Map attributes, Map extraAttributes, String name, Visibility visibility, + String description, String[] ext, boolean transitive, String deprecated, + ModuleRevisionId sourceModule) { + super(attributes, extraAttributes); + if (name == null) { throw new NullPointerException("null configuration name not allowed"); } @@ -118,6 +136,7 @@ public class Configuration extends Defau } this.transitive = transitive; this.deprecated = deprecated; + this.sourceModule = sourceModule; } /** @@ -162,6 +181,10 @@ public class Configuration extends Defau public final boolean isTransitive() { return transitive; } + + public ModuleRevisionId getSourceModule() { + return sourceModule; + } public String toString() { return name; Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultDependencyDescriptor.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultDependencyDescriptor.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultDependencyDescriptor.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultDependencyDescriptor.java Fri May 7 20:00:48 2010 @@ -88,7 +88,13 @@ public class DefaultDependencyDescriptor DefaultDependencyDescriptor newdd = new DefaultDependencyDescriptor( null, transformMrid, transformDynamicMrid, dd.isForce(), dd.isChanging(), dd.isTransitive()); + newdd.parentId = transformParentId; + ModuleRevisionId sourceModule = dd.getSourceModule(); + if (sourceModule != null) { + newdd.sourceModule = t.transform(sourceModule); + } + String[] moduleConfs = dd.getModuleConfigurations(); if (moduleConfs.length == 1 && "*".equals(moduleConfs[0])) { if (dd instanceof DefaultDependencyDescriptor) { @@ -159,7 +165,9 @@ public class DefaultDependencyDescriptor private final ModuleDescriptor md; private DependencyDescriptor asSystem = this; - + + private ModuleRevisionId sourceModule; + private DefaultDependencyDescriptor(DefaultDependencyDescriptor dd, ModuleRevisionId revision) { Checks.checkNotNull(dd, "dd"); Checks.checkNotNull(revision, "revision"); @@ -183,8 +191,9 @@ public class DefaultDependencyDescriptor includeRules = dd.includeRules == null ? null : new LinkedHashMap(dd.includeRules); dependencyArtifacts = dd.dependencyArtifacts == null ? null : new LinkedHashMap(dd.dependencyArtifacts); + sourceModule = dd.sourceModule; } - + public DefaultDependencyDescriptor( ModuleDescriptor md, ModuleRevisionId mrid, boolean force, boolean changing, boolean transitive) { @@ -211,6 +220,7 @@ public class DefaultDependencyDescriptor isForce = force; isChanging = changing; isTransitive = transitive; + sourceModule = md == null ? null : md.getModuleRevisionId(); } public ModuleId getDependencyId() { @@ -698,6 +708,10 @@ public class DefaultDependencyDescriptor return excludeRules; } + public ModuleRevisionId getSourceModule() { + return sourceModule; + } + public DependencyDescriptor clone(ModuleRevisionId revision) { return new DefaultDependencyDescriptor(this, revision); } Added: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultExtendsDescriptor.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultExtendsDescriptor.java?rev=942195&view=auto ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultExtendsDescriptor.java (added) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultExtendsDescriptor.java Fri May 7 20:00:48 2010 @@ -0,0 +1,62 @@ +package org.apache.ivy.core.module.descriptor; + +import org.apache.ivy.core.module.id.ModuleRevisionId; + +import java.util.ArrayList; +import java.util.List; + +public class DefaultExtendsDescriptor implements ExtendsDescriptor { + + private ModuleRevisionId parentRevisionId; + private ModuleRevisionId resolvedParentRevisionId; + private String location; + private List extendsTypes; + + public DefaultExtendsDescriptor(ModuleRevisionId parentRevisionId, + ModuleRevisionId resolvedParentRevisionId, + String location, String[] types) { + this.parentRevisionId = parentRevisionId; + this.resolvedParentRevisionId = resolvedParentRevisionId; + this.location = location; + this.extendsTypes = new ArrayList(types.length); + for (int i = 0; i < types.length; ++i) { + extendsTypes.add(types[i]); + } + } + + public ModuleRevisionId getParentRevisionId() { + return parentRevisionId; + } + + public ModuleRevisionId getResolvedParentRevisionId() { + return resolvedParentRevisionId; + } + + public String getLocation() { + return location; + } + + public String[] getExtendsTypes() { + return (String[])extendsTypes.toArray(new String[extendsTypes.size()]); + } + + public boolean isAllInherited() { + return extendsTypes.contains("all"); + } + + public boolean isInfoInherited() { + return isAllInherited() || extendsTypes.contains("info"); + } + + public boolean isDescriptionInherited() { + return isAllInherited() || extendsTypes.contains("description"); + } + + public boolean areConfigurationsInherited() { + return isAllInherited() || extendsTypes.contains("configurations"); + } + + public boolean areDependenciesInherited() { + return isAllInherited() || extendsTypes.contains("dependencies"); + } +} Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultExtendsDescriptor.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java Fri May 7 20:00:48 2010 @@ -148,6 +148,15 @@ public class DefaultModuleDescriptor imp nmd.status = md.getStatus(); nmd.publicationDate = md.getPublicationDate(); nmd.resolvedPublicationDate = md.getResolvedPublicationDate(); + + ExtendsDescriptor[] ed = md.getInheritedDescriptors(); + for (int i = 0; i < ed.length; ++i) { + ModuleRevisionId mrid = t.transform(ed[i].getParentRevisionId()); + ModuleRevisionId resolvedMrid = t.transform(ed[i].getResolvedParentRevisionId()); + nmd.inheritedDescriptors.add(new DefaultExtendsDescriptor(mrid, resolvedMrid, + ed[i].getLocation(), ed[i].getExtendsTypes())); + } + DependencyDescriptor[] dd = md.getDependencies(); for (int i = 0; i < dd.length; i++) { nmd.dependencies.add(NameSpaceHelper.toSystem(dd[i], ns)); @@ -227,6 +236,8 @@ public class DefaultModuleDescriptor imp private List excludeRules = new ArrayList(); // List(ExcludeRule) private Artifact metadataArtifact; + + private List inheritedDescriptors = new ArrayList(); //List(ExtendsDescriptor) private Map/**/ extraAttributesNamespaces = new LinkedHashMap(); @@ -322,6 +333,10 @@ public class DefaultModuleDescriptor imp this.status = status; } + public void addInheritedDescriptor(ExtendsDescriptor descriptor) { + inheritedDescriptors.add(descriptor); + } + public void addDependency(DependencyDescriptor dependency) { dependencies.add(dependency); } @@ -373,6 +388,11 @@ public class DefaultModuleDescriptor imp return status; } + public ExtendsDescriptor[] getInheritedDescriptors() { + return (ExtendsDescriptor[])inheritedDescriptors.toArray( + new ExtendsDescriptor[inheritedDescriptors.size()]); + } + public Configuration[] getConfigurations() { return (Configuration[]) configurations.values().toArray( new Configuration[configurations.size()]); Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DependencyDescriptor.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DependencyDescriptor.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DependencyDescriptor.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DependencyDescriptor.java Fri May 7 20:00:48 2010 @@ -40,7 +40,7 @@ import org.apache.ivy.util.extendable.Ex * be used instead of the default dependency constraint when performing dependency resolution. *

*/ -public interface DependencyDescriptor extends ExtendableItem { +public interface DependencyDescriptor extends ExtendableItem, InheritableItem { ModuleId getDependencyId(); /** Added: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ExtendsDescriptor.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ExtendsDescriptor.java?rev=942195&view=auto ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ExtendsDescriptor.java (added) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ExtendsDescriptor.java Fri May 7 20:00:48 2010 @@ -0,0 +1,46 @@ +package org.apache.ivy.core.module.descriptor; + +import org.apache.ivy.core.module.id.ModuleRevisionId; + +/** + * Describes parent descriptor information for a module descriptor. + */ +public interface ExtendsDescriptor { + + /** get the module revision id of the declared parent descriptor */ + public ModuleRevisionId getParentRevisionId(); + /** + * get the resolved revision id for {@link #getParentRevisionId}, see + * {@link org.apache.ivy.core.module.descriptor.ModuleDescriptor#getResolvedModuleRevisionId()} } + */ + public ModuleRevisionId getResolvedParentRevisionId(); + + /** + * If there is an explicit path to check for the parent descriptor, return it. + * Otherwise returns null. + */ + public String getLocation(); + + /** + * Get the parts of the parent descriptor that are inherited. Default + * supported types are info, description, + * configurations, dependencies, and/or all. + * Ivy extensions may add support for additional extends types. + */ + public String[] getExtendsTypes(); + + /** @return true if the all extend type is specified, implying all other types */ + public boolean isAllInherited(); + + /** @return true if parent info attributes are inherited (organisation, branch, revision, etc)*/ + public boolean isInfoInherited(); + + /** @return true if parent description is inherited */ + public boolean isDescriptionInherited(); + + /** @return true if parent configurations are inherited */ + public boolean areConfigurationsInherited(); + + /** @return true if parent dependencies are inherited */ + public boolean areDependenciesInherited(); +} Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ExtendsDescriptor.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/InheritableItem.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/InheritableItem.java?rev=942195&view=auto ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/InheritableItem.java (added) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/InheritableItem.java Fri May 7 20:00:48 2010 @@ -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. + * + */ +package org.apache.ivy.core.module.descriptor; + +import org.apache.ivy.core.module.id.ModuleRevisionId; + +/** + * Interface for elements that can be inherited from a parent descriptor + * by a child descriptor. + * @see Configuration + * @see DependencyDescriptor + */ +public interface InheritableItem { + /** + * @return the module in which this item was actually defined, if different + * from the module in which the item appears. May be null. + */ + public ModuleRevisionId getSourceModule(); +} Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/InheritableItem.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java Fri May 7 20:00:48 2010 @@ -72,6 +72,13 @@ public interface ModuleDescriptor void setResolvedModuleRevisionId(ModuleRevisionId revId); /** + * Get the list of parent descriptors imported via an <extends> element. + * Only directly imported descriptors are included; the parent's parents are + * not included. + */ + ExtendsDescriptor[] getInheritedDescriptors(); + + /** * This method update the resolved publication date * * @param publicationDate Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java Fri May 7 20:00:48 2010 @@ -133,6 +133,8 @@ public class PublishEngine { .setBranch(options.getPubBranch()) .setPubdate(options.getPubdate() == null ? new Date() : options.getPubdate()) + .setMerge(options.isMerge()) + .setMergedDescriptor(md) .setConfsToExclude((String[]) confsToRemove .toArray(new String[confsToRemove.size()]))); ivyFile = tmp; Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishOptions.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishOptions.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishOptions.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishOptions.java Fri May 7 20:00:48 2010 @@ -52,6 +52,8 @@ public class PublishOptions { private boolean overwrite; private boolean update; + + private boolean merge = true; private String[] confs; @@ -132,6 +134,15 @@ public class PublishOptions { this.update = update; return this; } + + public boolean isMerge() { + return merge; + } + + public PublishOptions setMerge(boolean merge) { + this.merge = merge; + return this; + } public boolean isValidate() { return validate; Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/UpdateOptions.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/UpdateOptions.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/UpdateOptions.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/UpdateOptions.java Fri May 7 20:00:48 2010 @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.Date; import java.util.Map; +import org.apache.ivy.core.module.descriptor.ModuleDescriptor; import org.apache.ivy.plugins.namespace.Namespace; import org.apache.ivy.plugins.parser.ParserSettings; @@ -54,6 +55,11 @@ public class UpdateOptions { */ private boolean replaceInclude = true; /** + * Should parent descriptor be merged inline + */ + private boolean merge = true; + private ModuleDescriptor mergedDescriptor = null; + /** * Configurations to exclude during update, or null to keep all confs. */ private String[] confsToExclude = null; @@ -118,6 +124,21 @@ public class UpdateOptions { this.replaceInclude = replaceInclude; return this; } + public boolean isMerge() { + // only return true if merge is set to true and if there is something to merge! + return merge && (mergedDescriptor != null) && (mergedDescriptor.getInheritedDescriptors().length > 0); + } + public UpdateOptions setMerge(boolean merge) { + this.merge = merge; + return this; + } + public ModuleDescriptor getMergedDescriptor() { + return mergedDescriptor; + } + public UpdateOptions setMergedDescriptor(ModuleDescriptor mergedDescriptor) { + this.mergedDescriptor = mergedDescriptor; + return this; + } public String[] getConfsToExclude() { return confsToExclude; } Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java?rev=942195&r1=942194&r2=942195&view=diff ============================================================================== --- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java (original) +++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParser.java Fri May 7 20:00:48 2010 @@ -24,6 +24,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.text.ParseException; import java.util.Arrays; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -31,33 +32,26 @@ import javax.xml.parsers.ParserConfigura import org.apache.ivy.Ivy; import org.apache.ivy.core.IvyContext; -import org.apache.ivy.core.module.descriptor.Configuration; -import org.apache.ivy.core.module.descriptor.ConfigurationAware; -import org.apache.ivy.core.module.descriptor.DefaultArtifact; -import org.apache.ivy.core.module.descriptor.DefaultDependencyArtifactDescriptor; -import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor; -import org.apache.ivy.core.module.descriptor.DefaultExcludeRule; -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.ExcludeRule; -import org.apache.ivy.core.module.descriptor.IncludeRule; -import org.apache.ivy.core.module.descriptor.License; -import org.apache.ivy.core.module.descriptor.MDArtifact; -import org.apache.ivy.core.module.descriptor.ModuleDescriptor; -import org.apache.ivy.core.module.descriptor.OverrideDependencyDescriptorMediator; +import org.apache.ivy.core.cache.ResolutionCacheManager; +import org.apache.ivy.core.module.descriptor.*; 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 +263,15 @@ public class XmlModuleDescriptorParser e 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 +337,250 @@ public class XmlModuleDescriptorParser e } } + 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/* */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); + } + } + + DefaultExtendsDescriptor ed = new DefaultExtendsDescriptor( + parent.getModuleRevisionId(), + parent.getResolvedModuleRevisionId(), + attributes.getValue("location"), + (String[])extendTypes.toArray(new String[extendTypes.size()])); + getMd().addInheritedDescriptor(ed); + + mergeWithOtherModuleDescriptor(extendTypes, parent); + } + + protected void mergeWithOtherModuleDescriptor(List/* */extendTypes, + ModuleDescriptor parent) { + + if (extendTypes.contains("all")) { + mergeAll(parent); + } else { + if (extendTypes.contains("info")) { + mergeInfo(parent); + } + + if (extendTypes.contains("configurations")) { + mergeConfigurations(parent.getModuleRevisionId(), parent.getConfigurations()); + } + + if (extendTypes.contains("dependencies")) { + mergeDependencies(parent.getDependencies()); + } + + if (extendTypes.contains("description")) { + mergeDescription(parent.getDescription()); + } + } + + } + + protected void mergeAll(ModuleDescriptor parent) { + ModuleRevisionId sourceMrid = parent.getModuleRevisionId(); + mergeInfo(parent); + mergeConfigurations(sourceMrid, parent.getConfigurations()); + mergeDependencies(parent.getDependencies()); + mergeDescription(parent.getDescription()); + } + + protected void mergeInfo(ModuleDescriptor parent) { + ModuleRevisionId parentMrid = parent.getModuleRevisionId(); + + DefaultModuleDescriptor descriptor = getMd(); + ModuleRevisionId currentMrid = descriptor.getModuleRevisionId(); + + ModuleRevisionId mergedMrid = ModuleRevisionId.newInstance( + mergeValue(parentMrid.getOrganisation(), currentMrid.getOrganisation()), + currentMrid.getName(), + mergeValue(parentMrid.getBranch(), currentMrid.getBranch()), + mergeValue(parentMrid.getRevision(), currentMrid.getRevision()), + mergeValues(parentMrid.getQualifiedExtraAttributes(), + currentMrid.getQualifiedExtraAttributes()) + ); + + descriptor.setModuleRevisionId(mergedMrid); + descriptor.setResolvedModuleRevisionId(mergedMrid); + + descriptor.setStatus(mergeValue(parent.getStatus(), descriptor.getStatus())); + if (descriptor.getNamespace() == null && parent instanceof DefaultModuleDescriptor) { + descriptor.setNamespace(((DefaultModuleDescriptor)parent).getNamespace()); + } + } + + private static String mergeValue(String inherited, String override) { + return override == null ? inherited : override; + } + + private static Map mergeValues(Map inherited, Map overrides) { + LinkedHashMap dup = new LinkedHashMap(inherited.size() + overrides.size()); + dup.putAll(inherited); + dup.putAll(overrides); + return dup; + } + + protected void mergeConfigurations(ModuleRevisionId sourceMrid, Configuration[] configurations) { + DefaultModuleDescriptor md = getMd(); + for (int i = 0; i < configurations.length; i++) { + Configuration configuration = configurations[i]; + Message.debug("Merging configuration with: " + configuration.getName()); + //copy configuration from parent descriptor + md.addConfiguration(new Configuration(configuration, sourceMrid)); + } + } + + protected void mergeDependencies(DependencyDescriptor[] dependencies) { + DefaultModuleDescriptor md = getMd(); + for (int i = 0; i < dependencies.length; i++) { + DependencyDescriptor dependencyDescriptor = dependencies[i]; + Message.debug("Merging dependency with: " + + dependencyDescriptor.getDependencyRevisionId().toString()); + md.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;