ant-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From xav...@apache.org
Subject svn commit: r601077 - in /ant/ivy/core/trunk: ./ doc/configuration/ src/java/org/apache/ivy/ src/java/org/apache/ivy/core/event/download/ src/java/org/apache/ivy/core/event/resolve/ src/java/org/apache/ivy/core/event/retrieve/ src/java/org/apache/ivy/c...
Date Tue, 04 Dec 2007 20:39:19 GMT
Author: xavier
Date: Tue Dec  4 12:39:16 2007
New Revision: 601077

URL: http://svn.apache.org/viewvc?rev=601077&view=rev
Log:
IMPROVEMENT: Ease performance auditing (IVY-655)

Added:
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/EndRetrieveEvent.java   (with props)
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/RetrieveEvent.java   (with props)
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/StartRetrieveEvent.java   (with props)
    ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/trigger/LogTrigger.java   (with props)
    ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/trigger/
    ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/trigger/LogTriggerTest.java   (with props)
Modified:
    ant/ivy/core/trunk/CHANGES.txt
    ant/ivy/core/trunk/doc/configuration/triggers.html
    ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/DownloadEvent.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/EndArtifactDownloadEvent.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveDependencyEvent.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveEvent.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/ResolveDependencyEvent.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ArtifactDownloadReport.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ResolveReport.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/retrieve/RetrieveEngine.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties
    ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/repository/TransferEvent.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/util/FileUtil.java
    ant/ivy/core/trunk/test/java/org/apache/ivy/core/retrieve/RetrieveTest.java

Modified: ant/ivy/core/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/CHANGES.txt (original)
+++ ant/ivy/core/trunk/CHANGES.txt Tue Dec  4 12:39:16 2007
@@ -62,6 +62,7 @@
 - NEW: Add a task/code to create M2 POM files from Ivy configurations (IVY-416)
 - NEW: [Build] Publish the ivy sources (IVY-646) (thanks to Nicolas Lalevée)
 
+- IMPROVEMENT: Ease performance auditing (IVY-655)
 - IMPROVEMENT: Maven Dependency Management is not used to determine artifact version (IVY-616) (thanks to Jim Bonanno)
 - IMPROVEMENT: split the cache into an downloaded artifacts cache and a metadata cache (IVY-628)
 - IMPROVEMENT: add publish triggers to event system (IVY-650) (thanks to Jason Trump)

Modified: ant/ivy/core/trunk/doc/configuration/triggers.html
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/configuration/triggers.html?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/doc/configuration/triggers.html (original)
+++ ant/ivy/core/trunk/doc/configuration/triggers.html Tue Dec  4 12:39:16 2007
@@ -50,30 +50,33 @@
             <li>conf</li>comma separated list of configurations which will be resolved
           </ul>
         </td>
-        <td>Fired before a module dependencies will be resolved</td>
+        <td>Fired at the beginning of the resolve process, before a module dependencies and transitive dependencies are resolved.</td>
     </tr>
     <tr><td>pre-resolve-dependency</td>
         <td>
           <ul>
             <li>organisation</li>the organisation of the dependency resolved
             <li>module</li>the name of the dependency resolved
-            <li>revision</li>the revision asked for the dependency
+            <li>req-revision</li>the requested revision for the dependency <span class="since">since 2.0</span> (provided for consistency with post-resolve-dependency)
+            <li>revision</li>the requested revision for the dependency
             <li>resolver</li>the name of the resolver used to resolve the dependency
           </ul>
         </td>
-        <td>Fired before each dependency is resolved in a single resolve call</td>
+        <td>Fired before each dependency is resolved. In this case resolved means resolving the actual revision if the requested revision is a version constraint and not a static version, and downloading all necessary metadata information.</td>
     </tr>
     <tr><td>post-resolve-dependency</td>
         <td>
           <ul>
             <li>organisation</li>the organisation of the dependency resolved
             <li>module</li>the name of the dependency resolved
-            <li>revision</li>the revision of the dependency resolved, or the revision asked if the resolution was not successful
+            <li>req-revision</li>the requested revision for the dependency <span class="since">since 2.0</span>
+            <li>revision</li>the revision of the dependency resolved, or the requested revision if the resolution was not successful
             <li>resolved</li>true if the resolution was successful, false otherwise
+            <li>duration</li>the time elapsed to resolve the dependency (in ms) <span class="since">since 2.0</span>
             <li>resolver</li>the name of the resolver used to resolve the dependency
           </ul>
         </td>
-        <td>Fired after each dependency resolved in a single resolve call</td>
+        <td>Fired after each dependency is resolved</td>
     </tr>
     <tr><td>post-resolve</td>
         <td>
@@ -82,9 +85,15 @@
             <li>module</li>the name of the module for which the dependencies have been resolved
             <li>revision</li>the revision of the module for which the dependencies have been resolved
             <li>conf</li>comma separated list of configurations resolved
+            <li>resolve-id</li>the identifier of the resolution process <span class="since">since 2.0</span>
+            <li>nb-dependencies</li>total number of dependencies, including transitive and evicted ones <span class="since">since 2.0</span>
+            <li>nb-artifacts</li>total number of artifacts resolved, excluding metadata artifacts <span class="since">since 2.0</span>
+            <li>resolve-duration</li>the time (in ms) elapsed to resolve dependencies, before dowloading artifacts <span class="since">since 2.0</span>
+            <li>download-duration</li>the time (in ms) elapsed to download all artifacts, excluding metadata artifacts downloaded during the first phase of the resolution process <span class="since">since 2.0</span>
+            <li>download-size</li>the total size (in bytes) of all downloaded artifacts, excluding metadata artifacts. Only artifacts actually downloaded (not in cache or used from their original location) are considered <span class="since">since 2.0</span>
           </ul>
         </td>
