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
+ * [EMAIL PROTECTED] #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 [EMAIL PROTECTED]
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
+ * [EMAIL PROTECTED] #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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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