ant-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From maart...@apache.org
Subject svn commit: r942195 [1/3] - in /ant/ivy/core/trunk: ./ doc/ doc/ivyfile/ doc/use/ src/java/org/apache/ivy/ant/ src/java/org/apache/ivy/core/deliver/ src/java/org/apache/ivy/core/module/descriptor/ src/java/org/apache/ivy/core/publish/ src/java/org/apac...
Date Fri, 07 May 2010 20:00:50 GMT
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 <conf description> 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 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+   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.    
+-->
+<html>
+<head>
+	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
+	<script type="text/javascript">var xookiConfig = {level: 1};</script>	
+	<script type="text/javascript" src="../xooki/xooki.js"></script>
+</head>
+<body>
+	<textarea id="xooki-source">
+<b>Tag:</b> extends <b>Parent:</b> <a href="../ivyfile/info.html">info</a><br/>
+<br/>
+Identifies an optional parent descriptor for this module.  For complicated projects composed of many modules that have common configurations or dependencies, inheritance allows modules to share this information.  Which parts of the parent descriptor are inherited can be controlled with the <i>extendType</i> attribute.  Supported <i>extendType</i> values are:
+<table class="ivy-attributes">
+<thead>
+    <tr><th class="ivy-att">Value</th><th class="ivy-att-desc">Description</th></tr>
+</thead>
+<tbody>
+    <tr><td>info</td><td>Attributes of the <a href="../ivyfile/info.html">info</a> element are inherited from the parent.  When an attribute appears in both child and parent, the child value is used.</td></tr>
+    <tr><td>description</td><td>The content of the <a href="../ivyfile/description.html">info/description</a> element is inherited from the parent.</td></tr>
+    <tr><td>configurations</td><td><a href="../ivyfile/conf.html">Configurations</a> defined in the parent descriptor are added to any configurations defined in the child descriptor.</td></tr>
+    <tr><td>dependencies</td><td><a href="../ivyfile/dependency.html">Dependencies</a> defined in the parent descriptor are added to any dependencies defined in the child descriptor.</td></tr>
+    <tr><td>all</td><td>info, description, configurations, and dependencies from the parent descriptor are merged into the child descriptor.</td></tr>
+</tbody>
+</table>
+
+<h1>Attributes</h1>
+<table class="ivy-attributes">
+<thead>
+    <tr><th class="ivy-att">Attribute</th><th class="ivy-att-desc">Description</th><th class="ivy-att-req">Required</th></tr>
+</thead>
+<tbody>
+    <tr><td>organisation</td><td>the organisation of the parent module</td>
+        <td>Yes</td></tr>
+    <tr><td>module</td><td>the name of the parent module</td>
+        <td>Yes</td></tr>
+    <tr><td>revision</td><td>the revision of the parent module.  Can be fixed, a dynamic value, or range of revisions; see <a href="../ivyfile/dependency.html">dependency</a> for information on specifying revisions.</td>
+        <td>Yes</td></tr>
+    <tr><td>extendType</td><td>which part(s) of the parent descriptor are inherited.  Valid values are <i>info</i>, <i>description</i>,
+<i>configurations</i>, <i>dependencies</i>, and <i>all</i>.</td>
+        <td>No, default is <i>all</i></td></tr>
+    <tr><td>location</td><td><p>A local filesystem path that should be searched for the parent descriptor.  If the parent descriptor cannot be found at this location, it will be located using dependency resolvers like any normal dependency.</p><p>This attribute is intended for development use.  For example, child module descriptors appear in a source control directory with the parent module descriptor at a higher level.  <i>location</i> will then contain the relative path to the parent descriptor for use during development builds.</p></td>
+        <td>No, as long as the parent descriptor exists in an Ivy resolver</td></tr>
+</tbody>
+</table>
+</textarea>
+<script type="text/javascript">xooki.postProcess();</script>
+</body>
+</html>

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
     <tr><th class="ivy-chld">Element</th><th class="ivy-chld-desc">Description</th><th class="ivy-chld-card">Cardinality</th></tr>
 </thead>
 <tbody>
+    <tr><td><a href="../ivyfile/extends.html">extends</a></td><td>identifies a parent Ivy file from which this descriptor inherits content</td>
+        <td>0..n</td></tr>
     <tr><td><a href="../ivyfile/license.html">license</a></td><td>contains information about the licenses of the described module</td>
         <td>0..n</td></tr>
     <tr><td><a href="../ivyfile/ivyauthor.html">ivyauthor</a></td><td>describes who has contributed to write the ivy file</td>

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
         <td>No. Defaults to default ivy value (as configured in configuration file)</td></tr>
     <tr><td>replacedynamicrev</td><td>true to replace dynmic revisions by static ones in the delivered file, false to avoid this replacement <span class="since">(since 1.3)</span></td>
         <td>No. Defaults to true</td></tr>
+    <tr><td>merge</td><td>if a descriptor <a href="../ivyfile/extends.html">extends</a> a parent, merge the inherited information directly into the delivered descriptor.  The <i>extends</i> element itself will be commented out in the delivered descriptor. <span class="since">(since 2.2)</span></td>
+        <td>No. Defaults to true.</td></tr>
 	<tr><td>settingsRef</td><td>A reference to the ivy settings that must be used by this task <span class="since">(since 2.0)</span></td>
 		<td>No, 'ivy.instance' is taken by default.</td></tr>    
 	<tr><td>conf</td><td>comma-separated list of configurations to include in the delivered file. Accepts wildcards. <span class="since">(since 2.0)</span></td>

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
         <td>No. Defaults to false</td></tr>
     <tr><td>update</td><td>true 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.</td>
         <td>No. Defaults to false</td></tr>
+    <tr><td>merge</td><td>if this descriptor <a href="../ivyfile/extends.html">extends</a> a parent, merge the inherited information directly into this descriptor on publish.  The <i>extends</i> element itself will be commented out in the published descriptor. <span class="since">(since 2.2)</span></td>
+        <td>No. Defaults to true</tr>
     <tr><td>validate</td><td>true to force ivy files validation against ivy.xsd, false to force no validation</td>
         <td>No. Defaults to default ivy value (as configured in [[settings settings file]])</td></tr>
     <tr><td>replacedynamicrev</td><td>true to replace dynamic revisions by static ones in the delivered file, false to avoid this replacement <span class="since">(since 1.3)</span></td>

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/*<String,String>*/ 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.
  * </p>
  */
-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 <code>info</code>, <code>description</code>,
+     * <code>configurations</code>, <code>dependencies</code>, and/or <code>all</code>.
+     * Ivy extensions may add support for additional extends types.
+     */
+    public String[] getExtendsTypes();
+
+    /** @return true if the <code>all</code> 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 &lt;extends&gt; 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 <code>null</code> 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/* <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);
+                }
+            }
+
+            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/* <String> */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;



Mime
View raw message