You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ivy-commits@incubator.apache.org by xa...@apache.org on 2007/12/01 02:30:54 UTC
svn commit: r600041 - in /incubator/ivy/core/trunk: ./ doc/configuration/
src/java/org/apache/ivy/ src/java/org/apache/ivy/core/event/publish/
src/java/org/apache/ivy/core/publish/ test/java/org/apache/ivy/core/publish/
Author: xavier
Date: Fri Nov 30 18:30:50 2007
New Revision: 600041
URL: http://svn.apache.org/viewvc?rev=600041&view=rev
Log:
IMPROVEMENT: add publish triggers to event system (IVY-650) (thanks to Jason Trump)
Added:
incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/
incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/EndArtifactPublishEvent.java (with props)
incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/PublishEvent.java (with props)
incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/StartArtifactPublishEvent.java (with props)
incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEventsTest.java (with props)
incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivy-1.0-dev.xml (with props)
incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivysettings-publisheventstest.xml (with props)
Modified:
incubator/ivy/core/trunk/CHANGES.txt
incubator/ivy/core/trunk/doc/configuration/triggers.html
incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java
incubator/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java
incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEngineTest.java
Modified: incubator/ivy/core/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/CHANGES.txt?rev=600041&r1=600040&r2=600041&view=diff
==============================================================================
--- incubator/ivy/core/trunk/CHANGES.txt (original)
+++ incubator/ivy/core/trunk/CHANGES.txt Fri Nov 30 18:30:50 2007
@@ -49,6 +49,7 @@
Andreas Sahlbach
John Shields
Johan Stuyts
+ Jason Trump
Tjeerd Verhagen
John Williams
Jaroslaw Wypychowski
@@ -74,7 +75,7 @@
- FIX: Invalid character in IvyRetrieveTest causing most tests to fail (IVY-604)
- FIX: ivy:settings and ivy:retrieve with explicit id causes unwarranted DEPRECATED warning (thanks to Jacob Grydholt Jensen)
-
+- IMPROVEMENT: add publish triggers to event system (IVY-650) (thanks to Jason Trump)
- IMPROVEMENT: Only display unique circular dependencies during Resolve (IVY-653)
- IMPROVEMENT: Adding option 'cp', which makes it possible for main to be loaded from file (IVY-543) (thanks to Tjeerd Verhagen)
- IMPROVEMENT: BasicURLHandler should use method=head for getURLInfo (IVY-611) (thanks to Jim Bonanno)
Modified: incubator/ivy/core/trunk/doc/configuration/triggers.html
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/doc/configuration/triggers.html?rev=600041&r1=600040&r2=600041&view=diff
==============================================================================
--- incubator/ivy/core/trunk/doc/configuration/triggers.html (original)
+++ incubator/ivy/core/trunk/doc/configuration/triggers.html Fri Nov 30 18:30:50 2007
@@ -120,6 +120,41 @@
</td>
<td>Fired after an artifact has been downloaded from a repository to the cache</td>
</tr>
+ <tr><td>pre-publish-artifact <br><span class="since">since 2.0</span></td>
+ <td>
+ <ul>
+ <li>organisation</li>the organisation of the artifact which is about to be published
+ <li>module</li>the name of the module of the artifact which is about to be published
+ <li>revision</li>the revision of the the artifact which is about to be published
+ <li>artifact</li>the name of the the artifact which is about to be published
+ <li>type</li>the type of the the artifact which is about to be published
+ <li>ext</li>the extension of the the artifact which is about to be published
+ <li>resolver</li>the name of the resolver into which the artifact is about to be published
+ <li>file</li>the absolute path of the source file for the artifact
+ <li>overwrite</li>"true" if the new data will overwrite existing artifacts, "false" otherwise
+ </ul>
+ </td>
+ <td>Fired before an artifact is published into a repository</td>
+ </tr>
+ <tr><td>post-publish-artifact <br><span class="since">since 2.0</span></td>
+ <td>
+ <ul>
+ <li>organisation</li>the organisation of the artifact that was published
+ <li>module</li>the name of the module of the artifact that was published
+ <li>revision</li>the revision of the the artifact that was published
+ <li>artifact</li>the name of the the artifact that was published
+ <li>type</li>the type of the the artifact that was published
+ <li>ext</li>the extension of the the artifact that was published
+ <li>resolver</li>the name of the resolver into which the artifact was published
+ <li>file</li>the absolute path of the source file for the artifact
+ <li>overwrite</li>"true" if the new data overwrote existing artifacts, "false" otherwise
+ <li>status</li>"successful" if the artifact published successfully; "failed" if the artifact failed to publish, or if the status is unknown
+ </ul>
+ </td>
+ <td>Fired after an artifact is published into a repository. Note that this event is fired
+ whether or not the publication succeeded. The "status" property can be checked to
+ verify success.</td>
+ </tr>
</tbody>
</table>
Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java?rev=600041&r1=600040&r2=600041&view=diff
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java Fri Nov 30 18:30:50 2007
@@ -286,7 +286,7 @@
deliverEngine = new DeliverEngine(settings);
}
if (publishEngine == null) {
- publishEngine = new PublishEngine(settings);
+ publishEngine = new PublishEngine(settings, eventManager);
}
if (installEngine == null) {
installEngine = new InstallEngine(
@@ -810,7 +810,7 @@
DependencyResolver resolver = (DependencyResolver) iter.next();
if (resolver instanceof BasicResolver) {
((BasicResolver) resolver).setEventManager(eventManager);
- }
+ }
}
}
Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/EndArtifactPublishEvent.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/EndArtifactPublishEvent.java?rev=600041&view=auto
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/EndArtifactPublishEvent.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/EndArtifactPublishEvent.java Fri Nov 30 18:30:50 2007
@@ -0,0 +1,56 @@
+/*
+ * 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.publish;
+
+import java.io.File;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+
+/**
+ * Event fired after artifact publication has finished (possibly in error). Triggers registered on
+ * {@link #NAME} will be notified of these events.
+ *
+ * @see DependencyResolver#publish(Artifact, File, boolean)
+ */
+public class EndArtifactPublishEvent extends PublishEvent {
+
+ private static final long serialVersionUID = -65690169431499422L;
+
+ public static final String NAME = "post-publish-artifact";
+
+ public static final String STATUS_SUCCESSFUL = "successful";
+
+ public static final String STATUS_FAILED = "failed";
+
+ private final boolean successful;
+
+ public EndArtifactPublishEvent(DependencyResolver resolver, Artifact artifact, File data,
+ boolean overwrite, boolean successful) {
+ super(NAME, resolver, artifact, data, overwrite);
+ this.successful = successful;
+ addAttribute("status", isSuccessful() ? STATUS_SUCCESSFUL : STATUS_FAILED);
+ }
+
+ /**
+ * @return true iff no errors were encountered during the publication
+ */
+ public boolean isSuccessful() {
+ return successful;
+ }
+}
Propchange: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/EndArtifactPublishEvent.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/PublishEvent.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/PublishEvent.java?rev=600041&view=auto
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/PublishEvent.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/PublishEvent.java Fri Nov 30 18:30:50 2007
@@ -0,0 +1,77 @@
+/*
+ * 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.publish;
+
+import java.io.File;
+
+import org.apache.ivy.core.event.IvyEvent;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+
+/**
+ * Base class for events fired during {@link DependencyResolver#publish(Artifact, File, boolean)}.
+ *
+ * @see StartArtifactPublishEvent
+ * @see EndArtifactPublishEvent
+ */
+public abstract class PublishEvent extends IvyEvent {
+
+ private final DependencyResolver resolver;
+
+ private final Artifact artifact;
+
+ private final File data;
+
+ private final boolean overwrite;
+
+ protected PublishEvent(String name, DependencyResolver resolver, Artifact artifact, File data,
+ boolean overwrite) {
+ super(name);
+ this.resolver = resolver;
+ this.artifact = artifact;
+ this.data = data;
+ this.overwrite = overwrite;
+
+ addMridAttributes(artifact.getModuleRevisionId());
+ addAttributes(artifact.getAttributes());
+ addAttribute("resolver", resolver.getName());
+ addAttribute("file", data.getAbsolutePath());
+ addAttribute("overwrite", String.valueOf(overwrite));
+ }
+
+ /** @return the resolver into which the artifact is being published */
+ public DependencyResolver getResolver() {
+ return resolver;
+ }
+
+ /** @return a local file containing the artifact data */
+ public File getData() {
+ return data;
+ }
+
+ /** @return metadata about the artifact being published */
+ public Artifact getArtifact() {
+ return artifact;
+ }
+
+ /** @return true iff this event overwrites existing resolver data for this artifact */
+ public boolean isOverwrite() {
+ return overwrite;
+ }
+
+}
Propchange: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/PublishEvent.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/StartArtifactPublishEvent.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/StartArtifactPublishEvent.java?rev=600041&view=auto
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/StartArtifactPublishEvent.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/StartArtifactPublishEvent.java Fri Nov 30 18:30:50 2007
@@ -0,0 +1,42 @@
+/*
+ * 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.publish;
+
+import java.io.File;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+
+/**
+ * Event fired just before an artifact is published into a resolver. Triggers registered on
+ * {@link #NAME} will be notified of these events.
+ *
+ * @see DependencyResolver#publish(Artifact, File, boolean)
+ */
+public class StartArtifactPublishEvent extends PublishEvent {
+
+ private static final long serialVersionUID = -1134274781039590219L;
+
+ public static final String NAME = "pre-publish-artifact";
+
+ public StartArtifactPublishEvent(DependencyResolver resolver, Artifact artifact, File data,
+ boolean overwrite) {
+ super(NAME, resolver, artifact, data, overwrite);
+ }
+
+}
Propchange: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/publish/StartArtifactPublishEvent.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java?rev=600041&r1=600040&r2=600041&view=diff
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java Fri Nov 30 18:30:50 2007
@@ -33,8 +33,10 @@
import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.IvyPatternHelper;
-import org.apache.ivy.core.cache.CacheManager;
import org.apache.ivy.core.cache.ResolutionCacheManager;
+import org.apache.ivy.core.event.EventManager;
+import org.apache.ivy.core.event.publish.EndArtifactPublishEvent;
+import org.apache.ivy.core.event.publish.StartArtifactPublishEvent;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
import org.apache.ivy.core.module.descriptor.MDArtifact;
@@ -49,9 +51,11 @@
public class PublishEngine {
private PublishEngineSettings settings;
+ private EventManager eventManager;
- public PublishEngine(PublishEngineSettings settings) {
+ public PublishEngine(PublishEngineSettings settings, EventManager eventManager) {
this.settings = settings;
+ this.eventManager = eventManager;
}
/**
@@ -228,11 +232,21 @@
DependencyResolver resolver, boolean overwrite) throws IOException {
IvyContext.getContext().checkInterrupted();
File src = new File(IvyPatternHelper.substitute(srcArtifactPattern, artifact));
- if (src.exists()) {
- resolver.publish(artifact, src, overwrite);
- return true;
- } else {
- return false;
+
+ //notify triggers that an artifact is about to be published
+ eventManager.fireIvyEvent(
+ new StartArtifactPublishEvent(resolver, artifact, src, overwrite));
+ boolean successful = false; //set to true once the publish succeeds
+ try {
+ if (src.exists()) {
+ resolver.publish(artifact, src, overwrite);
+ successful = true;
+ }
+ return successful;
+ } finally {
+ //notify triggers that the publish is finished, successfully or not.
+ eventManager.fireIvyEvent(
+ new EndArtifactPublishEvent(resolver, artifact, src, overwrite, successful));
}
}
Modified: incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEngineTest.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEngineTest.java?rev=600041&r1=600040&r2=600041&view=diff
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEngineTest.java (original)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEngineTest.java Fri Nov 30 18:30:50 2007
@@ -50,7 +50,7 @@
public void testAtomicity() throws Exception {
IvySettings settings = new IvySettings();
- final PublishEngine engine = new PublishEngine(settings);
+ final PublishEngine engine = new PublishEngine(settings, new EventManager());
final int[] counter = new int[] {0};
final DefaultModuleDescriptor md = DefaultModuleDescriptor
Added: incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEventsTest.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEventsTest.java?rev=600041&view=auto
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEventsTest.java (added)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEventsTest.java Fri Nov 30 18:30:50 2007
@@ -0,0 +1,440 @@
+/*
+ * 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.publish;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.apache.ivy.Ivy;
+import org.apache.ivy.core.IvyContext;
+import org.apache.ivy.core.event.IvyEvent;
+import org.apache.ivy.core.event.publish.EndArtifactPublishEvent;
+import org.apache.ivy.core.event.publish.PublishEvent;
+import org.apache.ivy.core.event.publish.StartArtifactPublishEvent;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.MDArtifact;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
+import org.apache.ivy.plugins.resolver.MockResolver;
+import org.apache.ivy.plugins.trigger.AbstractTrigger;
+
+import junit.framework.TestCase;
+
+public class PublishEventsTest extends TestCase {
+
+ //maps ArtifactRevisionId to PublishTestCase instance.
+ private HashMap expectedPublications;
+ //expected values for the current artifact being published.
+ private PublishTestCase currentTestCase;
+ private boolean expectedOverwrite;
+
+ //number of times PrePublishTrigger has been invoked successfully
+ private int preTriggers;
+ //number of times PostPublishTrigger has been invoked successfully
+ private int postTriggers;
+ //number of times an artifact has been successfully published by the resolver
+ private int publications;
+
+ //dummy test data that is reused by all cases.
+ private File ivyFile;
+ private Artifact ivyArtifact;
+ private File dataFile;
+ private Artifact dataArtifact;
+
+ private ModuleDescriptor publishModule;
+ private Collection publishSources;
+ private PublishOptions publishOptions;
+
+ //if non-null, InstrumentedResolver will throw this exception during publish
+ private IOException publishError;
+
+ //the ivy instance under test
+ private Ivy ivy;
+ private PublishEngine publishEngine;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ //reset test case state.
+ resetCounters();
+
+ //this ivy settings should configure an InstrumentedResolver, PrePublishTrigger, and PostPublishTrigger
+ //(see inner classes below).
+ ivy = Ivy.newInstance();
+ ivy.configure(PublishEventsTest.class.getResource("ivysettings-publisheventstest.xml"));
+ ivy.pushContext();
+ publishEngine = ivy.getPublishEngine();
+
+ //setup dummy ivy and data files to test publishing. since we're testing the engine and not the resolver,
+ //we don't really care whether the file actually gets published. we just want to make sure
+ //that the engine calls the correct methods in the correct order, and fires required events.
+ String resourcePath = PublishEventsTest.class.getResource("ivy-1.0-dev.xml").getPath();
+ resourcePath = URLDecoder.decode(resourcePath, System.getProperty("file.encoding"));
+ ivyFile = new File(resourcePath);
+ assertTrue("path to ivy file found in test environment", ivyFile.exists());
+ //the contents of the data file don't matter.
+ dataFile = File.createTempFile("ivydata", ".jar");
+ dataFile.deleteOnExit();
+
+ publishModule = XmlModuleDescriptorParser.getInstance().parseDescriptor(ivy.getSettings(), ivyFile.toURL(), false);
+ //always use the same source data file, no pattern substitution is required.
+ publishSources = Collections.singleton(dataFile.getAbsolutePath());
+ //always use the same ivy file, no pattern substitution is required.
+ publishOptions = new PublishOptions();
+ publishOptions.setSrcIvyPattern(ivyFile.getAbsolutePath());
+
+ //set up our expectations for the test. these variables will
+ //be checked by the resolver and triggers during publication.
+ dataArtifact = publishModule.getAllArtifacts()[0];
+ assertEquals("sanity check", "foo", dataArtifact.getName());
+ ivyArtifact = MDArtifact.newIvyArtifact(publishModule);
+
+ expectedPublications = new HashMap();
+ expectedPublications.put(dataArtifact.getId(), new PublishTestCase(dataArtifact, dataFile, true));
+ expectedPublications.put(ivyArtifact.getId(), new PublishTestCase(ivyArtifact, ivyFile, true));
+ assertEquals("hashCode sanity check: two artifacts expected during publish", 2, expectedPublications.size());
+
+ //push the TestCase instance onto the context stack, so that our
+ //triggers and resolver instances can interact with it it.
+ IvyContext.getContext().push(PublishEventsTest.class.getName(), this);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ //reset test state.
+ resetCounters();
+
+ //test case is finished, pop the test context off the stack.
+ IvyContext.getContext().pop(PublishEventsTest.class.getName());
+
+ //cleanup ivy resources
+ if (ivy != null) {
+ ivy.popContext();
+ ivy = null;
+ }
+ publishEngine = null;
+ if (dataFile != null)
+ dataFile.delete();
+ dataFile = null;
+ ivyFile = null;
+ }
+
+ protected void resetCounters() {
+ preTriggers = 0;
+ postTriggers = 0;
+ publications = 0;
+
+ expectedPublications = null;
+ expectedOverwrite = false;
+ publishError = null;
+ currentTestCase = null;
+
+ ivyArtifact = null;
+ dataArtifact = null;
+ }
+
+ /**
+ * Test a simple artifact publish, without errors or overwrite settings.
+ */
+ public void testPublishNoOverwrite() throws IOException {
+ //no modifications to input required for this case -- call out to the resolver, and verify that
+ //all of our test counters have been incremented.
+ Collection missing = publishEngine.publish(publishModule.getModuleRevisionId(), publishSources, "default", publishOptions);
+ assertEquals("no missing artifacts", 0, missing.size());
+
+ //if all tests passed, all of our counter variables should have been updated.
+ assertEquals("pre-publish trigger fired and passed all tests", 2, preTriggers);
+ assertEquals("post-publish trigger fired and passed all tests", 2, postTriggers);
+ assertEquals("resolver received a publish() call, and passed all tests", 2, publications);
+ assertEquals("all expected artifacts have been published", 0, expectedPublications.size());
+ }
+
+ /**
+ * Test a simple artifact publish, with overwrite set to true.
+ */
+ public void testPublishWithOverwrite() throws IOException {
+ //we expect the overwrite settings to be passed through the event listeners and into the publisher.
+ this.expectedOverwrite = true;
+
+ //set overwrite to true. InstrumentedResolver will verify that the correct argument value was provided.
+ publishOptions.setOverwrite(true);
+ Collection missing = publishEngine.publish(publishModule.getModuleRevisionId(), publishSources, "default", publishOptions);
+ assertEquals("no missing artifacts", 0, missing.size());
+
+ //if all tests passed, all of our counter variables should have been updated.
+ assertEquals("pre-publish trigger fired and passed all tests", 2, preTriggers);
+ assertEquals("post-publish trigger fired and passed all tests", 2, postTriggers);
+ assertEquals("resolver received a publish() call, and passed all tests", 2, publications);
+ assertEquals("all expected artifacts have been published", 0, expectedPublications.size());
+ }
+
+ /**
+ * Test an attempted publish with an invalid data file path.
+ */
+ public void testPublishMissingFile() throws IOException {
+ //delete the datafile. the publish should fail, but all events should still be fired,
+ //and the ivy artifact should still publish successfully.
+ assertTrue("datafile has been destroyed", dataFile.delete());
+ PublishTestCase dataPublish = (PublishTestCase)expectedPublications.get(dataArtifact.getId());
+ dataPublish.expectedSuccess = false;
+ Collection missing = publishEngine.publish(publishModule.getModuleRevisionId(), publishSources, "default", publishOptions);
+ assertEquals("one missing artifact", 1, missing.size());
+ assertSameArtifact("missing artifact was returned", dataArtifact, (Artifact)missing.iterator().next());
+
+ //if all tests passed, all of our counter variables should have been updated.
+ assertEquals("pre-publish trigger fired and passed all tests", 2, preTriggers);
+ assertEquals("post-publish trigger fired and passed all tests", 2, postTriggers);
+ assertEquals("only the ivy file published successfully", 1, publications);
+ assertEquals("publish of all expected artifacts has been attempted", 0, expectedPublications.size());
+ }
+
+ /**
+ * Test an attempted publish in which the target resolver throws an IOException.
+ */
+ public void testPublishWithException() {
+ //set an error to be thrown during publication of the data file.
+ this.publishError = new IOException("boom!");
+ //we don't care which artifact is attempted; either will fail with an IOException.
+ for (Iterator it = expectedPublications.values().iterator(); it.hasNext(); )
+ ((PublishTestCase)it.next()).expectedSuccess = false;
+
+ try {
+ publishEngine.publish(publishModule.getModuleRevisionId(), publishSources, "default", publishOptions);
+ fail("if the resolver throws an exception, the engine should too");
+ } catch (IOException expected) {
+ assertSame("exception thrown by the resolver should be propagated by the engine",
+ this.publishError, expected);
+ }
+
+ //the publish engine gives up after the resolver throws an exception on the first artifact,
+ //so only one set of events should have been fired.
+ //note that the initial publish error shouldn't prevent the post-publish trigger from firing.
+ assertEquals("pre-publish trigger fired and passed all tests", 1, preTriggers);
+ assertEquals("post-publish trigger fired and passed all tests", 1, postTriggers);
+ assertEquals("resolver never published successfully", 0, publications);
+ assertEquals("publication aborted after first failure", 1, expectedPublications.size());
+ }
+
+ /**
+ * Assert that two Artifact instances refer to the same artifact and contain the same metadata.
+ */
+ public static void assertSameArtifact(String message, Artifact expected, Artifact actual) {
+ assertEquals(message + ": name", expected.getName(), actual.getName());
+ assertEquals(message + ": id", expected.getId(), actual.getId());
+ assertEquals(message + ": moduleRevisionId", expected.getModuleRevisionId(), actual.getModuleRevisionId());
+ assertTrue(message + ": configurations", Arrays.equals(expected.getConfigurations(), actual.getConfigurations()));
+ assertEquals(message + ": type", expected.getType(), actual.getType());
+ assertEquals(message + ": ext", expected.getExt(), actual.getExt());
+ assertEquals(message + ": publicationDate", expected.getPublicationDate(), actual.getPublicationDate());
+ assertEquals(message + ": attributes", expected.getAttributes(), actual.getAttributes());
+ assertEquals(message + ": url", expected.getUrl(), actual.getUrl());
+ }
+
+ public static class PublishTestCase {
+ public Artifact expectedArtifact;
+ public File expectedData;
+ public boolean expectedSuccess;
+
+ public boolean preTriggerFired;
+ public boolean published;
+ public boolean postTriggerFired;
+
+ public PublishTestCase(Artifact artifact, File data, boolean success) {
+ this.expectedArtifact = artifact;
+ this.expectedData = data;
+ this.expectedSuccess = success;
+ }
+ }
+
+ /**
+ * Base class for pre- and post-publish-artifact triggers. When the trigger receives an event,
+ * the contents of the publish event are examined to make sure they match the variable settings
+ * on the calling {@link PublishEventsTest#currentTestCase} instance.
+ */
+ public static class TestPublishTrigger extends AbstractTrigger {
+
+ public void progress(IvyEvent event) {
+ PublishEventsTest test = (PublishEventsTest)IvyContext.getContext().peek(PublishEventsTest.class.getName());
+ InstrumentedResolver resolver = (InstrumentedResolver)test.ivy.getSettings().getResolver("default");
+
+ assertNotNull("instrumented resolver configured", resolver);
+ assertNotNull("got a reference to the current unit test case", test);
+
+ //test the proper sequence of events by comparing the number of pre-events,
+ //post-events, and actual publications.
+ assertTrue("event is of correct base type",
+ event instanceof PublishEvent);
+
+ PublishEvent pubEvent = (PublishEvent)event;
+ Artifact expectedArtifact = test.currentTestCase.expectedArtifact;
+ File expectedData = test.currentTestCase.expectedData;
+
+ assertSameArtifact("event records correct artifact",
+ expectedArtifact, pubEvent.getArtifact());
+ try {
+ assertEquals("event records correct file",
+ expectedData.getCanonicalPath(), pubEvent.getData().getCanonicalPath());
+
+ assertEquals("event records correct overwrite setting", test.expectedOverwrite, pubEvent.isOverwrite());
+ assertSame("event presents correct resolver", resolver, pubEvent.getResolver());
+
+ String[] attributes = {
+ "organisation", "module", "revision", "artifact", "type", "ext", "resolver", "overwrite"
+ };
+ String[] values = {
+ "apache", "PublishEventsTest", "1.0-dev", expectedArtifact.getName(), expectedArtifact.getType(), expectedArtifact.getExt(), "default", String.valueOf(test.expectedOverwrite)
+ };
+
+ for (int i = 0; i < attributes.length; ++i)
+ assertEquals("event declares correct value for " + attributes[i],
+ values[i], event.getAttributes().get(attributes[i]));
+ //we test file separately, since it is hard to guaranteean exact path match, but we want
+ //to make sure that both paths point to the same canonical location on the filesystem
+ String filePath = event.getAttributes().get("file").toString();
+ assertEquals("event declares correct value for file",
+ expectedData.getCanonicalPath(), new File(filePath).getCanonicalPath());
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ }
+
+ /**
+ * Extends the tests done by {@link TestPublishTrigger} to check that pre-publish events are
+ * fired before DependencyResolver.publish() is called, and before post-publish events are fired.
+ */
+ public static class PrePublishTrigger extends TestPublishTrigger {
+
+ public void progress(IvyEvent event) {
+
+ PublishEventsTest test = (PublishEventsTest)IvyContext.getContext().peek(PublishEventsTest.class.getName());
+ assertTrue("event is of correct concrete type",
+ event instanceof StartArtifactPublishEvent);
+ StartArtifactPublishEvent startEvent = (StartArtifactPublishEvent)event;
+
+ //verify that the artifact being publish was in the expected set. set the 'currentTestCase'
+ //pointer so that the resolver and post-publish trigger can check against it.
+ Artifact artifact = startEvent.getArtifact();
+ assertNotNull("event defines artifact", artifact);
+
+ PublishTestCase currentTestCase = (PublishTestCase)test.expectedPublications.remove(artifact.getId());
+ assertNotNull("artifact " + artifact.getId() + " was expected for publication", currentTestCase);
+ assertFalse("current publication has not been visited yet", currentTestCase.preTriggerFired);
+ assertFalse("current publication has not been visited yet", currentTestCase.published);
+ assertFalse("current publication has not been visited yet", currentTestCase.postTriggerFired);
+ test.currentTestCase = currentTestCase;
+
+ //superclass tests common attributes of publish events
+ super.progress(event);
+
+ //increment the call counter in the test
+ currentTestCase.preTriggerFired = true;
+ ++test.preTriggers;
+ }
+
+ }
+
+ /**
+ * Extends the tests done by {@link TestPublishTrigger} to check that post-publish events are
+ * fired after DependencyResolver.publish() is called, and that the "status" attribute is
+ * set to the correct value.
+ */
+ public static class PostPublishTrigger extends TestPublishTrigger {
+
+ public void progress(IvyEvent event) {
+ //superclass tests common attributes of publish events
+ super.progress(event);
+
+ PublishEventsTest test = (PublishEventsTest)IvyContext.getContext().peek(PublishEventsTest.class.getName());
+
+ //test the proper sequence of events by comparing the current count of pre-events,
+ //post-events, and actual publications.
+ assertTrue("event is of correct concrete type",
+ event instanceof EndArtifactPublishEvent);
+ assertTrue("pre-publish event has been triggered", test.preTriggers > 0);
+
+ //test sequence of events
+ assertTrue("pre-trigger event has already been fired for this artifact",
+ test.currentTestCase.preTriggerFired);
+ assertEquals("publication has been done if possible",
+ test.currentTestCase.expectedSuccess, test.currentTestCase.published);
+ assertFalse("post-publish event has not yet been fired for this artifact",
+ test.currentTestCase.postTriggerFired);
+
+ //test the "status" attribute of the post- event.
+ EndArtifactPublishEvent endEvent = (EndArtifactPublishEvent)event;
+ assertEquals("status bit is set correctly",
+ test.currentTestCase.expectedSuccess, endEvent.isSuccessful());
+
+ String expectedStatus = test.currentTestCase.expectedSuccess ? "successful" : "failed";
+ assertEquals("status attribute is set to correct value",
+ expectedStatus, endEvent.getAttributes().get("status"));
+
+ //increment the call counter in the wrapper test
+ test.currentTestCase.postTriggerFired = true;
+ ++test.postTriggers;
+ }
+
+ }
+
+ /**
+ * When publish() is called, verifies that a pre-publish event has been fired, and also verifies that
+ * the method arguments have the correct value. Also simulates an IOException if the current
+ * test case demands it.
+ */
+ public static class InstrumentedResolver extends MockResolver {
+
+ public void publish(Artifact artifact, File src, boolean overwrite) throws IOException {
+
+ //verify that the data from the current test case has been handed down to us
+ PublishEventsTest test = (PublishEventsTest)IvyContext.getContext().peek(PublishEventsTest.class.getName());
+
+ //test sequence of events.
+ assertNotNull(test.currentTestCase);
+ assertTrue("preTrigger has already fired", test.currentTestCase.preTriggerFired);
+ assertFalse("postTrigger has not yet fired", test.currentTestCase.postTriggerFired);
+ assertFalse("publish has not been called", test.currentTestCase.published);
+
+ //test event data
+ assertSameArtifact("publisher has received correct artifact",
+ test.currentTestCase.expectedArtifact, artifact);
+ assertEquals("publisher has received correct datafile",
+ test.currentTestCase.expectedData.getCanonicalPath(), src.getCanonicalPath());
+ assertEquals("publisher has received correct overwrite setting",
+ test.expectedOverwrite, overwrite);
+ assertTrue("publisher only invoked when source file exists", test.currentTestCase.expectedData.exists());
+
+ //simulate a publisher error if the current test case demands it.
+ if (test.publishError != null)
+ throw test.publishError;
+
+ //all assertions pass. increment the publication count
+ test.currentTestCase.published = true;
+ ++test.publications;
+ }
+ }
+
+}
\ No newline at end of file
Propchange: incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/PublishEventsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivy-1.0-dev.xml
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivy-1.0-dev.xml?rev=600041&view=auto
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivy-1.0-dev.xml (added)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivy-1.0-dev.xml Fri Nov 30 18:30:50 2007
@@ -0,0 +1,25 @@
+<!--
+ 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.
+-->
+<!-- Dummy module used by PublishEventsTest.java -->
+<ivy-module version="1.0">
+ <info organisation="apache" module="PublishEventsTest" revision="1.0-dev"/>
+ <publications>
+ <artifact name="foo" type="jar"/>
+ </publications>
+</ivy-module>
Propchange: incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivy-1.0-dev.xml
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivysettings-publisheventstest.xml
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivysettings-publisheventstest.xml?rev=600041&view=auto
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivysettings-publisheventstest.xml (added)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivysettings-publisheventstest.xml Fri Nov 30 18:30:50 2007
@@ -0,0 +1,36 @@
+<!--
+ 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.
+-->
+<!--
+ This ivy configuration is used with org.apache.ivy.core.publish.PublishEventsTest, to unit test basic features
+ of the PublishEngine.
+-->
+<ivysettings>
+ <!-- we define a special resolver that interacts with PublishEventsTest -->
+ <typedef name="publish-events-test" classname="org.apache.ivy.core.publish.PublishEventsTest$InstrumentedResolver"/>
+ <!-- we define triggers to test the behavior of pre- and post-publish events -->
+ <typedef name="pre-publish-test" classname="org.apache.ivy.core.publish.PublishEventsTest$PrePublishTrigger"/>
+ <typedef name="post-publish-test" classname="org.apache.ivy.core.publish.PublishEventsTest$PostPublishTrigger"/>
+ <triggers>
+ <pre-publish-test event="pre-publish-artifact"/>
+ <post-publish-test event="post-publish-artifact"/>
+ </triggers>
+ <resolvers>
+ <publish-events-test name="default"/>
+ </resolvers>
+</ivysettings>
Propchange: incubator/ivy/core/trunk/test/java/org/apache/ivy/core/publish/ivysettings-publisheventstest.xml
------------------------------------------------------------------------------
svn:eol-style = native