-        <td>Fired after a module dependencies has been resolved</td>
+        <td>Fired at the end of the resolve process, when all module dependencies have been resolved</td>
     </tr>
     <tr><td>pre-download-artifact</td>
         <td>
@@ -95,6 +104,7 @@
             <li>artifact</li>the name of the the artifact which is about to be downloaded
             <li>type</li>the type of the the artifact which is about to be downloaded
             <li>ext</li>the extension of the the artifact which is about to be downloaded
+            <li>metadata</li>true if the artifact to be downloaded is a metadata artifact, false for published artifacts <span class="since">since 2.0</span>
             <li>resolver</li>the name of the resolver used to download the artifact
             <li>origin</li>the origin location from which it will be downloaded
             <li>local</li>true if it's a local artifact, false otherwise
@@ -111,15 +121,47 @@
             <li>artifact</li>the name of the the artifact which was just downloaded
             <li>type</li>the type of the the artifact which was just downloaded
             <li>ext</li>the extension of the the artifact which was just downloaded
+            <li>metadata</li>true if the downloaded artifact is a metadata artifact, false for published artifacts <span class="since">since 2.0</span>
             <li>resolver</li>the name of the resolver used to download the artifact
             <li>origin</li>the origin location from which it was downloaded
             <li>local</li>true if it's a local artifact, false otherwise
             <li>size</li>the size in bytes of the downloaded artifact
+            <li>duration</li>the time elapsed to download the artifact (in ms) <span class="since">since 2.0</span>
             <li>file</li>the file to which it has been downloaded
           </ul>
         </td>
         <td>Fired after an artifact has been downloaded from a repository to the cache</td>
     </tr>
+    <tr><td>pre-retrieve <br><span class="since">since 2.0</span></td>
+        <td>
+          <ul>
+            <li>organisation</li>the organisation of the module for which the dependencies will be retrieved
+            <li>module</li>the name of the module for which the dependencies will be retrieved
+            <li>revision</li>the revision of the module for which the dependencies will be retrieved
+            <li>conf</li>comma separated list of configurations which will be retrieved
+            <li>symlink</li>true if Ivy will use symbolic links instead of copies on supported platforms, false otherwise
+            <li>sync</li>true if the retrieve process will be performed in sync mode, false otherwise
+          </ul>
+        </td>
+        <td>Fired at the beginning of the retrieve process.</td>
+    </tr>
+    <tr><td>post-retrieve <br><span class="since">since 2.0</span></td>
+        <td>
+          <ul>
+            <li>organisation</li>the organisation of the module for which the dependencies have been retrieved
+            <li>module</li>the name of the module for which the dependencies will be retrieved
+            <li>revision</li>the revision of the module for which the dependencies have been retrieved
+            <li>conf</li>comma separated list of configurations which have been retrieved
+            <li>symlink</li>true if Ivy used symbolic links instead of copies on supported platforms, false otherwise
+            <li>sync</li>true if the retrieve process has been performed in sync mode, false otherwise
+            <li>duration</li>the time elapsed in ms during the retrieve process
+            <li>size</li>the total size of artifacts which have actually been copied (or symlinked)
+            <li>nbCopied</li>the number of artifacts copied or symlinked
+            <li>nbUptodate</li>the number of artifacts which were already present and up to date at the destination location
+          </ul>
+        </td>
+        <td>Fired at the end of the retrieve process.</td>
+    </tr>
     <tr><td>pre-publish-artifact <br><span class="since">since 2.0</span></td>
         <td>
           <ul>
@@ -182,6 +224,7 @@
 <tbody>
 <tr><td>ant-build</td><td>Triggers an ant build.</td></tr>
 <tr><td>ant-call</td><td>Calls a target in the current ant build.</td></tr>
+<tr><td>log</td><td>Logs a message on the console or in a log file.</td></tr>
 </tbody>
 </table>
 
@@ -247,7 +290,17 @@
      <unzip src="${dep.file}" dest="${basedir}/out"/>
 </target>
 </code>
-	</textarea>
+<hr/>
+<code type="xml">
+<triggers>
+    <log file="ivy.log" 
+          message='downloaded "${origin}" to "${file}" (${duration}ms - ${size}B)'
+          event="post-download-artifact" filter="status=successful"/>
+</triggers>
+</code>
+Logs any successful artifact download, with information on the source and destination, and details on download size and duration.
+
+The file attribute is optional, the log trigger will output messages to console if it isn't provided.</textarea>
 <script type="text/javascript">xooki.postProcess();</script>
 </body>
 </html>

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java Tue Dec  4 12:39:16 2007
@@ -280,7 +280,7 @@
                 resolveEngine = new ResolveEngine(settings, eventManager, sortEngine);
             }
             if (retrieveEngine == null) {
-                retrieveEngine = new RetrieveEngine(settings);
+                retrieveEngine = new RetrieveEngine(settings, eventManager);
             }
             if (deliverEngine == null) {
                 deliverEngine = new DeliverEngine(settings);

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/DownloadEvent.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/DownloadEvent.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/DownloadEvent.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/DownloadEvent.java Tue Dec  4 12:39:16 2007
@@ -32,6 +32,7 @@
     protected void addArtifactAttributes(Artifact artifact) {
         addMridAttributes(artifact.getModuleRevisionId());
         addAttributes(artifact.getAttributes());
+        addAttribute("metadata", String.valueOf(artifact.isMetadata()));
     }
 
     public Artifact getArtifact() {

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/EndArtifactDownloadEvent.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/EndArtifactDownloadEvent.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/EndArtifactDownloadEvent.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/download/EndArtifactDownloadEvent.java Tue Dec  4 12:39:16 2007
@@ -38,12 +38,14 @@
         this.report = report;
         addAttribute("resolver", this.resolver.getName());
         addAttribute("status", this.report.getDownloadStatus().toString());
+        addAttribute("details", this.report.getDownloadDetails());
         addAttribute("size", String.valueOf(this.report.getSize()));
         addAttribute("file", dest.getAbsolutePath());
+        addAttribute("duration", String.valueOf(this.report.getDownloadTimeMillis()));
         ArtifactOrigin origin = report.getArtifactOrigin();
         if (origin != null) {
-            addAttribute("origin", this.report.getArtifactOrigin().getLocation());
-            addAttribute("local", String.valueOf(this.report.getArtifactOrigin().isLocal()));
+            addAttribute("origin", origin.getLocation());
+            addAttribute("local", String.valueOf(origin.isLocal()));
         } else {
             addAttribute("origin", "");
             addAttribute("local", "");

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveDependencyEvent.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveDependencyEvent.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveDependencyEvent.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveDependencyEvent.java Tue Dec  4 12:39:16 2007
@@ -26,10 +26,14 @@
 
     private ResolvedModuleRevision module;
 
+    private long duration;
+
     public EndResolveDependencyEvent(DependencyResolver resolver, DependencyDescriptor dd,
-            ResolvedModuleRevision module) {
+            ResolvedModuleRevision module, long duration) {
         super(NAME, resolver, dd);
         this.module = module;
+        this.duration = duration;
+        addAttribute("duration", String.valueOf(duration));
         if (this.module != null) {
             // override revision from the dependency descriptor
             addAttribute("revision", this.module.getDescriptor().getResolvedModuleRevisionId()
@@ -42,6 +46,22 @@
 
     public ResolvedModuleRevision getModule() {
         return module;
+    }
+    
+    /**
+     * Returns the time elapsed to resolve the dependency.
+     * <p>
+     * The time elapsed to resolve a dependency includes the time required to locate the the actual
+     * revision if the dependency descriptor use a version constraint, and to download the module
+     * metadata if necessary. It doesn't include any conflict management operations nor transitive
+     * dependency management. It's basically the time elapsed since the corresponding
+     * {@link StartResolveDependencyEvent}
+     * </p>
+     * 
+     * @return the time elapsed to resolve the dependency.
+     */
+    public long getDuration() {
+        return duration;
     }
 
 }

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveEvent.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveEvent.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveEvent.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/EndResolveEvent.java Tue Dec  4 12:39:16 2007
@@ -28,6 +28,12 @@
     public EndResolveEvent(ModuleDescriptor md, String[] confs, ResolveReport report) {
         super(NAME, md, confs);
         this.report = report;
+        addAttribute("resolve-id", String.valueOf(report.getResolveId()));
+        addAttribute("nb-dependencies", String.valueOf(report.getDependencies().size()));
+        addAttribute("nb-artifacts", String.valueOf(report.getArtifacts().size()));
+        addAttribute("resolve-duration", String.valueOf(report.getResolveTime()));
+        addAttribute("download-duration", String.valueOf(report.getDownloadTime()));
+        addAttribute("download-size", String.valueOf(report.getDownloadSize()));
     }
 
     public ResolveReport getReport() {

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/ResolveDependencyEvent.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/ResolveDependencyEvent.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/ResolveDependencyEvent.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/resolve/ResolveDependencyEvent.java Tue Dec  4 12:39:16 2007
@@ -34,6 +34,7 @@
         addAttribute("resolver", this.resolver.getName());
         addMridAttributes(this.dd.getDependencyRevisionId());
         addAttributes(this.dd.getExtraAttributes());
+        addAttribute("req-revision", dd.getDependencyRevisionId().getRevision());
     }
 
     public DependencyDescriptor getDependencyDescriptor() {

Added: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/EndRetrieveEvent.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/EndRetrieveEvent.java?rev=601077&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/EndRetrieveEvent.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/EndRetrieveEvent.java Tue Dec  4 12:39:16 2007
@@ -0,0 +1,83 @@
+/*
+ *  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.event.retrieve;
+
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.retrieve.RetrieveOptions;
+
+public class EndRetrieveEvent extends RetrieveEvent {
+    public static final String NAME = "post-retrieve";
+
+    private long duration;
+
+    private int nbCopied;
+
+    private int nbUpToDate;
+
+    private long totalCopiedSize;
+
+    public EndRetrieveEvent(ModuleRevisionId mrid, String[] confs, long elapsedTime,
+            int targetsCopied, int targetsUpToDate, long totalCopiedSize, RetrieveOptions options) {
+        super(NAME, mrid, confs, options);
+
+        this.duration = elapsedTime;
+        this.nbCopied = targetsCopied;
+        this.nbUpToDate = targetsUpToDate;
+        this.totalCopiedSize = totalCopiedSize;
+        addAttribute("duration", String.valueOf(elapsedTime));
+        addAttribute("size", String.valueOf(totalCopiedSize));
+        addAttribute("nbCopied", String.valueOf(targetsCopied));
+        addAttribute("nbUptodate", String.valueOf(targetsUpToDate));
+    }
+
+    /**
+     * Duration of the retrieve operation, in ms.
+     * 
+     * @return Duration of the retrieve operation, in ms.
+     */
+    public long getDuration() {
+        return duration;
+    }
+
+    /**
+     * Number of artifacts which were copied (or symlinked) during the retrieve
+     * 
+     * @return Number of artifacts which were copied during the retrieve.
+     */
+    public int getNbCopied() {
+        return nbCopied;
+    }
+
+    /**
+     * Number of artifacts which were not copied since they were already present and up to date.
+     * 
+     * @return Number of artifacts which were not copied since they were already present and up to
+     *         date.
+     */
+    public int getNbUpToDate() {
+        return nbUpToDate;
+    }
+    
+    /**
+     * Total size of all copied (or symlinked) artifacts, in bytes.
+     * @return Total size of all copied (or symlinked) artifacts, in bytes.
+     */
+    public long getTotalCopiedSize() {
+        return totalCopiedSize;
+    }
+}

Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/EndRetrieveEvent.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/RetrieveEvent.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/RetrieveEvent.java?rev=601077&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/RetrieveEvent.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/RetrieveEvent.java Tue Dec  4 12:39:16 2007
@@ -0,0 +1,46 @@
+/*
+ *  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.event.retrieve;
+
+import org.apache.ivy.core.event.IvyEvent;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.retrieve.RetrieveOptions;
+
+public class RetrieveEvent extends IvyEvent {
+    private ModuleRevisionId mrid;
+    private RetrieveOptions options;
+
+    protected RetrieveEvent(String name, ModuleRevisionId mrid, 
+            String[] confs, RetrieveOptions options) {
+        super(name);
+        this.mrid = mrid;
+        addMridAttributes(mrid);
+        addConfsAttribute(confs);
+        addAttribute("symlink", String.valueOf(options.isMakeSymlinks()));
+        addAttribute("sync", String.valueOf(options.isSync()));
+        this.options = options;
+    }
+
+    public ModuleRevisionId getModuleRevisionId() {
+        return mrid;
+    }
+    
+    public RetrieveOptions getOptions() {
+        return options;
+    }
+}

Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/RetrieveEvent.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/StartRetrieveEvent.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/StartRetrieveEvent.java?rev=601077&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/StartRetrieveEvent.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/StartRetrieveEvent.java Tue Dec  4 12:39:16 2007
@@ -0,0 +1,29 @@
+/*
+ *  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.event.retrieve;
+
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.retrieve.RetrieveOptions;
+
+public class StartRetrieveEvent extends RetrieveEvent {
+    public static final String NAME = "pre-retrieve";
+
+    public StartRetrieveEvent(ModuleRevisionId mrid, String[] confs, RetrieveOptions options) {
+        super(NAME, mrid, confs, options);
+    }
+}

Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/core/event/retrieve/StartRetrieveEvent.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ArtifactDownloadReport.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ArtifactDownloadReport.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ArtifactDownloadReport.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ArtifactDownloadReport.java Tue Dec  4 12:39:16 2007
@@ -119,8 +119,13 @@
         if (downloadStatus == DownloadStatus.SUCCESSFUL) {
             return "[SUCCESSFUL ] " + artifact + " (" + downloadTimeMillis + "ms)";
         } else if (downloadStatus == DownloadStatus.FAILED) {
-            return "[FAILED     ] " + artifact + ": " + downloadDetails
+            if (downloadDetails == MISSING_ARTIFACT) {
+                return "[NOT FOUND  ] " + artifact
                 + " (" + downloadTimeMillis + "ms)";
+            } else {
+                return "[FAILED     ] " + artifact + ": " + downloadDetails
+                    + " (" + downloadTimeMillis + "ms)";
+            }
         } else if (downloadStatus == DownloadStatus.NO) {
             return "[NOT REQUIRED] " + artifact;
         } else {

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ResolveReport.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ResolveReport.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ResolveReport.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/report/ResolveReport.java Tue Dec  4 12:39:16 2007
@@ -43,13 +43,12 @@
 
     private Map confReports = new LinkedHashMap();
 
-    private List problemMessages;
+    private List problemMessages = new ArrayList();
 
-    private List dependencies; // the list of all dependencies resolved, ordered from the more
+    private List dependencies = new ArrayList(); 
+    // the list of all dependencies resolved, ordered from the more dependent to the less dependent
 
-    // dependent to the less dependent
-
-    private List artifacts;
+    private List artifacts = new ArrayList();
 
     private long resolveTime;
 
@@ -57,6 +56,8 @@
 
     private String resolveId;
 
+    private long downloadSize;
+
     public ResolveReport(ModuleDescriptor md) {
         this(md, ResolveOptions.getDefaultResolveId(md));
     }
@@ -237,6 +238,23 @@
 
     public long getDownloadTime() {
         return downloadTime;
+    }
+
+    public void setDownloadSize(long size) {
+        this.downloadSize = size;
+    }
+    
+    /**
+     * The total size of downloaded artifacts, in bytes.
+     * <p>
+     * This only includes artifacts actually downloaded to cache (DownloadStatus.SUCCESSFUL), and
+     * not artifacts already in cache or used at their original location.
+     * </p>
+     * 
+     * @return The total size of downloaded artifacts, in bytes.
+     */
+    public long getDownloadSize() {
+        return downloadSize;
     }
 
     public String getResolveId() {

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java Tue Dec  4 12:39:16 2007
@@ -217,11 +217,13 @@
                 try {
                     Message.debug("\tusing " + resolver + " to resolve " + getId());
                     DependencyDescriptor dependencyDescriptor = getDependencyDescriptor(parent);
+                    long start = System.currentTimeMillis();
                     data.getEventManager().fireIvyEvent(
                         new StartResolveDependencyEvent(resolver, dependencyDescriptor));
                     module = resolver.getDependency(dependencyDescriptor, data);
                     data.getEventManager().fireIvyEvent(
-                        new EndResolveDependencyEvent(resolver, dependencyDescriptor, module));
+                        new EndResolveDependencyEvent(resolver, dependencyDescriptor, module,
+                            System.currentTimeMillis() - start));
                     if (module != null) {
                         data.getCacheManager().saveResolver(module.getDescriptor(),
                             module.getResolver().getName());

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java Tue Dec  4 12:39:16 2007
@@ -306,7 +306,8 @@
 
     public void outputReport(ResolveReport report, ResolutionCacheManager cacheMgr) 
             throws IOException {
-        Message.info(":: resolution report ::");
+        Message.info(":: resolution report :: resolve " + report.getResolveTime() + "ms"
+            + " :: artifacts dl " + report.getDownloadTime() + "ms");
         report.setProblemMessages(Message.getProblems());
         // output report
         report.output(settings.getReportOutputters(), cacheMgr);
@@ -321,6 +322,7 @@
         eventManager.fireIvyEvent(new PrepareDownloadEvent((Artifact[]) report.getArtifacts()
                 .toArray(new Artifact[report.getArtifacts().size()])));
 
+        long totalSize = 0;
         for (int i = 0; i < dependencies.length; i++) {
             checkInterrupted();
             // download artifacts required in all asked configurations
@@ -333,8 +335,10 @@
                 ArtifactDownloadReport[] adrs = dReport.getArtifactsReports();
                 for (int j = 0; j < adrs.length; j++) {
                     if (adrs[j].getDownloadStatus() == DownloadStatus.FAILED) {
-                        Message.warn("\t[NOT FOUND  ] " + adrs[j].getArtifact());
+                        Message.warn("\t" + adrs[j]);
                         resolver.reportFailure(adrs[j].getArtifact());
+                    } else if (adrs[j].getDownloadStatus() == DownloadStatus.SUCCESSFUL) {
+                        totalSize += adrs[j].getSize();
                     }
                 }
                 // update concerned reports
@@ -354,6 +358,7 @@
             }
         }
         report.setDownloadTime(System.currentTimeMillis() - start);
+        report.setDownloadSize(totalSize);
     }
 
     /**

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/retrieve/RetrieveEngine.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/retrieve/RetrieveEngine.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/retrieve/RetrieveEngine.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/retrieve/RetrieveEngine.java Tue Dec  4 12:39:16 2007
@@ -38,6 +38,9 @@
 import org.apache.ivy.core.cache.CacheManager;
 import org.apache.ivy.core.cache.RepositoryCacheManager;
 import org.apache.ivy.core.cache.ResolutionCacheManager;
+import org.apache.ivy.core.event.EventManager;
+import org.apache.ivy.core.event.retrieve.EndRetrieveEvent;
+import org.apache.ivy.core.event.retrieve.StartRetrieveEvent;
 import org.apache.ivy.core.module.descriptor.Artifact;
 import org.apache.ivy.core.module.descriptor.DefaultArtifact;
 import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
@@ -52,10 +55,15 @@
 import org.apache.ivy.util.Message;
 
 public class RetrieveEngine {
+    private static final int KILO = 1024;
+
     private RetrieveEngineSettings settings;
 
-    public RetrieveEngine(RetrieveEngineSettings settings) {
+    private EventManager eventManager;
+
+    public RetrieveEngine(RetrieveEngineSettings settings, EventManager eventManager) {
         this.settings = settings;
+        this.eventManager = eventManager;
     }
 
     /**
@@ -80,6 +88,9 @@
         RepositoryCacheManager cacheManager = getCacheManager(options);
         String[] confs = getConfs(mrid, options);
         Message.info("\tconfs: " + Arrays.asList(confs));
+        if (this.eventManager != null) {
+            this.eventManager.fireIvyEvent(new StartRetrieveEvent(mrid, confs, options));
+        }
 
         try {
             Map artifactsToCopy = determineArtifactsToCopy(mrid, destFilePattern, options);
@@ -95,6 +106,7 @@
             // do retrieve
             int targetsCopied = 0;
             int targetsUpToDate = 0;
+            long totalCopiedSize = 0;
             for (Iterator iter = artifactsToCopy.keySet().iterator(); iter.hasNext();) {
                 Artifact artifact = (Artifact) iter.next();
                 File archive;
@@ -123,6 +135,7 @@
                         } else {
                             FileUtil.copy(archive, destFile, null, true);
                         }
+                        totalCopiedSize += destFile.length();
                         targetsCopied++;
                     } else {
                         Message.verbose("\t\tto " + destFile + " [NOT REQUIRED]");
@@ -157,12 +170,19 @@
                     }
                 }
             }
+            long elapsedTime = System.currentTimeMillis() - start;
             Message.info("\t"
                     + targetsCopied
                     + " artifacts copied"
                     + (settings.isCheckUpToDate() ? (", " + targetsUpToDate + " already retrieved")
-                            : ""));
-            Message.verbose("\tretrieve done (" + (System.currentTimeMillis() - start) + "ms)");
+                            : "")
+                    + " (" + (totalCopiedSize / KILO) + "kB/" + elapsedTime + "ms)");
+            Message.verbose("\tretrieve done (" + (elapsedTime) + "ms)");
+            if (this.eventManager != null) {
+                this.eventManager.fireIvyEvent(new EndRetrieveEvent(
+                    mrid, confs, elapsedTime, targetsCopied, targetsUpToDate, totalCopiedSize, 
+                    options));
+            }
 
             return targetsCopied;
         } catch (Exception ex) {

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties Tue Dec  4 12:39:16 2007
@@ -50,3 +50,4 @@
 
 ant-build		= org.apache.ivy.ant.AntBuildTrigger
 ant-call		= org.apache.ivy.ant.AntCallTrigger
+log		        = org.apache.ivy.plugins.trigger.LogTrigger

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/repository/TransferEvent.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/repository/TransferEvent.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/repository/TransferEvent.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/repository/TransferEvent.java Tue Dec  4 12:39:16 2007
@@ -73,6 +73,11 @@
     public static final int TRANSFER_ERROR = 4;
 
     /**
+     * Used to check event type validity: should always be 0 <= type <= LAST_EVENT_TYPE
+     */
+    private static final int LAST_EVENT_TYPE = TRANSFER_ERROR;
+    
+    /**
      * Indicates GET transfer (from the repository)
      */
     public static final int REQUEST_GET = 5;
@@ -109,20 +114,26 @@
     private long totalLength;
 
     private boolean isTotalLengthSet = false;
+    
+    /**
+     * This attribute is used to store the time at which the event enters a type.
+     * <p>
+     * The array should better be seen as a Map from event type (int) to the time at which the event
+     * entered that type, 0 if it never entered this type.
+     * </p>
+     */
+    private long[] timeTracking = new long[LAST_EVENT_TYPE + 1];
 
     public TransferEvent(final Repository repository, final Resource resource, final int eventType,
             final int requestType) {
         super(getName(eventType));
 
         this.repository = repository;
-        addAttribute("repository", this.repository.getName());
-        this.resource = resource;
-        addAttribute("resource", this.resource.getName());
+        setResource(resource);
 
         setEventType(eventType);
 
         setRequestType(requestType);
-        addAttribute("request-type", requestType == REQUEST_GET ? "get" : "put");
     }
 
     public TransferEvent(final Repository repository, final Resource resource,
@@ -202,6 +213,7 @@
         }
 
         this.requestType = requestType;
+        addAttribute("request-type", requestType == REQUEST_GET ? "get" : "put");
     }
 
     /**
@@ -216,23 +228,19 @@
      *            The eventType to set.
      */
     protected void setEventType(final int eventType) {
-        switch (eventType) {
-
-            case TRANSFER_INITIATED:
-                break;
-            case TRANSFER_STARTED:
-                break;
-            case TRANSFER_COMPLETED:
-                break;
-            case TRANSFER_PROGRESS:
-                break;
-            case TRANSFER_ERROR:
-                break;
-            default:
-                throw new IllegalArgumentException("Illegal event type: " + eventType);
+        checkEventType(eventType);
+        if (this.eventType != eventType) {
+            this.eventType = eventType;
+            timeTracking[eventType] = System.currentTimeMillis();
+            if (eventType > TRANSFER_INITIATED) {
+                addAttribute("total-duration", 
+                    String.valueOf(getElapsedTime(TRANSFER_INITIATED, eventType)));
+                if (eventType > TRANSFER_STARTED) {
+                    addAttribute("duration", 
+                        String.valueOf(getElapsedTime(TRANSFER_STARTED, eventType)));
+                }
+            }
         }
-
-        this.eventType = eventType;
     }
 
     /**
@@ -241,6 +249,7 @@
      */
     protected void setResource(final Resource resource) {
         this.resource = resource;
+        addAttribute("resource", this.resource.getName());
     }
 
     /**
@@ -285,5 +294,61 @@
     public void setTotalLengthSet(boolean isTotalLengthSet) {
         this.isTotalLengthSet = isTotalLengthSet;
     }
+    
+    public Repository getRepository() {
+        return repository;
+    }
 
+    /**
+     * Returns the elapsed time (in ms) between when the event entered one type until it entered
+     * another event time.
+     * <p>
+     * This is especially useful to get the elapsed transfer time:
+     * <pre>
+     * getElapsedTime(TransferEvent.TRANSFER_STARTED, TransferEvent.TRANSFER_COMPLETED);
+     * </pre>
+     * </p>
+     * <p>
+     * Special cases:
+     * <ul>
+     * <li>returns -1 if the event never entered the fromEventType or the toEventType.</li>
+     * <li>returns 0 if the event entered toEventType before fromEventType</li>
+     * </ul>
+     * </p>
+     * 
+     * @param fromEventType
+     *            the event type constant from which time should be measured
+     * @param toEventType
+     *            the event type constant to which time should be measured
+     * @return the elapsed time (in ms) between when the event entered fromEventType until it
+     *         entered toEventType.
+     * @throws IllegalArgumentException
+     *             if either type is not a known constant event type.
+     */
+    public long getElapsedTime(int fromEventType, int toEventType) {
+        checkEventType(fromEventType);
+        checkEventType(toEventType);
+        long start = timeTracking[fromEventType];
+        long end = timeTracking[toEventType];
+        if (start == 0 || end == 0) {
+            return -1;
+        } else if (end < start) {
+            return 0;
+        } else {
+            return end - start;
+        }
+    }
+
+    /**
+     * Checks the given event type is a valid event type, throws an {@link IllegalArgumentException}
+     * if it isn't
+     * 
+     * @param eventType
+     *            the event type to check
+     */
+    private void checkEventType(int eventType) {
+        if (eventType < 0 || eventType > LAST_EVENT_TYPE) {
+            throw new IllegalArgumentException("invalid event type " + eventType);
+        }
+    }
 }

Added: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/trigger/LogTrigger.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/trigger/LogTrigger.java?rev=601077&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/trigger/LogTrigger.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/trigger/LogTrigger.java Tue Dec  4 12:39:16 2007
@@ -0,0 +1,127 @@
+/*
+ *  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.plugins.trigger;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+import org.apache.ivy.core.IvyPatternHelper;
+import org.apache.ivy.core.event.IvyEvent;
+import org.apache.ivy.core.resolve.ResolveProcessException;
+import org.apache.ivy.util.Message;
+
+/**
+ * A trigger performing logging.
+ * <p>
+ * The implementation is widely inspired by Ant Echo task.
+ * </p>
+ */
+public class LogTrigger extends AbstractTrigger {
+    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+    private String message = "";
+    
+    private File file = null;
+
+    private boolean append = true;
+    /** encoding; set to null or empty means 'default' */
+    private String encoding = "";
+
+    public void progress(IvyEvent event) {
+        log(IvyPatternHelper.substituteVariables(message, event.getAttributes()));
+    }
+
+    /**
+     * Logs the given message.
+     * 
+     * @param message the message to log
+     */
+    protected void log(String message) {
+        if (file == null) {
+            Message.info(message);
+        } else {
+            Writer out = null;
+            try {
+                // we add a line separator here for consistency with Message.info which creates a
+                // new line each time.
+                // we use the system dependent line separator to ease reading the log file
+                message += LINE_SEPARATOR;
+                String filename = file.getAbsolutePath();
+                if (encoding == null || encoding.length() == 0) {
+                    out = new FileWriter(filename, append);
+                } else {
+                    out = new BufferedWriter(
+                            new OutputStreamWriter(
+                                new FileOutputStream(filename, append), encoding));
+                }
+                out.write(message, 0, message.length());
+            } catch (IOException e) {
+                throw new ResolveProcessException(e);
+            } finally {
+                if (out != null) {
+                    try {
+                        out.close();
+                    } catch (IOException e) {
+                        throw new ResolveProcessException(e);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Message to write.
+     *
+     * @param msg Sets the value for the message variable.
+     */
+    public void setMessage(String msg) {
+        this.message = msg;
+    }
+
+    /**
+     * File to write to.
+     * @param file the file to write to, if not set, echo to
+     *             standard Ivy logging
+     */
+    public void setFile(String file) {
+        this.file = new File(file);
+    }
+
+    /**
+     * If true, append to existing file.
+     * @param append if true, append to existing file, default
+     *               is false.
+     */
+    public void setAppend(boolean append) {
+        this.append = append;
+    }
+
+    /**
+     * Declare the encoding to use when outputting to a file;
+     * Use "" for the platform's default encoding.
+     * @param encoding the character encoding to use.
+     */
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+}

Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/trigger/LogTrigger.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/util/FileUtil.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/FileUtil.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/util/FileUtil.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/FileUtil.java Tue Dec  4 12:39:16 2007
@@ -193,16 +193,75 @@
         }
     }
 
+    /**
+     * Reads the whole BufferedReader line by line, using \n as line separator for each line.
+     * <p>
+     * Note that this method will add a final \n to the last line even though there is no new line
+     * character at the end of last line in the original reader.
+     * </p>
+     * <p>
+     * The BufferedReader is closed when this method returns.
+     * </p>
+     * 
+     * @param in
+     *            the {@link BufferedReader} to read from
+     * @return a String with the whole content read from the {@link BufferedReader}
+     * @throws IOException
+     *             if an IO problems occur during reading
+     */
     public static String readEntirely(BufferedReader in) throws IOException {
-        StringBuffer buf = new StringBuffer();
+        try {
+            StringBuffer buf = new StringBuffer();
 
-        String line = in.readLine();
-        while (line != null) {
-            buf.append(line + "\n");
-            line = in.readLine();
+            String line = in.readLine();
+            while (line != null) {
+                buf.append(line + "\n");
+                line = in.readLine();
+            }
+            return buf.toString();
+        } finally {
+            in.close();
+        }
+    }
+
+    /**
+     * Reads the entire content of the file and returns it as a String.
+     * 
+     * @param f
+     *            the file to read from
+     * @return a String with the file content
+     * @throws IOException
+     *             if an IO problems occurs during reading
+     */
+    public static String readEntirely(File f) throws IOException {
+        return readEntirely(new FileInputStream(f));
+    }
+    
+    /**
+     * Reads the entire content of the {@link InputStream} and returns it as a String.
+     * <p>
+     * The input stream is closed when this method returns.
+     * </p>
+     * 
+     * @param is
+     *            the {@link InputStream} to read from
+     * @return a String with the input stream content
+     * @throws IOException
+     *             if an IO problems occurs during reading
+     */
+    public static String readEntirely(InputStream is) throws IOException {
+        try {
+            StringBuffer sb = new StringBuffer();
+            byte[] buffer = new byte[BUFFER_SIZE];
+            int c;
+
+            while ((c = is.read(buffer)) != -1) {
+                sb.append(new String(buffer, 0, c));
+            }
+            return sb.toString();
+        } finally {
+            is.close();
         }
-        in.close();
-        return buf.toString();
     }
 
     public static String concat(String dir, String file) {

Modified: ant/ivy/core/trunk/test/java/org/apache/ivy/core/retrieve/RetrieveTest.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/core/retrieve/RetrieveTest.java?rev=601077&r1=601076&r2=601077&view=diff
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/core/retrieve/RetrieveTest.java (original)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/core/retrieve/RetrieveTest.java Tue Dec  4 12:39:16 2007
@@ -19,12 +19,18 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 import junit.framework.TestCase;
 
 import org.apache.ivy.Ivy;
 import org.apache.ivy.core.IvyPatternHelper;
 import org.apache.ivy.core.cache.CacheManager;
+import org.apache.ivy.core.event.IvyEvent;
+import org.apache.ivy.core.event.IvyListener;
+import org.apache.ivy.core.event.retrieve.EndRetrieveEvent;
+import org.apache.ivy.core.event.retrieve.StartRetrieveEvent;
 import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
 import org.apache.ivy.core.report.ResolveReport;
 import org.apache.ivy.core.resolve.ResolveOptions;
@@ -80,6 +86,37 @@
         ivy.retrieve(md.getModuleRevisionId(), pattern, getRetrieveOptions());
         assertTrue(new File(IvyPatternHelper.substitute(pattern, "org1", "mod1.2", "2.0", "mod1.2",
             "jar", "jar", "default")).exists());
+    }
+
+    public void testEvent() throws Exception {
+        ResolveReport report = ivy.resolve(new File(
+                "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml").toURL(),
+            getResolveOptions(new String[] {"*"}));
+
+        final List events = new ArrayList();
+        ivy.getEventManager().addIvyListener(new IvyListener() {
+            public void progress(IvyEvent event) {
+                events.add(event);
+            }
+        });
+        ModuleDescriptor md = report.getModuleDescriptor();
+        String pattern = "build/test/retrieve/[module]/[conf]/[artifact]-[revision].[ext]";
+        ivy.retrieve(md.getModuleRevisionId(), pattern, getRetrieveOptions());
+        assertEquals(2, events.size());
+        assertTrue(events.get(0) instanceof StartRetrieveEvent);
+        assertTrue(events.get(1) instanceof EndRetrieveEvent);
+        EndRetrieveEvent ev = (EndRetrieveEvent) events.get(1);
+        assertEquals(1, ev.getNbCopied());
+        assertEquals(0, ev.getNbUpToDate());
+
+        events.clear();
+        ivy.retrieve(md.getModuleRevisionId(), pattern, getRetrieveOptions());
+        assertEquals(2, events.size());
+        assertTrue(events.get(0) instanceof StartRetrieveEvent);
+        assertTrue(events.get(1) instanceof EndRetrieveEvent);
+        ev = (EndRetrieveEvent) events.get(1);
+        assertEquals(0, ev.getNbCopied());
+        assertEquals(1, ev.getNbUpToDate());
     }
 
     public void testRetrieveOverwrite() throws Exception {

Added: ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/trigger/LogTriggerTest.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/trigger/LogTriggerTest.java?rev=601077&view=auto
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/trigger/LogTriggerTest.java (added)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/trigger/LogTriggerTest.java Tue Dec  4 12:39:16 2007
@@ -0,0 +1,91 @@
+/*
+ *  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.plugins.trigger;
+
+import java.io.File;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+import org.apache.ivy.core.event.resolve.StartResolveEvent;
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.util.FileUtil;
+import org.apache.ivy.util.Message;
+import org.apache.ivy.util.MockMessageLogger;
+
+public class LogTriggerTest extends TestCase {
+    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+    
+    private StartResolveEvent ev;
+    private LogTrigger trigger;
+    private File testDir;
+
+    protected void setUp() {
+        ev = new StartResolveEvent(
+            DefaultModuleDescriptor.newBasicInstance(ModuleRevisionId.parse("o#A;1"), new Date()), 
+            new String[] {"c"});
+        trigger = new LogTrigger();
+        trigger.setEvent(ev.getName());
+        testDir = new File("build/test/trigger");
+        testDir.mkdirs();
+    }
+    
+    protected void tearDown() throws Exception {
+        FileUtil.forceDelete(testDir);
+    }
+
+    public void testMessage() throws Exception {
+        trigger.setMessage("msg: ${organisation} ${module} ${revision}");
+        
+        MockMessageLogger mockLogger = new MockMessageLogger();
+        Message.setDefaultLogger(mockLogger);
+        trigger.progress(ev);
+        
+        mockLogger.assertLogInfoContains("msg: o A 1");
+    }
+    
+    public void testFile() throws Exception {
+        trigger.setMessage("msg: ${organisation} ${module} ${revision}");
+        File f = new File(testDir, "test.log");
+        trigger.setFile(f.getPath());
+        
+        trigger.progress(ev);
+        
+        assertTrue(f.exists());
+        assertEquals("msg: o A 1" + LINE_SEPARATOR, FileUtil.readEntirely(f));
+
+        trigger.progress(ev);
+        
+        assertEquals("msg: o A 1" + LINE_SEPARATOR + "msg: o A 1" + LINE_SEPARATOR, 
+            FileUtil.readEntirely(f));
+    }
+    
+    public void testFileNoAppend() throws Exception {
+        trigger.setMessage("msg: ${organisation} ${module} ${revision}");
+        File f = new File(testDir, "test.log");
+        trigger.setFile(f.getPath());
+        trigger.setAppend(false);
+        
+        trigger.progress(ev);
+        trigger.progress(ev);
+        
+        assertTrue(f.exists());
+        assertEquals("msg: o A 1" + LINE_SEPARATOR, FileUtil.readEntirely(f));
+    }
+}

Propchange: ant/ivy/core/trunk/test/java/org/apache/ivy/plugins/trigger/LogTriggerTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message