diff --git a/maven3-eventspy-3.0/pom.xml b/maven3-eventspy-3.0/pom.xml index e30c8da..33571e6 100644 --- a/maven3-eventspy-3.0/pom.xml +++ b/maven3-eventspy-3.0/pom.xml @@ -27,18 +27,17 @@ THE SOFTWARE. 4.0.0 org.hudsonci.plugins - hudson-maven3 - 3.0.1-SNAPSHOT + maven3-plugin-parent + 3.0.7-SNAPSHOT maven3-eventspy-3.0 - Hudson :: Maven 3 :: Event Spy 3.0 + Hudson Maven3 Event Spy 3.0 org.eclipse.hudson hudson-utils - ${hudson.core.version} commons-lang @@ -66,7 +65,7 @@ THE SOFTWARE. org.apache.maven maven-embedder - ${mavenVersion} + 3.0.3 provided @@ -75,11 +74,77 @@ THE SOFTWARE. maven3-model test-jar - + + + org.eclipse.hudson + hudson-core + provided + jar + + + hudson-cli + org.eclipse.hudson + + + hudson-remoting + org.eclipse.hudson + + + + + org.eclipse.hudson + hudson-remoting + ${hudson.remoting.version} + provided + + + + org.eclipse.hudson + hudson-plugin-utils + provided + jar + + + org.eclipse.hudson + hudson-war + provided + war + + + org.eclipse.hudson + hudson-test-framework + provided + jar + + + org.eclipse.hudson + hudson-inject + provided + + + hudson-core + org.eclipse.hudson + + + + + org.eclipse.hudson + hudson-service + provided + + + hudson-plugin-utils + org.eclipse.hudson + + + + + org.eclipse.hudson hudson-test-utils - ${hudson.core.version} test diff --git a/maven3-eventspy-3.1/pom.xml b/maven3-eventspy-3.1/pom.xml new file mode 100644 index 0000000..f92169b --- /dev/null +++ b/maven3-eventspy-3.1/pom.xml @@ -0,0 +1,182 @@ + + + + + 4.0.0 + + org.hudsonci.plugins + maven3-plugin-parent + 3.0.7-SNAPSHOT + + + maven3-eventspy-3.1 + Hudson Maven3 Event Spy 3.1 + + + + org.eclipse.hudson + hudson-utils + + + commons-lang + commons-lang + + + + + + org.hudsonci.plugins + maven3-eventspy-common + + + + ch.qos.logback + logback-classic + + + + org.codehaus.plexus + plexus-component-annotations + provided + + + + org.apache.maven + maven-embedder + ${mavenVersion} + provided + + + + org.hudsonci.plugins + maven3-model + test-jar + + + + org.eclipse.hudson + hudson-core + provided + jar + + + hudson-cli + org.eclipse.hudson + + + hudson-remoting + org.eclipse.hudson + + + + + org.eclipse.hudson + hudson-remoting + ${hudson.remoting.version} + provided + + + + org.eclipse.hudson + hudson-plugin-utils + provided + jar + + + org.eclipse.hudson + hudson-war + provided + war + + + org.eclipse.hudson + hudson-test-framework + provided + jar + + + org.eclipse.hudson + hudson-inject + provided + + + hudson-core + org.eclipse.hudson + + + + + org.eclipse.hudson + hudson-service + provided + + + hudson-plugin-utils + org.eclipse.hudson + + + + + + + org.eclipse.hudson + hudson-test-utils + test + + + + + + + org.codehaus.plexus + plexus-component-metadata + + + + generate-metadata + generate-test-metadata + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + + maven3-eventspy-runtime.jar + + + + + + + + diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/DelegatingEventSpy.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/DelegatingEventSpy.java new file mode 100644 index 0000000..48d4b9c --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/DelegatingEventSpy.java @@ -0,0 +1,200 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import com.google.inject.Binder; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.name.Names; +import org.hudsonci.utils.common.TestAccessible; +import org.apache.maven.BuildAbort; +import org.apache.maven.eventspy.EventSpy; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.hudsonci.maven.eventspy.common.Constants; +import org.eclipse.sisu.space.SpaceModule; +import org.eclipse.sisu.wire.WireModule; +import org.eclipse.sisu.inject.MutableBeanLocator; +import org.eclipse.sisu.space.URLClassSpace; +import org.eclipse.sisu.BeanEntry; + +import java.net.URL; +import java.util.Iterator; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.hudsonci.maven.eventspy.common.Constants.DELEGATE_PROPERTY; + +/** + * Delegates to a {@link EventSpy} component configured via {@link Constants#DELEGATE_PROPERTY}. + * This is the main {@link EventSpy} which Maven will load and is configured via Plexus, delegate + * is loaded via JSR-330. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Component(role=EventSpy.class, hint="delegating") +public class DelegatingEventSpy + extends EventSpySupport + implements Module +{ + @Requirement + private MutableBeanLocator locator; + + private EventSpy delegate; + + /** + * For Plexus. + */ + @SuppressWarnings({"unused"}) + public DelegatingEventSpy() { + } + + @TestAccessible + public DelegatingEventSpy(final EventSpy delegate) { + this.delegate = checkNotNull(delegate); + } + + public EventSpy getDelegate() { + checkState(delegate != null); + return delegate; + } + + public void configure(final Binder binder) { + binder.bind(MutableBeanLocator.class).toInstance(locator); + } + + @Override + public void init(final Context context) throws Exception { + try { + log.debug("Initializing w/context: {}", context); + checkNotNull(context); + super.init(context); + + // Spit out some trace information + if (log.isTraceEnabled()) { + log.trace("Context keys: {}", context.getData().keySet()); + log.trace("Container: {}", getContainer()); + log.trace("Working dir: {}", getWorkingDirectory()); + + log.trace("Version properties:"); + for (Map.Entry entry : getVersionProperties().entrySet()) { + log.trace(" {}='{}'", entry.getKey(), entry.getValue()); + } + + log.trace("User properties:"); + for (Map.Entry entry : getUserProperties().entrySet()) { + log.trace(" {}='{}'", entry.getKey(), entry.getValue()); + } + + log.trace("System properties:"); + for (Map.Entry entry : getSystemProperties().entrySet()) { + log.trace(" {}='{}'", entry.getKey(), entry.getValue()); + } + } + + // Delegate is non-null in testing case + if (delegate == null) { + delegate = loadDelegate(); + log.debug("Delegate: {}", delegate); + } + + getDelegate().init(context); + } + catch (Throwable e) { + log.error("Init failed", e); + + // Abort on failure to init() + if (e instanceof BuildAbort) { + throw (BuildAbort)e; + } + throw new BuildAbort("Failed to initialize", e); + } + } + + // Our delegate impls are bound as @Typed(EventSpySupport) to stop Maven 3.1 finding and activating them directly as EventSpy's + + private EventSpy loadDelegate() { + checkState(locator != null); + + // Setup the Injector to load spy impls from + URL[] scanPath = { + getClass().getProtectionDomain().getCodeSource().getLocation(), + }; + URLClassSpace space = new URLClassSpace(getClass().getClassLoader(), scanPath); + Injector injector = Guice.createInjector(new WireModule(new SpaceModule(space), this)); + + // Log what spies we know about + if (log.isDebugEnabled()) { + log.debug("Known spies:"); + for (BeanEntry spy : locator.locate(Key.get(EventSpySupport.class))) { + log.debug(" {}", spy); + } + } + + // Load the delegate, default to RemotingEventSpy + String name = getProperty(DELEGATE_PROPERTY, RemotingEventSpy.class.getName()); + log.debug("Loading delegate named: {}", name); + Iterator> itr = locator.locate(Key.get(EventSpySupport.class, Names.named(name))).iterator(); + if (itr.hasNext()) { + return itr.next().getValue(); + } + throw new RuntimeException("No such delegate: "+name); + } + + @Override + public void close() throws Exception { + try { + log.debug("Closing"); + ensureOpened(); + getDelegate().close(); + } + catch (Throwable e) { + log.error("Close failed", e); + + // Abort on failure to close() + if (e instanceof BuildAbort) { + throw (BuildAbort)e; + } + throw new BuildAbort("Failed to close", e); + } + } + + @Override + public void onEvent(final Object event) throws Exception { + try { + ensureOpened(); + getDelegate().onEvent(event); + } + catch (Exception e) { + log.error("Failed to handle event", e); + // complain but continue + throw e; + } + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/EventSpyHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/EventSpyHandler.java new file mode 100644 index 0000000..f3ea78a --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/EventSpyHandler.java @@ -0,0 +1,70 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.hudsonci.maven.eventspy.common.Callback; +import org.hudsonci.maven.eventspy_31.recorder.BuildRecorder; + +import org.hudsonci.utils.event.EventHandlerSupport; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Support for {@link org.apache.maven.eventspy.EventSpy} event handlers. + * + * @author Jason Dillon + * @since 2.1.0 + */ +public abstract class EventSpyHandler + extends EventHandlerSupport +{ + public static class HandlerContext + { + private final Callback callback; + private final BuildRecorder buildRecorder; + + public HandlerContext(final Callback callback) { + this.callback = checkNotNull(callback); + // TODO: how to inject since this is likely to be eventspy version specific + buildRecorder = new BuildRecorder(callback); + } + + public Callback getCallback() { + return callback; + } + + public BuildRecorder getBuildRecorder() { + return buildRecorder; + } + } + + protected Callback getCallback() { + return getContext().getCallback(); + } + + protected BuildRecorder getBuildRecorder() { + return getContext().getBuildRecorder(); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/EventSpyProcessor.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/EventSpyProcessor.java new file mode 100644 index 0000000..0c09808 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/EventSpyProcessor.java @@ -0,0 +1,69 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.sonatype.gossip.support.DC; +import org.hudsonci.utils.event.EventProcessorSupport; +import org.apache.maven.BuildAbort; + +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * {@link org.apache.maven.eventspy.EventSpy} event processor. + * + * @author Jason Dillon + * @since 2.1.0 + */ +public class EventSpyProcessor + extends EventProcessorSupport +{ + public EventSpyProcessor(final List handlers, EventSpyHandler defaultHandler) { + super(handlers, defaultHandler); + } + + private final AtomicInteger counter = new AtomicInteger(0); + + @Override + public void process(final Object event) throws Exception { + DC.put(EventSpyProcessor.class, counter.getAndIncrement()); + + try { + super.process(event); + } + finally { + DC.remove(EventSpyProcessor.class); + } + } + + @Override + protected void onFailure(final Exception cause) throws Exception { + log.error("Processing failure; aborting Maven", cause); + + // FIXME: We should tell the Callback that we are aborting so it can more gracefully handle this, ATM it will look like an I/O failure when the process dies. + + throw new BuildAbort("Error occurred while processing events; aborting", cause); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/EventSpySupport.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/EventSpySupport.java new file mode 100644 index 0000000..81d22f1 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/EventSpySupport.java @@ -0,0 +1,122 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.apache.maven.eventspy.AbstractEventSpy; +import org.codehaus.plexus.DefaultPlexusContainer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.Properties; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Support for {@link org.apache.maven.eventspy.EventSpy} implementations. + * + * @author Jason Dillon + * @since 2.1.0 + */ +public class EventSpySupport + extends AbstractEventSpy +{ + // This is really more of a things for *-eventspy-common, but due to the use of Maven-specific + // ... interfaces its living here, may change if/when needed + + protected final Logger log = LoggerFactory.getLogger(getClass()); + + private Context context; + + protected boolean isOpen() { + return context != null; + } + + protected void ensureOpened() { + if (!isOpen()) { + throw new IllegalStateException(); + } + } + + protected Context getContext() { + ensureOpened(); + return context; + } + + protected DefaultPlexusContainer getContainer() { + return (DefaultPlexusContainer) getContext().getData().get("plexus"); + } + + protected File getWorkingDirectory() { + return new File((String)getContext().getData().get("workingDirectory")); + } + + protected Properties getSystemProperties() { + return (Properties)getContext().getData().get("systemProperties"); + } + + protected Properties getUserProperties() { + return (Properties)getContext().getData().get("userProperties"); + } + + protected Properties getVersionProperties() { + return (Properties)getContext().getData().get("versionProperties"); + } + + /** + * Get a configuration property value. + */ + protected String getProperty(final String name, final String defaultValue) { + checkNotNull(name); + + // For now we only look at system properties for configuration + String value = getSystemProperties().getProperty(name); + if (value == null) { + value = defaultValue; + } + + return value; + } + + /** + * Get a configuration property value. + */ + protected String getProperty(final String name) { + return getProperty(name, null); + } + + @Override + public void init(final Context context) throws Exception { + if (isOpen()) { + throw new IllegalStateException(); + } + this.context = checkNotNull(context); + } + + @Override + public void close() throws Exception { + this.context = null; + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/LifecycleDebugLoggerImpl.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/LifecycleDebugLoggerImpl.java new file mode 100644 index 0000000..fda135b --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/LifecycleDebugLoggerImpl.java @@ -0,0 +1,146 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.hudsonci.utils.common.TestAccessible; +import org.apache.maven.eventspy.internal.EventSpyDispatcher; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.lifecycle.MavenExecutionPlan; +import org.apache.maven.lifecycle.internal.LifecycleDebugLogger; +import org.apache.maven.lifecycle.internal.ProjectBuildList; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Bridges {@link LifecycleDebugLogger} hooks to {@link org.apache.maven.eventspy.EventSpy} events. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Component(role=LifecycleDebugLogger.class) +public class LifecycleDebugLoggerImpl + extends LifecycleDebugLogger +{ + @Requirement + private EventSpyDispatcher dispatcher; + + /** + * For Plexus. + */ + @SuppressWarnings({"unused"}) + public LifecycleDebugLoggerImpl() { + super(); + } + + /** + * For testing. + */ + @TestAccessible + public LifecycleDebugLoggerImpl(final org.codehaus.plexus.logging.Logger logger) { + super(logger); + } + + public class ReactorPlanEvent + { + public final ProjectBuildList projectBuilds; + + public ReactorPlanEvent(final ProjectBuildList projectBuilds) { + this.projectBuilds = checkNotNull(projectBuilds); + } + + public void delegate() { + LifecycleDebugLoggerImpl.super.debugReactorPlan(projectBuilds); + } + + @Override + public String toString() { + return "ReactorPlanEvent{" + + "projectBuilds=" + projectBuilds + + '}'; + } + } + + @Override + public void debugReactorPlan(final ProjectBuildList projectBuilds) { + dispatcher.onEvent(new ReactorPlanEvent(projectBuilds)); + } + + public class ProjectPlanEvent + { + public final MavenProject currentProject; + + public final MavenExecutionPlan executionPlan; + + public ProjectPlanEvent(final MavenProject currentProject, final MavenExecutionPlan executionPlan) { + this.currentProject = checkNotNull(currentProject); + this.executionPlan = checkNotNull(executionPlan); + } + + public void delegate() { + LifecycleDebugLoggerImpl.super.debugProjectPlan(currentProject, executionPlan); + } + + @Override + public String toString() { + return "ProjectPlanEvent{" + + "currentProject=" + currentProject + + ", executionPlan=" + executionPlan + + '}'; + } + } + + @Override + public void debugProjectPlan(final MavenProject currentProject, final MavenExecutionPlan executionPlan) { + dispatcher.onEvent(new ProjectPlanEvent(currentProject, executionPlan)); + } + + public class WeavePlanEvent + { + public final MavenSession session; + + public WeavePlanEvent(final MavenSession session) { + this.session = checkNotNull(session); + } + + public void delegate() { + LifecycleDebugLoggerImpl.super.logWeavePlan(session); + } + + @Override + public String toString() { + return "WeavePlanEvent{" + + "session=" + session + + '}'; + } + } + + @Override + public void logWeavePlan(final MavenSession session) { + dispatcher.onEvent(new WeavePlanEvent(session)); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/LoggerManagerImpl.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/LoggerManagerImpl.java new file mode 100644 index 0000000..13a9649 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/LoggerManagerImpl.java @@ -0,0 +1,268 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.apache.maven.eventspy.EventSpy; +import org.codehaus.plexus.logging.AbstractLogger; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.LoggerManager; +import org.hudsonci.maven.eventspy.common.Callback; + +import static com.google.common.base.Preconditions.checkArgument; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.codehaus.plexus.logging.Logger.LEVEL_DEBUG; +import static org.codehaus.plexus.logging.Logger.LEVEL_DISABLED; +import static org.codehaus.plexus.logging.Logger.LEVEL_ERROR; +import static org.codehaus.plexus.logging.Logger.LEVEL_FATAL; +import static org.codehaus.plexus.logging.Logger.LEVEL_INFO; +import static org.codehaus.plexus.logging.Logger.LEVEL_WARN; + +/** + * Bridges logging over {@link Callback}. + * + * @author Jason Dillon + * @since 2.1.0 + */ +public class LoggerManagerImpl + implements LoggerManager +{ + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerManagerImpl.class); + + private final EventSpy spy; + + private final LoggerManager delegate; + + private int threshold = LEVEL_DEBUG; + + public LoggerManagerImpl(final EventSpy spy, final LoggerManager delegate) { + this.spy = checkNotNull(spy); + this.delegate = checkNotNull(delegate); + } + + // + // TODO: Figure out if we need to invoke more delegate methods... to get the default logging working. + // + + public void setThreshold(final int threshold) { + this.threshold = threshold; + } + + /** + * Same as {@link #setThreshold}, we do not track logger adapters. + */ + public void setThresholds(final int threshold) { + setThreshold(threshold); + } + + public int getThreshold() { + return threshold; + } + + public int getThreshold(final String role) { + return getThreshold(); + } + + /** + * Not supported. + */ + public int getThreshold(final String role, final String roleHint) { + return getThreshold(); + } + + public Logger getLoggerForComponent(final String role) { + return getLoggerForComponent(role, null); + } + + public Logger getLoggerForComponent(final String role, final String roleHint) { + checkNotNull(role); + + Logger logger = new LoggerImpl(getThreshold(), toLoggerName(role, roleHint), + delegate.getLoggerForComponent(role, roleHint)); + + log.debug("Created logger: {}", logger); + + return logger; + } + + /** + * Not supported. + */ + public void returnComponentLogger(final String role, final String hint) { + if (log.isDebugEnabled()) { + log.debug("Ignoring logger return; name={}", toLoggerName(role,hint)); + } + } + + public void returnComponentLogger(final String role) { + returnComponentLogger(role, null); + } + + /** + * Not supported. + */ + public int getActiveLoggerCount() { + return -1; + } + + private String toLoggerName(final String role, final String roleHint) { + if (roleHint == null) { + return role; + } + else { + return String.format("%s#%s", role, roleHint); + } + } + + /** + * Container for log event details. + */ + public static class LogEvent + { + private final Logger logger; + + private final int level; + + private final String message; + + private final Throwable cause; + + public LogEvent(final Logger logger, final int level, final String message, final Throwable cause) { + this.logger = checkNotNull(logger); + checkArgument(level >= LEVEL_DEBUG && level <= LEVEL_DISABLED); + this.level = level; + this.message = checkNotNull(message); + // cause might be null + this.cause = cause; + } + + public Logger getLogger() { + return logger; + } + + public int getLevel() { + return level; + } + + public String getMessage() { + return message; + } + + public Throwable getCause() { + return cause; + } + + public void delegate() { + switch (level) { + case LEVEL_DEBUG: + logger.debug(message, cause); + break; + case LEVEL_INFO: + logger.info(message, cause); + break; + case LEVEL_WARN: + logger.warn(message, cause); + break; + case LEVEL_ERROR: + logger.error(message, cause); + break; + case LEVEL_FATAL: + logger.fatalError(message, cause); + break; + default: + throw new Error(); + } + } + + @Override + public String toString() { + return "LogEvent{" + + logger.getName() + + ": level=" + level + + ", message='" + message + '\'' + + ", cause=" + cause + + '}'; + } + } + + /** + * Logger which turns method calls into {@link LogEvent} instances for processing. + */ + private class LoggerImpl + extends AbstractLogger + { + private Logger delegate; + + public LoggerImpl(final int threshold, final String name, final Logger delegate) { + super(threshold, name); + this.delegate = checkNotNull(delegate); + } + + private void emitLog(final int level, final String message, final Throwable cause) { + if (threshold <= level) { + LogEvent event = new LogEvent(delegate, level, message, cause); + + // FIXME: Figure out how to pipe to handler. + // FIXME: Log events can come in before we are fully opened, as well as after we are closed + // FIXME: May also avoid threshold check here and always pass on and only delegate if in range? + // FIXME: If we are going to leave the output as-is then probably always want to delegate here? + + log.debug("{}", event); + } + } + + public void debug(final String message, final Throwable cause) { + emitLog(LEVEL_DEBUG, message, cause); + } + + public void info(final String message, final Throwable cause) { + emitLog(LEVEL_INFO, message, cause); + } + + public void warn(final String message, final Throwable cause) { + emitLog(LEVEL_WARN, message, cause); + } + + public void error(final String message, final Throwable cause) { + emitLog(LEVEL_ERROR, message, cause); + } + + public void fatalError(final String message, final Throwable cause) { + emitLog(LEVEL_FATAL, message, cause); + } + + public Logger getChildLogger(final String name) { + return new LoggerImpl(getThreshold(), String.format("%s.%s", getName(), name), delegate.getChildLogger(name)); + } + + @Override + public String toString() { + return "LoggerImpl{" + + "name='" + getName() + '\'' + + ", threshold=" + threshold + + '}'; + } + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/LoggingEventSpy.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/LoggingEventSpy.java new file mode 100644 index 0000000..082b3a2 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/LoggingEventSpy.java @@ -0,0 +1,57 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import javax.enterprise.inject.Typed; +import javax.inject.Named; + +/** + * A simple {@link org.apache.maven.eventspy.EventSpy} which simply logs method calls. + * + * @author Jason Dillon + * @since 2.1.0 + * + * Limit binding with @Typed to make sure this is only seen by our delegate spy. + */ +@Named +@Typed(EventSpySupport.class) +public class LoggingEventSpy + extends EventSpySupport +{ + @Override + public void init(final Context context) throws Exception { + log.debug("init: {}", context); + } + + @Override + public void close() throws Exception { + log.debug("close"); + } + + @Override + public void onEvent(final Object event) throws Exception { + log.debug("event: {}", event); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/MavenArtifactConverter.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/MavenArtifactConverter.java new file mode 100644 index 0000000..fe337fc --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/MavenArtifactConverter.java @@ -0,0 +1,67 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.hudsonci.maven.model.MavenCoordinatesDTO; +import org.hudsonci.maven.model.state.ArtifactDTO; + +import org.eclipse.aether.artifact.Artifact; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Convert Maven based artifacts to our artifact model. + * + * @author Jamie Whitehouse + * @since 2.1.0 + */ +public class MavenArtifactConverter +{ + private MavenArtifactConverter() + { + // non-instantiable + } + + public static ArtifactDTO convertAetherArtifact(final Artifact artifact) { + checkNotNull(artifact); + + MavenCoordinatesDTO coordinates = new MavenCoordinatesDTO() + .withGroupId( artifact.getGroupId() ) + .withArtifactId( artifact.getArtifactId() ) + .withType( artifact.getExtension() ) + .withVersion( artifact.getBaseVersion() ) + .withExpandedMetaVersion( artifact.getVersion() ) + .withClassifier( artifact.getClassifier() ) + .normalize(); + + String type = artifact.getProperty( "type", "undefined" ); + + ArtifactDTO artifactDto = new ArtifactDTO() + .withCoordinates( coordinates ) + .withType( type ); + + return artifactDto; + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/MavenProjectConverter.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/MavenProjectConverter.java new file mode 100644 index 0000000..fd0b287 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/MavenProjectConverter.java @@ -0,0 +1,202 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.hudsonci.maven.model.MavenCoordinatesDTO; +import org.hudsonci.maven.model.ThrowableDTOHelper; +import org.hudsonci.maven.model.state.BuildResultDTO; +import org.hudsonci.maven.model.state.BuildSummaryDTO; +import org.hudsonci.maven.model.state.MavenProjectDTO; +import org.hudsonci.maven.model.state.ProfileDTO; + +import org.apache.maven.execution.BuildFailure; +import org.apache.maven.execution.BuildSuccess; +import org.apache.maven.execution.BuildSummary; +import org.apache.maven.execution.MavenExecutionResult; +import org.apache.maven.project.MavenProject; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Converts {@link MavenProject}s and their {@link BuildSummary}s to corresponding DTOs. + * + * @author Jamie Whitehouse + * @since 2.1.0 + */ +public class MavenProjectConverter +{ + private MavenProjectConverter() + { + // non-instantiable + } + + public static ArrayList extractFrom( final MavenExecutionResult event ) + { + ArrayList participatingProjects = new ArrayList(); + + List projects = event.getTopologicallySortedProjects(); + + for ( MavenProject mavenProject : projects ) + { + MavenProjectDTO projectDTO = convertMavenProject( mavenProject ); + updateWithBuildSummary( projectDTO, event.getBuildSummary( mavenProject ) ); + participatingProjects.add( projectDTO ); + } + return participatingProjects; + } + + public static MavenProjectDTO convertMavenProject( final MavenProject mavenProject ) + { + checkNotNull(mavenProject); + + MavenProjectDTO projectDTO = new MavenProjectDTO() + .withName( mavenProject.getName() ) + .withCoordinates( asCoordinates( mavenProject ) ) + .withProfiles( convertProfiles( ProfileCollector.collect( mavenProject ) ) ); + + return projectDTO; + } + + public static MavenCoordinatesDTO asCoordinates( final MavenProject mavenProject ) + { + checkNotNull(mavenProject); + + // Assume groupId, artifactId and version are never null. + return new MavenCoordinatesDTO() + .withGroupId( mavenProject.getGroupId() ) + .withArtifactId( mavenProject.getArtifactId() ) + .withType( nullSafeString( mavenProject.getPackaging() ) ) + .withVersion( mavenProject.getVersion() ) + .normalize(); + } + + static private String nullSafeString( String original ) + { + return ( original == null || original.length() == 0 ) ? "" : original; + } + + /** + * Add the converted build summary to the project. + * + * Assumes that the project attached to the BuildSummary matches the projectDTO. + * If the summary is null the result will be {@link BuildResultDTO#SKIPPED}. + * This will replace any existing summary associated with the project. + */ + public static void updateWithBuildSummary( final MavenProjectDTO projectDTO, final BuildSummary buildSummary ) + { + checkNotNull(projectDTO); + // BuildSummary can be null. + + projectDTO.setBuildSummary( convertBuildSummary( buildSummary ) ); + } + + /** + * This will replace any existing summary associated with the project. + */ + public static void updateWithBuildResult( final MavenProjectDTO projectDTO, final BuildResultDTO resultDTO ) + { + checkNotNull(projectDTO); + checkNotNull(resultDTO); + + projectDTO.setBuildSummary( new BuildSummaryDTO().withResult( resultDTO ) ); + } + + /** + * If the summary is null the result will be {@link BuildResultDTO#SKIPPED}. + */ + public static BuildSummaryDTO convertBuildSummary( final BuildSummary buildSummary ) + { + // BuildSummary can be null. + + BuildSummaryDTO buildSummaryDTO = new BuildSummaryDTO().withResult( convertToBuildResult( buildSummary ) ); + + if ( buildSummary != null ) + { + buildSummaryDTO.setDuration( buildSummary.getTime() ); + + if ( buildSummary instanceof BuildFailure ) + { + Throwable cause = ( (BuildFailure) buildSummary ).getCause(); + if ( cause != null ) + { + buildSummaryDTO.setFailureCause( ThrowableDTOHelper.convert(cause) ); + } + } + } + + return buildSummaryDTO; + } + + /** + * If the summary is null the result will be {@link BuildResultDTO#SKIPPED}. + * If a translation can not be matched the result will be {@link BuildResultDTO#UNKNOWN}. + */ + public static BuildResultDTO convertToBuildResult( final BuildSummary buildSummary ) + { + // BuildSummary can be null. + + final BuildResultDTO result; + + if ( buildSummary == null ) + { + result = BuildResultDTO.SKIPPED; + } + else if ( buildSummary instanceof BuildSuccess ) + { + result = BuildResultDTO.SUCCESS; + } + else if ( buildSummary instanceof BuildFailure ) + { + result = BuildResultDTO.FAILURE; + } + else + { + result = BuildResultDTO.UNKNOWN; + } + + return result; + } + + public static Collection convertProfiles( final Collection profiles ) + { + checkNotNull(profiles); + + Collection profilesDTO = new ArrayList(); + + for ( ResolvedProfile resolvedProfile : profiles ) + { + profilesDTO.add( new ProfileDTO() + .withId( resolvedProfile.getId() ) + .withSource( resolvedProfile.getSource() ) + .withActive( resolvedProfile.isActive() ) ); + } + return profilesDTO; + + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/ProfileCollector.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/ProfileCollector.java new file mode 100644 index 0000000..1edb03a --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/ProfileCollector.java @@ -0,0 +1,157 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.apache.maven.model.Profile; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuildingRequest; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Extracts {@link Profile}s from a {@link MavenProject} and converts them to {@link ResolvedProfile}s. + * + * Currently extracts pom and external profiles, but not those from the super pom. + * + * Benjamin's comments regarding the usefulness of super pom profiles: + * There is currently only one profile in the super POM (release-profile) which + * is scheduled for removal in future versions as users should rather set up + * their own release profile according their tastes. Likewise, I don't see us + * adding any other profiles to the super POM. + * + * Note: the super pom has an empty string for the key and is always present + * but may not have any profiles. It will only be added if there are profiles. + * TODO: may want to make this a special string similar to 'external', 'super-pom' or the GAV? + * + * @author Jamie Whitehouse + * @since 2.1.0 + */ +public class ProfileCollector +{ + private final MavenProject initiatingProject; + + private final Collection activeProfiles; + + private final Collection container; + + /** + * Non-instantiable, use {@link #collect(MavenProject)}. + */ + private ProfileCollector( MavenProject project ) + { + this.initiatingProject = project; + this.activeProfiles = getActiveProfileIds( project.getInjectedProfileIds() ); + this.container = new ArrayList(); + } + + /** + * Collects the {@link ResolvedProfile}s from the {@link MavenProject} up through + * all parent hierarchies and any external (settings.xml) profiles. + * + * @param project the starting project + * @return The profiles within this projects hierarchy, never {@code null}. + * + * @see MavenProject#getInjectedProfileIds() for similar information. + */ + public static Collection collect( final MavenProject project ) + { + checkNotNull(project); + return new ProfileCollector( project ).execute(); + } + + private Collection execute() + { + collectExternal(); + collectFromProjectUp( initiatingProject ); + // TODO: super pom, source identified as empty string. + + return container; + } + + /** + * ProjectBuildingRequest().getProfiles() contains the 'external' profiles present for this project. + * TODO: Consider passing in the 'external' list rather than using ProjectBuildingRequest. + * This could come from ExecutionEvent.getSession().getRequest which is a MavenExecutionRequest, + */ + private void collectExternal() + { + ProjectBuildingRequest projectBuildingRequest = initiatingProject.getProjectBuildingRequest(); + if ( null != projectBuildingRequest ) + { + collectResolvedProfiles( ResolvedProfile.EXTERNAL, projectBuildingRequest.getProfiles() ); + } + } + + private void collectFromProjectUp( final MavenProject project ) + { + // At the top of the hierarchy, stop recursion. + if ( null == project ) + { + return; + } + + collectResolvedProfiles( project, project.getModel().getProfiles() ); + // Walk up hierarchy. + collectFromProjectUp( project.getParent() ); + } + + private void collectResolvedProfiles( final MavenProject source, final Collection profiles ) + { + for ( Profile profile : profiles ) + { + container.add( new ResolvedProfile( source, profile, isActive( profile ) ) ); + } + } + + /** + * If Maven thinks the ResolvedProfile is active, make it so. + * + * Need to perform operation outside of ResolvedProfile because external profiles + * will not have a MavenProject to get the InjectedProfileIds from. + * + * @param profile the ResolvedProfiles backing Profile + * @return true if the profile is active, false otherwise + */ + private boolean isActive( final Profile profile ) + { + return activeProfiles.contains( profile.getId() ); + } + + private Collection getActiveProfileIds( final Map> activeProfilesMap ) + { + Collection allActiveProfiles = new ArrayList(); + Collection> values = activeProfilesMap.values(); + for ( List list : values ) + { + allActiveProfiles.addAll( list ); + } + return allActiveProfiles; + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/RecordingEventSpy.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/RecordingEventSpy.java new file mode 100644 index 0000000..5f27f0f --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/RecordingEventSpy.java @@ -0,0 +1,60 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import javax.enterprise.inject.Typed; +import javax.inject.Named; + +/** + * Records invocations on {@link Callback}. + * + * @author Jason Dillon + * @since 2.1.0 + * + * Limit binding with @Typed to make sure this is only seen by our delegate spy. + */ +@Named +@Typed(EventSpySupport.class) +public class RecordingEventSpy + extends EventSpySupport +{ + // TODO: Setup the basic event processing bits similar to RemotingEventSpy and install a dummy callback proxy + recording handler + // TODO: Need some more request/response methods on Callback before this can be fully validated to work + + @Override + public void init(final Context context) throws Exception { + log.debug("init: {}", context); + } + + @Override + public void close() throws Exception { + log.debug("close"); + } + + @Override + public void onEvent(final Object event) throws Exception { + log.debug("event: {}", event); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/RemotingEventSpy.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/RemotingEventSpy.java new file mode 100644 index 0000000..4de8601 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/RemotingEventSpy.java @@ -0,0 +1,183 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.hudsonci.maven.model.PropertiesDTOHelper; +import org.hudsonci.maven.model.state.RuntimeEnvironmentDTO; +import org.apache.maven.BuildAbort; +import org.hudsonci.maven.eventspy.common.Callback; +import org.hudsonci.maven.eventspy.common.CallbackManager; +import org.hudsonci.maven.eventspy.common.RemotingClient; + +import javax.enterprise.inject.Typed; +import javax.inject.Inject; +import javax.inject.Named; +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.hudsonci.maven.eventspy.common.Constants.CALLBACK_WAIT_TIMEOUT; +import static org.hudsonci.maven.eventspy.common.Constants.CALLBACK_WAIT_TIMEOUT_UNIT; +import static org.hudsonci.maven.eventspy.common.Constants.PORT_PROPERTY; + +/** + * Hudson {@link org.apache.maven.eventspy.EventSpy} for Maven 3.0 integration. + * + * @author Jason Dillon + * @since 2.1.0 + * + * Limit binding with @Typed to make sure this is only seen by our delegate spy. + */ +@Named +@Typed(EventSpySupport.class) +public class RemotingEventSpy + extends EventSpySupport +{ + private final EventSpyProcessor processor; + + private RemotingClient client; + + private Callback callback; + + @Inject + public RemotingEventSpy(final List handlers) { + checkNotNull( handlers ); + this.processor = new EventSpyProcessor(handlers, null); + } + + /** + * Returns the port number to be used when establishing communication. + * + * @throws Error If the port number has not been configured. + */ + private int getPort() { + String tmp = getProperty(PORT_PROPERTY); + if (tmp == null) { + throw new Error("Missing port number"); + } + return Integer.parseInt(tmp); + } + + /** + * Opens remoting channel. + * + * @throws Error Failed to open channel. + */ + private void openChannel() throws Exception { + int port = getPort(); + client = new RemotingClient(port); + client.open(); + } + + /** + * Closes the remoting channel. + */ + private void closeChannel() throws Exception { + client.join(); + client.close(); + } + + /** + * Invoked by Maven startup process. + * + * Initiates the remoting connection back to controlling MavenBuilder component. + * Waits for callback reference, blocking until received (or times out). + * Initializes the event processor with context. + * + * @throws Error Initialization failed. + */ + @Override + public void init(final Context context) throws Exception { + checkNotNull( context ); + + log.debug("Initializing"); + + super.init(context); + + openChannel(); + + // Wait for the callback + callback = CallbackManager.get(CALLBACK_WAIT_TIMEOUT, CALLBACK_WAIT_TIMEOUT_UNIT); + + // For now we are going to use the standard logging to STDOUT that Maven does + // DefaultPlexusContainer container = getContainer(); + // container.setLoggerManager(new LoggerManagerImpl(this, container.getLoggerManager())); + + // Initialize the processor + processor.init(new EventSpyHandler.HandlerContext(callback)); + + // Expose Maven's environment (props, version, envvars, etc) + RuntimeEnvironmentDTO env = new RuntimeEnvironmentDTO() + .withVersionProperties(PropertiesDTOHelper.convert(getVersionProperties())) + .withUserProperties(PropertiesDTOHelper.convert(getUserProperties())) + .withSystemProperties(PropertiesDTOHelper.convert(getSystemProperties())) + .withSystemEnvironment(PropertiesDTOHelper.convert(System.getenv())) + .withWorkingDirectory(getWorkingDirectory().getCanonicalPath()); + callback.setRuntimeEnvironment(env); + + // Should be all ready now to handle event stream + log.debug("Ready"); + } + + /** + * Performs event processing. + * + * Handles throwing {@link BuildAbort}. + */ + @Override + public void onEvent(final Object event) throws Exception { + checkNotNull( event ); + + ensureOpened(); + + // FIXME: This is way too chatty +// // First check if we are aborted +// if (callback.isAborted()) { +// // TODO: May want to see if this can be pushed, instead of pulled +// log.debug("Aborting build"); +// throw new BuildAbort("Aborted"); +// } + + // Delegate handling to processor + processor.process(event); + } + + @Override + public void close() throws Exception { + log.debug("Closing"); + + // Signal that we are finished + try { + callback.close(); + + // Shutdown the connection + closeChannel(); + } + finally { + super.close(); + } + + log.debug("Closed"); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/ResolvedProfile.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/ResolvedProfile.java new file mode 100644 index 0000000..c12a455 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/ResolvedProfile.java @@ -0,0 +1,99 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.apache.maven.model.Profile; +import org.apache.maven.model.building.ModelBuildingResult; +import org.apache.maven.project.MavenProject; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Source identifier has the form {@code ::} to be consistent + * with {@link MavenProject#getInjectedProfileIds()}. + * + * {@link ModelBuildingResult#getModelIds()} is the backing format for MavenProjects. + * + * @author Jamie Whitehouse + * @since 2.1.0 + */ +public class ResolvedProfile +{ + public static final MavenProject EXTERNAL = null; + + private final MavenProject declaringProject; + + private final Profile profile; + + private final boolean isActive; + + /** + * If the Profiles are from an external source use {@link ResolvedProfile#EXTERNAL} as the declaringProject. + * + * @param source the project that originated the profile, or {@link ResolvedProfile#EXTERNAL} + * @param profile + * @param isActive + */ + public ResolvedProfile( MavenProject source, Profile profile, boolean isActive ) + { + // MavenProject can be null for the special case of external profiles. + checkNotNull( profile ); + + // TODO: Consider extracting the sourceId and profileId at time of construction + // to mitigate mutability and extraneous object references. + this.declaringProject = source; + this.profile = profile; + this.isActive = isActive; + } + + public String getId() + { + return profile.getId(); + } + + public String getSource() + { + String sourceId; + // Using null as a special case for external/settings.xml based profiles. + if ( null == declaringProject ) + { + sourceId = "external"; + } + else + { + // NOTE MavenProject.getId is in a different format than MavenProject.getInjectedProfileIds + sourceId = + String.format( "%s:%s:%s", declaringProject.getGroupId(), declaringProject.getArtifactId(), + declaringProject.getVersion() ); + } + + return sourceId; + } + + public boolean isActive() + { + return isActive; + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/TerminateJvmEventSpy.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/TerminateJvmEventSpy.java new file mode 100644 index 0000000..d2b5f7f --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/TerminateJvmEventSpy.java @@ -0,0 +1,48 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import javax.enterprise.inject.Typed; +import javax.inject.Named; + +/** + * Spy which simply terminates the JVM. + * + * @author Jason Dillon + * @since 2.1.0 + * + * Limit binding with @Typed to make sure this is only seen by our delegate spy. + */ +@Named +@Typed(EventSpySupport.class) +public class TerminateJvmEventSpy + extends EventSpySupport +{ + @Override + public void init(final Context context) throws Exception { + log.error("Terminating JVM"); + Runtime.getRuntime().exit(99); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/DependencyResolutionRequestHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/DependencyResolutionRequestHandler.java new file mode 100644 index 0000000..3970b8b --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/DependencyResolutionRequestHandler.java @@ -0,0 +1,47 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.apache.maven.project.DependencyResolutionRequest; +import org.hudsonci.maven.eventspy_31.EventSpyHandler; + +import javax.inject.Named; + +/** + * Handles {@link DependencyResolutionRequest}. + * + * @author Jamie Whitehouse + * @since 2.1.0 + */ +@Named +public class DependencyResolutionRequestHandler + extends EventSpyHandler +{ + public void handle(DependencyResolutionRequest event) throws Exception { + log.debug("DependencyResolution request: {}", event); + + getBuildRecorder().recordDependencyResolutionStarted(event.getMavenProject()); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/DependencyResolutionResultHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/DependencyResolutionResultHandler.java new file mode 100644 index 0000000..945ec2b --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/DependencyResolutionResultHandler.java @@ -0,0 +1,47 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.apache.maven.project.DependencyResolutionResult; +import org.hudsonci.maven.eventspy_31.EventSpyHandler; + +import javax.inject.Named; + +/** + * Handles {@link DependencyResolutionResult}. + * + * @author Jamie Whitehouse + * @since 2.1.0 + */ +@Named +public class DependencyResolutionResultHandler + extends EventSpyHandler +{ + public void handle(DependencyResolutionResult event) throws Exception { + log.debug("DependencyResolution result: {}", event); + + getBuildRecorder().recordDependencyResolutionFinished(event.getResolvedDependencies()); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ExecutionEventHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ExecutionEventHandler.java new file mode 100644 index 0000000..12d336a --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ExecutionEventHandler.java @@ -0,0 +1,164 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.hudsonci.maven.model.MavenCoordinatesDTO; +import org.hudsonci.maven.model.state.ArtifactDTO; +import org.hudsonci.maven.model.state.MavenProjectDTO; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.BuildSummary; +import org.apache.maven.execution.ExecutionEvent; +import org.apache.maven.execution.ExecutionEvent.Type; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.project.MavenProject; +import org.hudsonci.maven.eventspy_31.EventSpyHandler; + +import javax.inject.Named; + +import java.util.List; +import java.util.Set; + +import static org.apache.maven.execution.ExecutionEvent.Type.ProjectFailed; +import static org.apache.maven.execution.ExecutionEvent.Type.ProjectSkipped; +import static org.apache.maven.execution.ExecutionEvent.Type.ProjectStarted; +import static org.apache.maven.execution.ExecutionEvent.Type.ProjectSucceeded; +import static org.apache.maven.execution.ExecutionEvent.Type.SessionStarted; + +/** + * Handles {@link ExecutionEvent} events. + * + * @author Jason Dillon + * @author Jamie Whitehouse + * @since 2.1.0 + */ +@Named +public class ExecutionEventHandler + extends EventSpyHandler +{ + public void handle( final ExecutionEvent event ) throws Exception + { + Type type = event.getType(); + log.debug( "Execution event type: {}", type ); + + recordSessionStarted( event ); + recordProjectStarted( event ); + recordMojoStarted( event ); + recordProjectFinished( event ); + // TODO: could probably handle SessionEnded instead of MavenExecutionResult + // in MavenExecutionResultHandler + } + + private void recordSessionStarted( final ExecutionEvent event ) + { + if ( SessionStarted.equals( event.getType() ) ) + { + List projects = event.getSession().getProjects(); + + log.debug( "Recording MavenProjects" ); + getBuildRecorder().recordSessionStarted(projects); + + ProfileLogger.log( event ); // TODO: is this needed anymore? + } + } + + private void recordProjectStarted( final ExecutionEvent event ) + { + if ( ProjectStarted.equals( event.getType() ) ) + { + MavenProject project = event.getProject(); + + log.debug( "Updating MavenProject" ); + getBuildRecorder().recordProjectStarted(project); + + ProjectLogger.log( project, "project started" ); + } + } + + private void recordProjectFinished( final ExecutionEvent event ) + { + Type type = event.getType(); + if ( ProjectSucceeded.equals( type ) || ProjectFailed.equals( type ) || ProjectSkipped.equals( type ) ) + { + MavenProject project = event.getProject(); + BuildSummary buildSummary = event.getSession().getResult().getBuildSummary( project ); + + log.debug( "Updating MavenProject" ); + getBuildRecorder().recordProjectFinished(project, buildSummary); + + // Record artifact usage at end of project build since they are + // populated in each phase, not at the beginning. + // NOTE: Benjamin has indicated that this is very closely bound to + // the plugin lifecycle and exposes only those artifacts, that a + // plugin has asked for now. + // Hence why there's no info at project finished. + ProjectLogger.log( project, "project finished" ); + } + } + + private void recordMojoStarted( final ExecutionEvent event ) + { + if( ExecutionEvent.Type.MojoStarted.equals(event.getType()) ) + { + MojoExecution mojoExecution = event.getMojoExecution(); + ProjectLogger.log(event.getProject(), "mojo started - " + mojoExecution.getLifecyclePhase() + " " + mojoExecution.getArtifactId() + " " + mojoExecution.getExecutionId() ); + + // There are none. + //log.debug("Mojo Plugin deps: {}", mojoExecution.getPlugin().getDependencies()); + } + } + + // TODO: Use this information to verify that repo events are being + // properly correlated to the current executing project. + // This is not an exhaustive list, but they all should be matched as + // a minimal test. + // Or use the info from ProjectLogger. + @SuppressWarnings( "unused" ) + private void recordDirectArtifacts( MavenProject project, MavenProjectDTO projectDTO ) + { + Set artifacts = project.getDependencyArtifacts(); + // TODO: may want to record these separately as plugin use. + // Note: + // project.getPluginArtifacts() makes the 'type/extension' maven-plugin which doesn't match anything Aether has resolved. + // see underlying org.apache.maven.artifact.factory.DefaultArtifactFactory.createPluginArtifact() + // With m3 use Aether Artifact.getProperty( "type" ); see it's JavaDoc + //artifacts.addAll( project.getPluginArtifacts() ); + + for( Artifact artifact : artifacts ) + { + ArtifactDTO artifactDTO = new ArtifactDTO().withCoordinates( new MavenCoordinatesDTO() + .withGroupId( artifact.getGroupId() ) + .withArtifactId( artifact.getArtifactId() ) + .withType( artifact.getType() ) + .withVersion( artifact.getVersion() ) + .withClassifier( artifact.getClassifier() ) + .normalize() ); + + artifactDTO.getDependentProjects().add( projectDTO.getId() ); + // TODO: Maybe do in batch since it's traffic back to the master. + //getCallback().updateArtifact( artifactDTO ); + } + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/LogEventHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/LogEventHandler.java new file mode 100644 index 0000000..f938ae0 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/LogEventHandler.java @@ -0,0 +1,45 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import javax.inject.Named; + +import org.hudsonci.maven.eventspy_31.EventSpyHandler; +import org.hudsonci.maven.eventspy_31.LoggerManagerImpl.LogEvent; + +/** + * Handles {@link LogEvent} events. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Named +public class LogEventHandler + extends EventSpyHandler +{ + public void handle(final LogEvent event) throws Exception { + log.debug("Log event: {}", event); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/MavenExecutionRequestHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/MavenExecutionRequestHandler.java new file mode 100644 index 0000000..201ffdd --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/MavenExecutionRequestHandler.java @@ -0,0 +1,103 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + + +import org.apache.maven.cli.transfer.BatchModeMavenTransferListener; +import org.apache.maven.cli.transfer.QuietMavenTransferListener; +import org.apache.maven.execution.MavenExecutionRequest; +import org.hudsonci.maven.eventspy.common.DocumentReference; +import org.hudsonci.maven.eventspy_31.EventSpyHandler; +import org.eclipse.aether.transfer.TransferListener; + +import javax.inject.Named; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; + +import static org.apache.maven.cli.MavenCli.DEFAULT_USER_TOOLCHAINS_FILE; + +/** + * Handles {@link MavenExecutionRequest} events. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Named +public class MavenExecutionRequestHandler + extends EventSpyHandler +{ + public void handle(final MavenExecutionRequest event) throws Exception { + log.debug("Execution request: {}", event); + + // Configure a batch listener unless a quiet listener is already added + TransferListener listener = event.getTransferListener(); + if (!(listener instanceof QuietMavenTransferListener)) { + event.setTransferListener(new BatchModeMavenTransferListener(System.out)); + log.debug("Configured batch mode transfer listener"); + } + + ProfileLogger.logRequestProfiles( event ); // TODO: is this needed anymore? + + configureToolChains(event); + + // TODO: See if we need to actually handle TransferEvent's via handlers too, or if the other aether events cover our needs. + } + + private void configureToolChains(final MavenExecutionRequest event) throws IOException { + // If there is a toolchains document, then write its content to file and configure the request to use it + DocumentReference document = getCallback().getToolChainsDocument(); + if (document == null) return; + + if (event.getUserToolchainsFile() != DEFAULT_USER_TOOLCHAINS_FILE) { + log.warn("Custom tool-chains file configured via command-line as well as via document; document taking precedence"); + } + + log.info("Using tool-chains document ID: {}", document.getId()); + log.trace("Content:\n{}", document.getContent()); // FIXME: May contain sensitive data? + + File file = new File(getCallback().getMavenContextDirectory(), "toolchains.xml"); + File dir = file.getParentFile(); + if (!dir.exists()) { + if (!dir.mkdirs()) { + log.warn("Failed to create directory structure for: {}", file); + } + } + + // Document should not really contain sensitive details, so just leave it around + Writer writer = new BufferedWriter(new FileWriter(file)); + try { + writer.write(document.getContent()); + } + finally { + writer.close(); + } + + log.debug("Wrote toolchains.xml: {}", file); + event.setUserToolchainsFile(file); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/MavenExecutionResultHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/MavenExecutionResultHandler.java new file mode 100644 index 0000000..58f8f07 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/MavenExecutionResultHandler.java @@ -0,0 +1,62 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.apache.maven.execution.MavenExecutionResult; +import org.hudsonci.maven.eventspy_31.EventSpyHandler; +import org.hudsonci.maven.eventspy_31.MavenProjectConverter; + +import javax.inject.Named; + +/** + * Handles {@link MavenExecutionResult} events. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Named +public class MavenExecutionResultHandler + extends EventSpyHandler +{ + public void handle( final MavenExecutionResult event ) + throws Exception + { + log.debug( "Execution result: {}", event ); + + if ( event.hasExceptions() ) + { + log.info( "Build failed with exception(s)" ); + + int i = 0; + for ( Throwable cause : event.getExceptions() ) + { + log.info( "[{}] {}", ++i, cause ); + } + } + + log.debug( "Recording MavenProjects" ); + getBuildRecorder().recordSessionFinished( MavenProjectConverter.extractFrom( event ) ); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ProfileLogger.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ProfileLogger.java new file mode 100644 index 0000000..124e930 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ProfileLogger.java @@ -0,0 +1,98 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.apache.maven.execution.ExecutionEvent; +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.model.Profile; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Settings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map.Entry; + +public class ProfileLogger +{ + private static final Logger log = LoggerFactory.getLogger(ProfileLogger.class); + private static final boolean disabled = true; + + @SuppressWarnings("unused") + public static void log( final ExecutionEvent event ) + { + if( disabled ) return; + + for (MavenProject project : event.getSession().getProjects()) { + log.debug("*** Examining profiles for {}.", project.getName()); + logProfileList( project.getActiveProfiles(), "active" ); + logProfileList( project.getModel().getProfiles(), "model"); + + //logProfiles( event.getSession().getProjectBuildingRequest().getProfiles(), "ProjectBuildingRequest" ); + logProfileList( project.getProjectBuildingRequest().getProfiles(), "ProjectBuildingRequest" ); + + log.debug( "InjectedProfileIds" ); + for ( Entry> entry : project.getInjectedProfileIds().entrySet() ) + { + log.debug( " from {} are {}", entry.getKey(), entry.getValue() ); + } + + Settings settings = event.getSession().getSettings(); + logSettingsProfileList( settings.getProfiles(), "session-settings" ); + + log.debug( "Collected projects: {}", project.getCollectedProjects() ); + log.debug( "Project references: {}", project.getProjectReferences() ); + } + } + + @SuppressWarnings("unused") + public static void logRequestProfiles( final MavenExecutionRequest event ) + { + if( disabled ) return; + + log.debug( "*** Examinig Request profiles." ); + logProfileList( event.getProfiles(), "profiles" ); + log.debug( " active {}", event.getActiveProfiles() ); + log.debug( " inactive {}", event.getInactiveProfiles() ); + } + + private static void logProfileList( List profiles, String type ) + { + log.debug( String.format( "%s %s profiles.", type, profiles.size() ) ); + for ( Profile profile : profiles ) + { + log.debug( " {}", profile ); + } + } + + private static void logSettingsProfileList( List profiles, String type ) + { + log.debug( String.format( "%s %s profiles.", type, profiles.size() ) ); + for ( org.apache.maven.settings.Profile profile : profiles ) + { + log.debug( " {}", String.format("Profile {id: %s, source: %s}", profile.getId(), profile.getSourceLevel() ) ); + } + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ProjectLogger.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ProjectLogger.java new file mode 100644 index 0000000..f28e7f6 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ProjectLogger.java @@ -0,0 +1,69 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.model.Dependency; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.artifact.PluginArtifact; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.List; + +public class ProjectLogger +{ + private static final Logger log = LoggerFactory.getLogger(ProjectLogger.class); + private static final boolean disabled = !Boolean.valueOf(System.getProperty("hudson.eventspy.logging.project")); + + public static void log( MavenProject project, String where ) + { + if( disabled ) return; + + log.debug( "MavenProject ({}) artifacts @ {}:", project.getId(), where); + logArtifactContents( "artifacts", project.getArtifacts() ); + logArtifactContents( "attachedArtifacts", project.getAttachedArtifacts() ); + logArtifactContents( "dependencyArtifacts", project.getDependencyArtifacts() ); + logArtifactContents( "extensionArtifacts", project.getExtensionArtifacts() ); + logArtifactContents( "pluginArtifacts", project.getPluginArtifacts() ); + + for( Artifact artifact : project.getPluginArtifacts() ) + { + if (artifact instanceof PluginArtifact) { + List dependencies = ((PluginArtifact) artifact).getDependencies(); + + Integer maybeSize = (dependencies == null ? null : dependencies.size()); + log.debug( " {} " + "pluginDependencies" + ": {}", maybeSize, dependencies ); + } + } + } + + private static void logArtifactContents( String method, Collection artifacts ) + { + Integer maybeSize = (artifacts == null ? null : artifacts.size()); + log.debug( " {} " + method + ": {}", maybeSize, artifacts ); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ProjectPlanEventHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ProjectPlanEventHandler.java new file mode 100644 index 0000000..ed46a2d --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ProjectPlanEventHandler.java @@ -0,0 +1,45 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import javax.inject.Named; + +import org.hudsonci.maven.eventspy_31.EventSpyHandler; +import org.hudsonci.maven.eventspy_31.LifecycleDebugLoggerImpl.ProjectPlanEvent; + +/** + * Handles {@link ProjectPlanEvent} events. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Named +public class ProjectPlanEventHandler + extends EventSpyHandler +{ + public void handle(final ProjectPlanEvent event) throws Exception { + log.debug("Project plan: {}", event); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ReactorPlanEventHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ReactorPlanEventHandler.java new file mode 100644 index 0000000..161ffd0 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/ReactorPlanEventHandler.java @@ -0,0 +1,45 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import javax.inject.Named; + +import org.hudsonci.maven.eventspy_31.EventSpyHandler; +import org.hudsonci.maven.eventspy_31.LifecycleDebugLoggerImpl.ReactorPlanEvent; + +/** + * Handles {@link ReactorPlanEvent} events. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Named +public class ReactorPlanEventHandler + extends EventSpyHandler +{ + public void handle(final ReactorPlanEvent event) throws Exception { + log.debug("Reactor plan: {}", event); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/RepositoryEventHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/RepositoryEventHandler.java new file mode 100644 index 0000000..8b282ef --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/RepositoryEventHandler.java @@ -0,0 +1,177 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.hudsonci.utils.common.TestAccessible; +import org.hudsonci.maven.model.state.ArtifactDTO; +import org.hudsonci.maven.model.state.ArtifactOperationDTO; + +import org.hudsonci.maven.eventspy_31.EventSpyHandler; +import org.hudsonci.maven.eventspy_31.MavenArtifactConverter; +import org.eclipse.aether.RepositoryEvent; +import org.eclipse.aether.RepositoryEvent.EventType; +import org.eclipse.aether.RequestTrace; +import org.eclipse.aether.repository.ArtifactRepository; +import org.eclipse.aether.repository.RemoteRepository; + +import javax.inject.Named; + +import java.util.Arrays; +import java.util.List; + +import static org.eclipse.aether.RepositoryEvent.EventType.ARTIFACT_DEPLOYED; +import static org.eclipse.aether.RepositoryEvent.EventType.ARTIFACT_DOWNLOADED; +import static org.eclipse.aether.RepositoryEvent.EventType.ARTIFACT_INSTALLED; +import static org.eclipse.aether.RepositoryEvent.EventType.ARTIFACT_RESOLVED; + +/** + * Handles {@link RepositoryEvent} events. + * + * @author Jason Dillon + * @author Jamie Whitehouse + * + * @since 2.1.0 + */ +@Named +public class RepositoryEventHandler + extends EventSpyHandler +{ + /** + * ARTIFACT_DOWNLOADED ; it's been downloaded + * ARTIFACT_RESOLVED; it's been resolved, either downloaded or cached + * ARTIFACT_INSTALLED + * ARTIFACT_DEPLOYED + */ + private static final List interestingArtifactEvents = Arrays.asList( ARTIFACT_RESOLVED, ARTIFACT_DOWNLOADED, ARTIFACT_INSTALLED, ARTIFACT_DEPLOYED ); + + public void handle(final RepositoryEvent event) throws Exception { + log.debug("Repository event: {}", event); + + logRequestTrace(event); + + if( isInterestingArtifactEvent( event ) ) + { + // Converter checks for nulls. + ArtifactDTO artifact = MavenArtifactConverter.convertAetherArtifact(event.getArtifact()); + + // getVersion vs getBaseVersion + // getVersion is the timestamped snapshot vs -SNAPSHOT + // Record both, MavenCoordinatesDTO.getVersion() should always return -SNAPSHOT for + // snapshot artifacts, unless the pom is explicitly using a timestamp snapshot. + // * INSTALLED vs DEPLOYED ramifications: + // use of this as the version would cause deployed artifacts to not match any + // registered installed artifacts because installed artifacts are -SNAPSHOT + // * External -SNAPSHOT dependency DOWNLOADED and RESOLVED ramifications: + // the aether getVersion is the timestamped format, which is handy to know the exact version used in the build + // but if -SNAPSHOT was declared in the pom then the devs don't likely care that much. + // TODO: Could also impact up/downstream triggered builds and fingerprinting? + + ArtifactOperationDTO operation = resolveOperationType( event ); + // Null File is acceptable. + getBuildRecorder().recordArtifactAction(artifact, operation, event.getFile()); + + //logRepositoryConfiguration(operation,event); + } + } + + /** + * Capture deployed artifacts remote repo config for later use in uploading the buildinfo for the artifact. + */ + private void logRepositoryConfiguration(final ArtifactOperationDTO operation, final RepositoryEvent event) { + if (event.getRepository() != null) { + log.debug("Repo type: {}; info {}", event.getRepository().getClass(), event.getRepository()); + } + + if (ArtifactOperationDTO.DEPLOYED.equals(operation)) { + ArtifactRepository repository = event.getRepository(); + if (repository instanceof RemoteRepository) { + RemoteRepository remoteRepo = (RemoteRepository) repository; + log.debug("Deploy info for remote repository: {}", repository); + log.debug(" Authentication: {}", remoteRepo.getAuthentication()); + } + } + } + + /** + * From Benjamin Bentmann: + * Aether artifact resolution can succeed or fail, the event is fired in + * both cases to signal the end of the resolution. + * Checking the artifact file is another way to detect failure/success, by + * definition, an artifact is considered resolved if and only if it has a file. + */ + @TestAccessible + ArtifactOperationDTO resolveOperationType( final RepositoryEvent event ) + { + ArtifactOperationDTO result; + if( null == event.getFile() ) + { + for( Exception e : event.getExceptions() ) + { + log.debug( "Artifact not found", e ); + } + + result = ArtifactOperationDTO.NOT_FOUND; + } + else + { + result = ArtifactOperationDTO.valueOf( event.getType().name().substring( 9 ) ); + } + + return result; + } + + // TODO: find a better name, something to indicate that it's about actions + // being completed e.g. INSTALLED not INSTALLING + private boolean isInterestingArtifactEvent( final RepositoryEvent event ) + { + return interestingArtifactEvents.contains( event.getType() ); + } + + private void logRequestTrace(final RepositoryEvent event) { + // Use trace level logging because this is a lot of information that + // we're currently not using. + if (!log.isTraceEnabled()) { + // Don't compute trace logging if we're not logging. + return; + } + + RequestTrace currentNode = event.getTrace(); + + if (currentNode == null) { + // Nothing to log. + return; + } + + StringBuffer sb = new StringBuffer(); + sb.append(currentNode.getData().getClass().getSimpleName()); + + while ((currentNode = currentNode.getParent()) != null) { + sb.append(" <= "); + sb.append(currentNode.getData().getClass().getSimpleName()); + } + + log.trace("Trace stack: {}; value {}", sb.toString(), event.getTrace().getData()); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/SettingsBuildingRequestHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/SettingsBuildingRequestHandler.java new file mode 100644 index 0000000..b48e995 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/SettingsBuildingRequestHandler.java @@ -0,0 +1,84 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.apache.maven.settings.building.SettingsBuildingRequest; +import org.apache.maven.settings.building.StringSettingsSource; +import org.hudsonci.maven.eventspy.common.DocumentReference; +import org.hudsonci.maven.eventspy_31.EventSpyHandler; + +import javax.inject.Named; + +import static org.apache.maven.cli.MavenCli.DEFAULT_GLOBAL_SETTINGS_FILE; +import static org.apache.maven.cli.MavenCli.DEFAULT_USER_SETTINGS_FILE; + +/** + * Handles {@link SettingsBuildingRequest} events. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Named +public class SettingsBuildingRequestHandler + extends EventSpyHandler +{ + public void handle(final SettingsBuildingRequest event) throws Exception { + log.debug("Settings request: {}", event); + + DocumentReference document; + + // TODO: Support debug option to write document to disk + + document = getCallback().getSettingsDocument(); + log.debug("Settings document: {}", document); + + if (document != null) { + if (event.getUserSettingsFile() != DEFAULT_USER_SETTINGS_FILE) { + log.warn("Custom settings file configured via command-line as well as via document; document taking precedence"); + } + + log.info("Using settings document ID: {}", document.getId()); + log.trace("Content:\n{}", document.getContent()); // FIXME: May contain sensitive data + + event.setUserSettingsFile(null); + event.setUserSettingsSource(new StringSettingsSource(document.getContent(), document.getLocation())); + } + + document = getCallback().getGlobalSettingsDocument(); + log.debug("Global settings document: {}", document); + + if (document != null) { + if (event.getGlobalSettingsFile() != DEFAULT_GLOBAL_SETTINGS_FILE) { + log.warn("Custom global settings file configured via command-line as well as via document; document taking precedence"); + } + + log.info("Using global settings document ID: {}", document.getId()); + log.trace("Content:\n{}", document.getContent()); // FIXME: May contain sensitive data + + event.setGlobalSettingsFile(null); + event.setGlobalSettingsSource(new StringSettingsSource(document.getContent(), document.getLocation())); + } + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/SettingsBuildingResultHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/SettingsBuildingResultHandler.java new file mode 100644 index 0000000..96482cf --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/SettingsBuildingResultHandler.java @@ -0,0 +1,45 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.apache.maven.settings.building.SettingsBuildingResult; +import org.hudsonci.maven.eventspy_31.EventSpyHandler; + +import javax.inject.Named; + +/** + * Handles {@link SettingsBuildingResult} events. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Named +public class SettingsBuildingResultHandler + extends EventSpyHandler +{ + public void handle(final SettingsBuildingResult event) throws Exception { + log.debug("Settings result: {}", event); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/WeavePlanEventHandler.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/WeavePlanEventHandler.java new file mode 100644 index 0000000..f190575 --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/handler/WeavePlanEventHandler.java @@ -0,0 +1,45 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import javax.inject.Named; + +import org.hudsonci.maven.eventspy_31.EventSpyHandler; +import org.hudsonci.maven.eventspy_31.LifecycleDebugLoggerImpl.WeavePlanEvent; + +/** + * Handles {@link WeavePlanEvent} events. + * + * @author Jason Dillon + * @since 2.1.0 + */ +@Named +public class WeavePlanEventHandler + extends EventSpyHandler +{ + public void handle(final WeavePlanEvent event) throws Exception { + log.debug("Weave plan: {}", event); + } +} diff --git a/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/recorder/BuildRecorder.java b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/recorder/BuildRecorder.java new file mode 100644 index 0000000..a8de5cf --- /dev/null +++ b/maven3-eventspy-3.1/src/main/java/org/hudsonci/maven/eventspy_31/recorder/BuildRecorder.java @@ -0,0 +1,280 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.recorder; + +import org.hudsonci.utils.common.TestAccessible; +import org.hudsonci.maven.model.MavenCoordinatesDTO; +import org.hudsonci.maven.model.state.ArtifactActionDTO; +import org.hudsonci.maven.model.state.ArtifactDTO; +import org.hudsonci.maven.model.state.ArtifactOperationDTO; +import org.hudsonci.maven.model.state.BuildResultDTO; +import org.hudsonci.maven.model.state.MavenProjectDTO; +import org.hudsonci.maven.model.state.MavenProjectDTOHelper; + +import org.apache.maven.execution.BuildSummary; +import org.apache.maven.project.MavenProject; +import org.hudsonci.maven.eventspy.common.Callback; +import org.hudsonci.maven.eventspy_31.MavenArtifactConverter; +import org.hudsonci.maven.eventspy_31.MavenProjectConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.eclipse.aether.graph.Dependency; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.hudsonci.maven.eventspy_31.MavenProjectConverter.convertMavenProject; +import static org.hudsonci.maven.eventspy_31.MavenProjectConverter.updateWithBuildResult; +import static org.hudsonci.maven.eventspy_31.MavenProjectConverter.updateWithBuildSummary; + +/** + * Records and processes significant build events. + * + * @author Jamie Whitehouse + * @since 2.1.0 + */ +public class BuildRecorder +{ + private static final Logger log = LoggerFactory.getLogger(BuildRecorder.class); + private MavenCoordinatesDTO resolvingProjectCoordinates; + private final Callback callback; + + private String executingProjectId; + + private int dependencyArtifactCount = 0; + private int recordedArtifactCount = 0; + private long commitDurationToDate = 0; + private ArrayList recordedArtifacts = new ArrayList(350); // Rough guess capacity based on permodule analysis of Hudson. + + /** + * @param callback to transfer build information to + */ + public BuildRecorder(final Callback callback) { + this.callback = callback; + } + + public void recordArtifactAction(final ArtifactDTO artifact, final ArtifactOperationDTO operation, final File file) { + checkNotNull(artifact); + checkNotNull(operation); + // A null file is acceptable; occurs when not found or a transfer error. + + // Capture all types, including poms since these can be used as a + // dependency with scope=import and we'll want to fingerprint them. + + artifact.withRepositoryFile(resolveFile(file)) + .withActions(new ArtifactActionDTO().withProjectId(executingProjectId) + .withOperation(operation)); + + // Artifact creating projects are not consumers. + if (ArtifactOperationDTO.INSTALLED.equals(operation)) { + artifact.withCreatedProject(executingProjectId); + } + else { + artifact.withConsumingProjects(executingProjectId); + } + + recordArtifact(artifact); + } + + @Deprecated + public void recordArtifactAction(final MavenCoordinatesDTO coordinates, + final ArtifactOperationDTO operation, + final File file, + final String artifactType) { + checkNotNull(coordinates); + checkNotNull(operation); + // A null file is acceptable; occurs when not found or a transfer error. + + // Capture all types, including poms since these can be used as a + // dependency with scope=import and we'll want to fingerprint them. + ArtifactDTO artifact = new ArtifactDTO() + .withCoordinates(coordinates) + .withType(artifactType) + .withRepositoryFile(resolveFile(file)) + .withActions(new ArtifactActionDTO().withProjectId(executingProjectId) + .withOperation(operation)); + + // Artifact creating projects are not consumers. + if (ArtifactOperationDTO.INSTALLED.equals(operation)) { + artifact.withCreatedProject(executingProjectId); + } + else { + artifact.withConsumingProjects(executingProjectId); + } + + recordArtifact(artifact); + } + + /** + * Resolves the file to a path or returns null if not possible, rather than throwing an exception. + * + * Currently only the ArtifactFingerprinter uses the path, and it checks for nulls and records errors. + * + * I'd rather have the rest of the artifact info recorded and no fingerprint than having the exception cause all + * info to be lost. + */ + private String resolveFile(final File file) { + String path = null; + if (file != null) { + try { + // Note: this must be performed on the actual node the data is being collected on rather than from the + // callback running on the master. + path = file.getCanonicalPath(); + log.debug("Computed artifact path for {} as canonicalPath {}", file.getName(), path); + } + catch (IOException e) { + // Treat exception the same as file not found and return null. + log.error("File could not be resolved", e); + } + } + return path; + } + + /** + * Synchronizes recording of artifacts. + */ + public void recordArtifact(final ArtifactDTO artifact) { + synchronized (recordedArtifacts) { + recordedArtifacts.add(checkNotNull(artifact)); + recordedArtifactCount++; + } + } + + public void recordDependencyResolutionStarted(final MavenProject mavenProject) { + if (mavenProject != null) { + log.debug("Requested dependencies for {}", mavenProject); + setResolvingProject(mavenProject); + } + else { + log.debug("Requested dependencies for {}", "a non-project"); + resetResolvingProject(); + } + } + + public void recordDependencyResolutionFinished(final List resolvedDependencies) { + checkNotNull(resolvedDependencies); + log.debug("Recording dependencies for {}:", resolvingProjectCoordinates); + for (Dependency dependency : resolvedDependencies) { + log.debug(" {}", dependency.toString()); + + if (isResolvingProjectRequests()) { + ArtifactDTO artifactDto = MavenArtifactConverter.convertAetherArtifact(dependency.getArtifact()); + artifactDto.withDependentProjects(MavenProjectDTOHelper.asId(resolvingProjectCoordinates)); + + recordArtifact(artifactDto); + dependencyArtifactCount++; + } + } + } + + public void recordSessionFinished(final List participatingProjects) { + // Record project/module info. + // TODO: Do we need a sanity check that the in progress collected + // projects match the final list of projects? + callback.setParticipatingProjects(participatingProjects); + + // This is as close to the Callback.close event as we're likely to get, at the moment. + // Just in case artifacts were recorded outside of the last project/module build. + commitArtifacts(); + } + + private boolean isResolvingProjectRequests() { + return resolvingProjectCoordinates != null; + } + + private void setResolvingProject(final MavenProject mavenProject) { + resolvingProjectCoordinates = MavenProjectConverter.asCoordinates(mavenProject); + } + + private void resetResolvingProject() { + resolvingProjectCoordinates = null; + } + + public void recordSessionStarted(final List projects) { + List participatingProjects = new ArrayList(); + + for (MavenProject project : projects) { + MavenProjectDTO projectDTO = convertMavenProject(project); + updateWithBuildResult(projectDTO, BuildResultDTO.SCHEDULED); + participatingProjects.add(projectDTO); + } + + callback.setParticipatingProjects(participatingProjects); + } + + public void recordProjectStarted(final MavenProject project) { + MavenProjectDTO projectDTO = convertMavenProject(project); + updateWithBuildResult(projectDTO, BuildResultDTO.BUILDING); + + updateProject(projectDTO); + } + + public void recordProjectFinished(final MavenProject project, final BuildSummary buildSummary) { + MavenProjectDTO projectDTO = convertMavenProject(project); + updateWithBuildSummary(projectDTO, buildSummary); + + updateProject(projectDTO); + } + + // Moved from CallbackImpl.updateParticipatingProject + private void updateProject(final MavenProjectDTO project) { + callback.updateParticipatingProject(project); + + if (project.getBuildSummary() != null && BuildResultDTO.BUILDING.equals(project.getBuildSummary().getResult())) { + executingProjectId = project.getId(); + log.debug("Current executing project: {}.", executingProjectId); + } + else { + // No point in committing artifacts for newly started projects because the contents should not be that + // much different than the previously finished project and it's a waste of traffic. + commitArtifacts(); + } + } + + @TestAccessible + List getRecordedArtifacts() { + synchronized (recordedArtifacts) { + return recordedArtifacts; + } + } + + private void commitArtifacts() { + synchronized (recordedArtifacts) { + long start = System.currentTimeMillis(); + callback.addArtifacts(recordedArtifacts); + long duration = System.currentTimeMillis() - start; + + commitDurationToDate += duration; + log.debug("Committed {} artifacts in {}ms of cumulative {}ms: {} dependencies of {} recorded", new Object[] { + recordedArtifacts.size(),duration,commitDurationToDate,dependencyArtifactCount, recordedArtifactCount}); + + // Takes advantage of the callback being remote and de/serialization breaking the reference to the recordedArtifacts. + recordedArtifacts.clear(); + } + } +} diff --git a/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/MavenProjectConverterTest.java b/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/MavenProjectConverterTest.java new file mode 100644 index 0000000..fd39861 --- /dev/null +++ b/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/MavenProjectConverterTest.java @@ -0,0 +1,194 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31; + +import org.hudsonci.maven.model.state.BuildResultDTO; +import org.hudsonci.maven.model.state.BuildSummaryDTO; +import org.hudsonci.maven.model.state.MavenProjectDTO; + +import org.apache.maven.execution.BuildFailure; +import org.apache.maven.execution.BuildSuccess; +import org.apache.maven.execution.BuildSummary; +import org.apache.maven.execution.MavenExecutionResult; +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.project.MavenProject; +import org.hudsonci.maven.eventspy_31.MavenProjectConverter; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; + +/** + * Model to DTO conversion tests for {@link MavenProjectConverter}. + * + * @author Jamie Whitehouse + */ +public class MavenProjectConverterTest +{ + @Test + public void verifyBuildSummaryToBuildResultConversion() + { + BuildResultDTO success = + MavenProjectConverter.convertToBuildResult( new BuildSuccess( createProjectStub(), 0 ) ); + assertThat( success, equalTo( BuildResultDTO.SUCCESS ) ); + + BuildResultDTO failure = + MavenProjectConverter.convertToBuildResult( new BuildFailure( createProjectStub(), 0, null ) ); + assertThat( failure, equalTo( BuildResultDTO.FAILURE ) ); + + BuildResultDTO nullSummary = MavenProjectConverter.convertToBuildResult( null ); + assertThat( nullSummary, equalTo( BuildResultDTO.SKIPPED ) ); + + BuildResultDTO unknownType = + MavenProjectConverter.convertToBuildResult( new BuildSummary( createProjectStub(), 0 ) + { + } ); + assertThat( unknownType, equalTo( BuildResultDTO.UNKNOWN ) ); + } + + @Test + public void verifyNonNullBuildSummaryConversion() + { + long duration = 1002003; + BuildSummary summary = new BuildSummary( createProjectStub(), duration ) + { + }; + + BuildSummaryDTO summaryDTO = MavenProjectConverter.convertBuildSummary( summary ); + assertThat( summaryDTO.getDuration(), equalTo( duration ) ); + // Result conversion tested elsewhere; just ensure that it's been copied into the DTO. + assertThat( summaryDTO.getResult(), instanceOf( BuildResultDTO.class ) ); + + // TODO: if BuildSummary is instance of BuildFailure there's an exception that can be added + } + + @Test + public void failureBuildSummaryCauseIsConverted() + { + BuildSummary summary = new BuildFailure( createProjectStub(), 0, + new LifecycleExecutionException( new IllegalStateException( "Nested exception for testing." ) ) ); + BuildSummaryDTO summaryDTO = MavenProjectConverter.convertBuildSummary( summary ); + + // Content doesn't matter for this test. + assertThat( summaryDTO.getFailureCause(), notNullValue() ); + } + + @Test + public void failureBuildSummaryWithNullCauseIsConvertedWithoutNPE() + { + BuildSummary summary = new BuildFailure( createProjectStub(), 0, null ); + BuildSummaryDTO summaryDTO = MavenProjectConverter.convertBuildSummary( summary ); + + assertThat( summaryDTO.getFailureCause(), nullValue() ); + } + + @Test + public void nullBuildSummaryIsConvertedToSkipped() + { + BuildSummaryDTO summaryDTO = MavenProjectConverter.convertBuildSummary( null ); + assertThat( summaryDTO.getResult(), equalTo( BuildResultDTO.SKIPPED ) ); + } + + @Test + public void projectUpdatedWithConvertedBuildSummary() + { + // BuildSummary conversion is tested elsewhere; just ensure that there is + // an association made between the converted value and the MavenProjectDTO. + + // Expected initial state. + MavenProjectDTO projectDTO = new MavenProjectDTO(); + assertThat( projectDTO.getBuildSummary(), nullValue() ); + + BuildSummary summary = new BuildSummary( createProjectStub(), 0 ) + { + }; + + MavenProjectConverter.updateWithBuildSummary( projectDTO, summary ); + BuildSummaryDTO summaryDTO = projectDTO.getBuildSummary(); + assertThat( summaryDTO, notNullValue() ); + assertThat( summaryDTO, instanceOf( BuildSummaryDTO.class ) ); + } + + /** + * Verifies that when {@link MavenExecutionResult#getBuildSummary(MavenProject)} returns null the project is updated + * appropriately. + */ + @Test + public void projectUpdatedToSkippedWhenBuildSummaryIsNull() + { + MavenProjectDTO projectDTO = new MavenProjectDTO(); + MavenProjectConverter.updateWithBuildSummary( projectDTO, null ); + assertThat( projectDTO.getBuildSummary().getResult(), equalTo( BuildResultDTO.SKIPPED ) ); + } + + @Test + public void projectWithNoBuildSummaryIsUpdatedWithConvertedBuildResult() + { + MavenProjectDTO projectDTO = new MavenProjectDTO(); + + // test when no build summary + MavenProjectConverter.updateWithBuildResult( projectDTO, BuildResultDTO.SCHEDULED ); + assertThat( projectDTO.getBuildSummary().getResult(), equalTo( BuildResultDTO.SCHEDULED ) ); + } + + @Test + public void projectWithExistingBuildSummaryIsOverwrittenWithConvertedBuildResult() + { + MavenProjectDTO projectDTO = new MavenProjectDTO(); + projectDTO.setBuildSummary( new BuildSummaryDTO().withResult( BuildResultDTO.SUCCESS ).withDuration( 500L ) ); + assertThat( projectDTO.getBuildSummary(), notNullValue() ); + + BuildSummary summary = new BuildFailure( createProjectStub(), 1500, null ); + + // test when build summary already exists + MavenProjectConverter.updateWithBuildSummary( projectDTO, summary ); + assertThat( projectDTO.getBuildSummary().getResult(), equalTo( BuildResultDTO.FAILURE ) ); + assertThat( projectDTO.getBuildSummary().getDuration(), equalTo( 1500l ) ); + } + + @Test + public void verifyMavenProjectBasicConversion() + { + MavenProject project = createProjectStub(); + MavenProjectDTO projectDTO = MavenProjectConverter.convertMavenProject( project ); + assertThat( projectDTO.getName(), equalTo( project.getName() ) ); + assertThat( projectDTO.getId(), equalTo( "org.hudsonci.example:example-project:jar:1.0-SNAPSHOT") ); + + // TODO: no name set + } + + private MavenProject createProjectStub() + { + MavenProject project = new MavenProject(); + project.setName( "Project for testing" ); + project.setGroupId( "org.hudsonci.example" ); + project.setArtifactId( "example-project" ); + project.setVersion( "1.0-SNAPSHOT" ); + return project; + } +} diff --git a/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/handler/MavenExecutionResultHandlerTest.java b/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/handler/MavenExecutionResultHandlerTest.java new file mode 100644 index 0000000..bfc54c9 --- /dev/null +++ b/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/handler/MavenExecutionResultHandlerTest.java @@ -0,0 +1,107 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.hudsonci.maven.model.state.MavenProjectDTO; + +import org.apache.maven.execution.DefaultMavenExecutionResult; +import org.apache.maven.execution.MavenExecutionResult; +import org.apache.maven.project.MavenProject; +import org.hudsonci.maven.eventspy.common.Callback; +import org.hudsonci.maven.eventspy_31.EventSpyHandler; +import org.hudsonci.maven.eventspy_31.handler.MavenExecutionResultHandler; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@RunWith( MockitoJUnitRunner.class ) +public class MavenExecutionResultHandlerTest +{ + @Mock + private Callback callback; + private EventSpyHandler eventHandler; + + @Before + public void configureHandler() + { + // add the handlers that I'm interested in... + // plexus wires this up for us + // MavenExecutionResultHandler eventHandler = new MavenExecutionResultHandler(); + // EventSpyProcessor processor = new EventSpyProcessor(null, eventHandler); + // processor.init(new EventSpyHandler.HandlerContext(mock( Callback.class ))); + // processor.process( eventHandler ) + // eventHandler.handle( mock(MavenExecutionResult.class) ); + + eventHandler = new MavenExecutionResultHandler(); + eventHandler.init( new EventSpyHandler.HandlerContext( callback ) ); + } + + @SuppressWarnings( { "rawtypes", "unchecked" } ) + @Test + public void participatingProjectsAreCollected() + throws Exception + { + MavenExecutionResult resultWithProjects = new DefaultMavenExecutionResult(); + resultWithProjects.setTopologicallySortedProjects( Arrays.asList( new MavenProject[] + { + new MavenProject(), + new MavenProject(), + new MavenProject() + }) ); + + eventHandler.handle( resultWithProjects ); + + ArgumentCaptor captor = ArgumentCaptor.forClass( List.class ); + verify( callback, times( 1 ) ).setParticipatingProjects( captor.capture() ); + + List dtos = captor.getValue(); + assertThat( dtos, hasSize( 3 ) ); + + // Assume that all translation work is done by the MavenProjectConverter, + // which is tested elsewhere. + // Hence, no need to check the collection contents. + } + + @Test + public void nullProjectsDoNotThrowExceptions() throws Exception + { + // Ensures that we're using a Maven version that has MNG-4904 applied. + MavenExecutionResult result = new DefaultMavenExecutionResult(); + result.setTopologicallySortedProjects( null ); + + eventHandler.handle( result ); + } +} diff --git a/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/handler/RepsitoryEventHandlerTest.java b/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/handler/RepsitoryEventHandlerTest.java new file mode 100644 index 0000000..cd07118 --- /dev/null +++ b/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/handler/RepsitoryEventHandlerTest.java @@ -0,0 +1,57 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.handler; + +import org.hudsonci.maven.model.state.ArtifactOperationDTO; + +import org.hudsonci.maven.eventspy_31.handler.RepositoryEventHandler; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.eclipse.aether.RepositoryEvent; +import org.eclipse.aether.RepositoryEvent.EventType; +import org.eclipse.aether.RepositorySystemSession; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +/** + * Tests for the {@link RepositoryEventHandler}. + */ +@RunWith(MockitoJUnitRunner.class) +public class RepsitoryEventHandlerTest +{ + @Mock + private RepositorySystemSession session; + + @Test + public void aetherFailedResolutionsAreTransformedToNotFoundOperations() throws Exception + { + RepositoryEvent event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DESCRIPTOR_INVALID ).build(); + + assertThat( new RepositoryEventHandler().resolveOperationType( event ), equalTo( ArtifactOperationDTO.NOT_FOUND ) ); + } +} diff --git a/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/recorder/BuildRecorderArtifactRecordingTest.java b/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/recorder/BuildRecorderArtifactRecordingTest.java new file mode 100644 index 0000000..cfe2351 --- /dev/null +++ b/maven3-eventspy-3.1/src/test/java/org/hudsonci/maven/eventspy_31/recorder/BuildRecorderArtifactRecordingTest.java @@ -0,0 +1,257 @@ +/** + * The MIT License + * + * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.hudsonci.maven.eventspy_31.recorder; + +import com.google.common.collect.ImmutableList; +import org.hudsonci.maven.model.MavenCoordinatesDTO; +import org.hudsonci.maven.model.state.ArtifactDTO; +import org.hudsonci.maven.model.state.ArtifactOperationDTO; +import org.hudsonci.maven.model.state.MavenProjectDTO; +import org.hudsonci.maven.model.state.MavenProjectDTOHelper; +import org.hudsonci.maven.model.state.RuntimeEnvironmentDTO; + +import org.apache.maven.project.MavenProject; +import org.hamcrest.Matchers; +import org.hudsonci.maven.eventspy.common.Callback; +import org.hudsonci.maven.eventspy.common.DocumentReference; +import org.hudsonci.maven.eventspy_31.recorder.BuildRecorder; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.hudsonci.maven.model.test.CannedDtos.fakeArtifact; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasSize; + +/** + * Tests for {@link BuildRecorder} functions related to tracking artifacts. + * + * @author Jamie Whitehouse + */ +//@Ignore("Test needs updating to match slight rework of Callback/BuildRecorder interaction.") +public class BuildRecorderArtifactRecordingTest +{ + private BuildRecorder recorder; + + private CallbackStub callback; + + @Before + public void configure() { + callback = new CallbackStub(); + recorder = new BuildRecorder(callback); + } + + @Test + @SuppressWarnings("unchecked") + public void recordedArtifactPassedToCallbackWhenSessionFinished() { + ArtifactDTO artifact = fakeArtifact(); + + recorder.recordArtifact(artifact); + recorder.recordSessionFinished(null); + + assertThat(getCallbackArtifacts(), hasItem(artifact)); + } + + /** + * Merging happens with the ArtifactRegistry on the master in the Callback. + */ + @Test + public void artifactsShouldNotBeAggregatedOrMerged() { + recorder.recordArtifactAction(fakeArtifact(), ArtifactOperationDTO.DOWNLOADED, new File(".")); + recorder.recordArtifactAction(fakeArtifact(), ArtifactOperationDTO.RESOLVED, new File(".")); + recorder.recordSessionFinished(null); + + List artifacts = getCallbackArtifacts(); + assertThat(artifacts, hasSize(2)); + } + + /** + * From Benjamin Bentmann: Aether artifact resolution can succeed or fail, the event is fired in both cases to + * signal the end of the resolution. The RepositoryEvent.getException() should indicate success or failure. From + * Aether's point of view, there are only two reasons for resolution failures, not found or transfer issue. Checking + * the artifact file is another way to detect failure/success, by definition, an artifact is considered resolved if + * and only if it has a file. + * + * From Jamie: We need to accept null Files. + */ + @Test + public void unresolvedArtifactIsAcceptable() { + File nullFile = null; + recorder.recordArtifactAction(fakeArtifact(), ArtifactOperationDTO.NOT_FOUND, nullFile); + // JUnit will error if an unexpected exception is thrown. + + assertThat(recorder.getRecordedArtifacts().get(0).getActions(), hasSize(1)); + } + + @Test + public void projectStartedDoesNotCommitArtifacts() { + // Make a record to confirm it's not committed when starting a project. + recorder.recordArtifactAction(fakeArtifact(), ArtifactOperationDTO.RESOLVED, new File(".")); + + MavenProject project = createBuildingProject(createBuildingCoordinates()); + recorder.recordProjectStarted(project); + + assertThat(getCallbackArtifacts(), Matchers. empty()); + } + + @Test + public void projectFinishedCommitsArtifacts() { + MavenProject project = createBuildingProject(createBuildingCoordinates()); + recorder.recordProjectStarted(project); + recorder.recordArtifactAction(fakeArtifact(), ArtifactOperationDTO.RESOLVED, new File(".")); + recorder.recordProjectFinished(project, null); + + assertThat(getCallbackArtifacts(), hasSize(1)); + } + + @Test + public void currentBuildingProjectHasDependenciesTracked() { + MavenCoordinatesDTO coordinates = buildProjectWithArtifactOperation(ArtifactOperationDTO.DOWNLOADED); + ArtifactDTO committedArtifact = recorder.getRecordedArtifacts().get(0); + + assertThat(committedArtifact.getConsumingProjects(), contains(MavenProjectDTOHelper.asId(coordinates))); + assertThat(committedArtifact.getDependentProjects(), Matchers. empty()); + } + + @Test + public void artifactInstallOperationRecordsCreatorButNotConsumer() { + MavenCoordinatesDTO coordinates = buildProjectWithArtifactOperation(ArtifactOperationDTO.INSTALLED); + ArtifactDTO committedArtifact = recorder.getRecordedArtifacts().get(0); + + assertThat(committedArtifact.getActions(), hasSize(1)); + + assertThat(committedArtifact.getCreatedProject(), equalTo(MavenProjectDTOHelper.asId(coordinates))); + + assertThat(committedArtifact.getConsumingProjects(), Matchers. empty()); + assertThat(committedArtifact.getDependentProjects(), Matchers. empty()); + } + + // TODO: should projects deploying be considered the creator? + // E.g. what if this project is just deploying other artifacts? + // How does this work with assembly attach and build helper like plugins? + @Test + public void artifactDeployOperationIsRecordedAsConsumerNotCreator() { + buildProjectWithArtifactOperation(ArtifactOperationDTO.DEPLOYED); + ArtifactDTO committedArtifact = recorder.getRecordedArtifacts().get(0); + + assertThat(committedArtifact.getActions(), hasSize(1)); + assertThat(committedArtifact.getConsumingProjects(), hasSize(1)); + assertThat(committedArtifact.getDependentProjects(), Matchers. empty()); + } + + @Test + public void consumingOperationsHaveProjectRecordedAsConsumer() { + MavenCoordinatesDTO buildingProject = buildProjectWithArtifactOperation(ArtifactOperationDTO.DEPLOYED); + assertThat(recorder.getRecordedArtifacts(), hasSize(1)); + assertThat(recorder.getRecordedArtifacts().get(0).getConsumingProjects(), contains(MavenProjectDTOHelper.asId(buildingProject))); + + buildProjectWithArtifactOperation(ArtifactOperationDTO.RESOLVED); + assertThat(recorder.getRecordedArtifacts(), hasSize(2)); + assertThat(recorder.getRecordedArtifacts().get(1).getConsumingProjects(), contains(MavenProjectDTOHelper.asId(buildingProject))); + } + + private List getCallbackArtifacts() { + return callback.getArtifacts(); + } + + private MavenCoordinatesDTO buildProjectWithArtifactOperation(final ArtifactOperationDTO operation) { + MavenCoordinatesDTO coordinates = createBuildingCoordinates(); + MavenProject project = createBuildingProject(coordinates); + recorder.recordProjectStarted(project); + recorder.recordArtifactAction(fakeArtifact(), operation, new File(".")); + return coordinates; + } + + private MavenProject createBuildingProject(MavenCoordinatesDTO coordinates) { + MavenProject project = new MavenProject(); + project.setGroupId(coordinates.getGroupId()); + project.setArtifactId(coordinates.getArtifactId()); + project.setPackaging(coordinates.getType()); + project.setVersion(coordinates.getVersion()); + return project; + } + + private MavenCoordinatesDTO createBuildingCoordinates() { + return new MavenCoordinatesDTO().withGroupId("fake-id").withArtifactId("building").withType("jar").withVersion("test-version"); + } + + private class CallbackStub implements Callback { + private final List capturedArtifacts = new ArrayList(); + + public List getArtifacts() { + return capturedArtifacts; + } + + public void addArtifacts(final Collection artifacts) { + capturedArtifacts.addAll(ImmutableList.copyOf(artifacts)); + } + + public void setParticipatingProjects(List projects) { + } + + public void updateParticipatingProject(MavenProjectDTO project) { + // Do nothing but allow method to pass for test. + } + + public File getMavenContextDirectory() { + throw new UnsupportedOperationException("Not implemented"); + } + + public boolean isAborted() { + throw new UnsupportedOperationException("Not implemented"); + } + + public void close() { + throw new UnsupportedOperationException("Not implemented"); + } + + public void setRuntimeEnvironment(RuntimeEnvironmentDTO env) { + throw new UnsupportedOperationException("Not implemented"); + } + + public void setArtifacts(Collection artifacts) { + throw new UnsupportedOperationException("Not implemented"); + } + + public DocumentReference getSettingsDocument() { + throw new UnsupportedOperationException("Not implemented"); + } + + public DocumentReference getGlobalSettingsDocument() { + throw new UnsupportedOperationException("Not implemented"); + } + + public DocumentReference getToolChainsDocument() { + throw new UnsupportedOperationException("Not implemented"); + } + } +} diff --git a/maven3-eventspy-common/pom.xml b/maven3-eventspy-common/pom.xml index 661c74d..a2c7c81 100644 --- a/maven3-eventspy-common/pom.xml +++ b/maven3-eventspy-common/pom.xml @@ -27,14 +27,42 @@ THE SOFTWARE. 4.0.0 org.hudsonci.plugins - hudson-maven3 - 3.0.1-SNAPSHOT + maven3-plugin-parent + 3.0.7-SNAPSHOT maven3-eventspy-common Hudson :: Maven 3 :: Event Spy Common + + org.eclipse.hudson + hudson-core + provided + jar + + + hudson-cli + org.eclipse.hudson + + + hudson-remoting + org.eclipse.hudson + + + + + org.eclipse.hudson + hudson-war + provided + war + + + org.eclipse.hudson + hudson-test-framework + provided + jar + org.slf4j slf4j-api @@ -53,7 +81,7 @@ THE SOFTWARE. - org.eclipse.hudson.main + org.eclipse.hudson hudson-remoting ${hudson.remoting.version} provided diff --git a/maven3-model/pom.xml b/maven3-model/pom.xml index 6445904..2f0ae84 100644 --- a/maven3-model/pom.xml +++ b/maven3-model/pom.xml @@ -27,12 +27,13 @@ THE SOFTWARE. 4.0.0 org.hudsonci.plugins - hudson-maven3 - 3.0.1-SNAPSHOT + maven3-plugin-parent + 3.0.7-SNAPSHOT + org.hudsonci.plugins maven3-model - Hudson :: Maven 3 :: Model + Hudson Maven3 Model @@ -58,10 +59,81 @@ THE SOFTWARE. provided + + org.eclipse.hudson + hudson-core + provided + jar + + + hudson-cli + org.eclipse.hudson + + + hudson-remoting + org.eclipse.hudson + + + + + org.eclipse.hudson + hudson-remoting + ${hudson.remoting.version} + provided + + + org.eclipse.hudson + hudson-utils + provided + jar + + + org.eclipse.hudson + hudson-plugin-utils + provided + jar + + + org.eclipse.hudson + hudson-war + provided + war + + + org.eclipse.hudson + hudson-test-framework + provided + jar + + + org.eclipse.hudson + hudson-inject + provided + + + hudson-core + org.eclipse.hudson + + + + + org.eclipse.hudson + hudson-service + provided + + + hudson-plugin-utils + org.eclipse.hudson + + + + + org.eclipse.hudson hudson-test-utils - ${hudson.core.version} test @@ -79,7 +151,7 @@ THE SOFTWARE. - org.jvnet.hudson.main + org.hudsonci.libs hudson-jaxb-xjc ${hudson.jaxb.version} diff --git a/maven3-plugin/nb-configuration.xml b/maven3-plugin/nb-configuration.xml new file mode 100644 index 0000000..c5bbdab --- /dev/null +++ b/maven3-plugin/nb-configuration.xml @@ -0,0 +1,19 @@ + + + + + + JDK_1.7 + true + + diff --git a/maven3-plugin/pom.xml b/maven3-plugin/pom.xml index 033580a..213a04b 100644 --- a/maven3-plugin/pom.xml +++ b/maven3-plugin/pom.xml @@ -27,40 +27,34 @@ THE SOFTWARE. 4.0.0 org.hudsonci.plugins - hudson-maven3 - 3.0.1-SNAPSHOT + maven3-plugin-parent + 3.0.7-SNAPSHOT + org.hudsonci.plugins maven3-plugin - 3.0.1a-SNAPSHOT - Hudson :: Maven 3 :: Plugin + 3.0.7-SNAPSHOT + Hudson Maven3 Plugin hpi - Hudson Maven3 Support + Hudson Maven3 Support Plugin + maven http://wiki.hudson-ci.org/display/HUDSON/Maven+3+Build+Plugin - - - - - org.jvnet.hudson.main - hudson-rest - pom - ${hudson.rest.version} - import - - - - org.jvnet.hudson.main - hudson-gwt - pom - ${hudson.gwt.version} - import - - - + + + This plug-in adds Maven3 support to Hudson. It adds a builder to Freestyle Project to build maven projects. + + + + + The MIT license + http://www.opensource.org/licenses/mit-license.php + repo + + @@ -77,14 +71,12 @@ THE SOFTWARE. org.eclipse.hudson hudson-test-utils - ${hudson.core.version} test org.eclipse.hudson hudson-core - ${hudson.core.version} provided @@ -114,7 +106,6 @@ THE SOFTWARE. org.eclipse.hudson hudson-service - ${hudson.core.version} provided @@ -125,10 +116,9 @@ THE SOFTWARE. - org.jvnet.hudson.main - hudson-rest-api - provided - + org.hudsonci.plugins + rest-plugin + org.sonatype.aether @@ -142,15 +132,11 @@ THE SOFTWARE. provided - - org.jvnet.hudson.main + + org.hudsonci.libs hudson-gwt-common provided - - guava-gwt - com.google.guava - gwt-log com.google.code.gwt-log @@ -158,12 +144,6 @@ THE SOFTWARE. - - com.google.guava - guava-gwt - 12.0 - - com.allen-sauer.gwt.log gwt-log @@ -171,25 +151,25 @@ THE SOFTWARE. - org.jvnet.hudson.main + org.hudsonci.libs hudson-gwt-icons-silk provided - org.jvnet.hudson.main + org.hudsonci.libs hudson-gwt-theme-chrome provided - + org.fusesource.restygwt restygwt provided - org.jvnet.hudson.main + org.hudsonci.libs hudson-gwt-test-support test @@ -203,39 +183,46 @@ THE SOFTWARE. org.eclipse.hudson hudson-utils - ${hudson.core.version} provided - + org.eclipse.hudson hudson-plugin-utils - ${hudson.core.version} provided - org.eclipse.hudson.main + org.eclipse.hudson hudson-remoting ${hudson.remoting.version} provided - org.jvnet.hudson.main - rest-plugin + org.eclipse.hudson + hudson-war + provided + war + + + org.eclipse.hudson + hudson-test-framework + provided jar - + ${project.artifactId} + org.codehaus.enunciate maven-enunciate-plugin + org.apache.maven.plugins @@ -279,7 +266,7 @@ THE SOFTWARE. - + org.apache.maven.plugins maven-war-plugin @@ -289,7 +276,7 @@ THE SOFTWARE. - org.jvnet.hudson.tools + org.eclipse.hudson.tools maven-hpi-plugin true diff --git a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/MavenBuilder.java b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/MavenBuilder.java index 3141069..61a33e7 100644 --- a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/MavenBuilder.java +++ b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/MavenBuilder.java @@ -80,9 +80,15 @@ public class MavenBuilder @XStreamOmitField private NodeService nodes; + + public MavenBuilder(final BuildConfigurationDTO config){ + this(config, false, ""); + } - public MavenBuilder(final BuildConfigurationDTO config) { + public MavenBuilder(final BuildConfigurationDTO config, boolean disabled, String description) { this.config = checkNotNull(config); + setDisabled(disabled); + setDescription(description); } @Inject @@ -159,6 +165,11 @@ public DocumentDTO call() { public boolean perform(final AbstractBuild build, final Launcher launcher, final BuildListener listener) throws InterruptedException, IOException { + if (isDisabled()){ + listener.getLogger().println("\nThe Maven 3 builder is temporarily disabled.\n"); + // just return, this builder is disabled temporarily + return true; + } BuildStateDTO state = attachBuildState( build ).getState(); attachBuildAction( build ); diff --git a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/MavenBuilderDescriptor.java b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/MavenBuilderDescriptor.java index 117acbb..2f146ae 100644 --- a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/MavenBuilderDescriptor.java +++ b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/MavenBuilderDescriptor.java @@ -257,7 +257,9 @@ public boolean configure(final StaplerRequest req, final JSONObject data) throws */ @Override public Builder newInstance(final StaplerRequest req, final JSONObject data) throws FormException { - return new MavenBuilder(createConfiguration(data)); + boolean disabled = data.getBoolean("disabled"); + String description = data.getString("description"); + return new MavenBuilder(createConfiguration(data), disabled, description); } /** diff --git a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/BuildConfigurationExtractor.java b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/BuildConfigurationExtractor.java index 2a0e62b..ef814c1 100644 --- a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/BuildConfigurationExtractor.java +++ b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/BuildConfigurationExtractor.java @@ -92,7 +92,7 @@ public BuildConfigurationDTO extract() { config.setInstallationId(getString("installationId")); config.setGoals(getString("goals")); config.setProperties(getProperties("properties")); - config.setPomFile(getString("pomFile")); + config.setPomFile(getString("pomFile").trim()); config.setPrivateRepository(getBoolean("privateRepository")); config.setPrivateTmpdir(getBoolean("privateTmpdir")); config.setOffline(getBoolean("offline")); diff --git a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/MavenBuilderServiceImpl.java b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/MavenBuilderServiceImpl.java index c9e73c7..a89ee72 100644 --- a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/MavenBuilderServiceImpl.java +++ b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/MavenBuilderServiceImpl.java @@ -161,7 +161,7 @@ public void setBuilderConfiguration(final String projectName, final int index, f for (Builder builder : project.getBuilders()) { if (builder instanceof MavenBuilder) { if (i == index) { - builder = new MavenBuilder(config); + builder = new MavenBuilder(config, builder.isDisabled(), builder.getDescription()); found = true; } i++; diff --git a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/MavenInstallationValidator.java b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/MavenInstallationValidator.java index 722a9be..deeba11 100644 --- a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/MavenInstallationValidator.java +++ b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/builder/internal/MavenInstallationValidator.java @@ -118,11 +118,15 @@ public FilePath getExecutable() throws Exception { mvn = new FilePath(launcher.getChannel(), buildEnv.get(MAVEN_EXEC_WIN)); } else { String file = "mvn"; + FilePath dir = getHome(); if (!launcher.isUnix()) { file += ".bat"; + FilePath winMvn = dir.child("bin").child(file); + if (!winMvn.exists()){ + file = "mvn.cmd"; + } } - FilePath dir = getHome(); mvn = dir.child("bin").child(file); } ensureFileExists(mvn); @@ -248,7 +252,8 @@ private void maybyPut(final String key, final EnvVars source, final EnvVars targ public String getEventSpyVersion() throws Exception { // FIXME: This should probably be in its own component, as well as most of the validation bits VersionScheme versionScheme = new GenericVersionScheme(); - VersionConstraint versionConstraint = new GenericVersionScheme().parseVersionConstraint("[3.0.3,)"); + VersionConstraint maven31 = versionScheme.parseVersionConstraint("[3.1,)"); + VersionConstraint maven30 = versionScheme.parseVersionConstraint("[3.0.3,)"); Version version; String tmp = getMavenVersion(); @@ -258,8 +263,11 @@ public String getEventSpyVersion() throws Exception { throw new AbortException("Unable to parse Maven version: " + tmp); } - // FIXME: For now we only have one spy version, so just make sure that the mvn version given is compatible - if (versionConstraint.containsVersion(version)) { + if (maven31.containsVersion(version)) { + return "3.1"; + } + + if (maven30.containsVersion(version)) { return "3.0"; } diff --git a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/dependencymonitor/internal/DependencyMonitorImpl.java b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/dependencymonitor/internal/DependencyMonitorImpl.java index d6238d6..b9ae0dc 100644 --- a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/dependencymonitor/internal/DependencyMonitorImpl.java +++ b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/dependencymonitor/internal/DependencyMonitorImpl.java @@ -72,7 +72,7 @@ public class DependencyMonitorImpl /** * Set of projects which are subscribed for notifications to artifact changes. */ - private final Set subscribedProjects = Collections.synchronizedSet(new HashSet()); + private final Set subscribedProjects = Collections.synchronizedSet(new HashSet()); private volatile boolean primed; @@ -89,28 +89,28 @@ public void subscribe(final AbstractProject project) { checkNotNull(project); log.debug("Subscribe: {}", project); - subscribedProjects.add(project); + subscribedProjects.add(project.getFullName()); } public void unsubscribe(final AbstractProject project) { checkNotNull(project); log.debug("Unsubscribe: {}", project); - subscribedProjects.remove(project); + subscribedProjects.remove(project.getFullName()); } /** * Check if the given project is subscribed to receive artifact updated notifications. */ private boolean isSubscribedForArtifactNotifications(final AbstractProject project) { - return subscribedProjects.contains(project); + return subscribedProjects.contains(project.getFullName()); } public void purge(final AbstractProject project) { checkNotNull(project); log.debug("Purge: {}", project); - subscribedProjects.remove(project); + subscribedProjects.remove(project.getFullName()); projectArtifactCache.purgeArtifacts(project); } diff --git a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/dependencymonitor/internal/ProjectArtifactCacheImpl.java b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/dependencymonitor/internal/ProjectArtifactCacheImpl.java index ab87103..734aff3 100644 --- a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/dependencymonitor/internal/ProjectArtifactCacheImpl.java +++ b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/dependencymonitor/internal/ProjectArtifactCacheImpl.java @@ -48,6 +48,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import static com.google.common.base.Preconditions.checkNotNull; +import hudson.model.Hudson; +import java.util.ArrayList; import static org.hudsonci.utils.common.Varargs.$; /** @@ -75,12 +77,12 @@ public class ProjectArtifactCacheImpl /** * Map of artifact producing projects to their produced artifacts. */ - private final Multimap projectProducedArtifacts = HashMultimap.create(); + private final Multimap projectProducedArtifacts = HashMultimap.create(); /** * Map of artifact consuming projects to their consumed artifacts. */ - private final Multimap projectConsumedArtifacts = HashMultimap.create(); + private final Multimap projectConsumedArtifacts = HashMultimap.create(); @Inject public ProjectArtifactCacheImpl(final ProjectService projectService, final ArtifactsExtractor artifactsExtractor) { @@ -119,9 +121,10 @@ public ArtifactsPair getArtifacts(final AbstractProject project) { public Collection getProducedArtifacts(final AbstractProject project) { checkNotNull(project); + Lock lock = readLock(); try { - return ImmutableSet.copyOf(projectProducedArtifacts.get(project)); + return ImmutableSet.copyOf(projectProducedArtifacts.get(project.getFullName())); } finally { lock.unlock(); @@ -132,7 +135,7 @@ public Collection getConsumedArtifacts(final AbstractProjec checkNotNull(project); Lock lock = readLock(); try { - return ImmutableSet.copyOf(projectConsumedArtifacts.get(project)); + return ImmutableSet.copyOf(projectConsumedArtifacts.get(project.getFullName())); } finally { lock.unlock(); @@ -142,7 +145,15 @@ public Collection getConsumedArtifacts(final AbstractProjec public Collection getArtifactProducers() { Lock lock = readLock(); try { - return ImmutableSet.copyOf(projectProducedArtifacts.keySet()); + final ArrayList ret = new ArrayList(); + for (String name: projectProducedArtifacts.keySet()) { + final AbstractProject p = Hudson.getInstance().getItemByFullName(name, AbstractProject.class); + if ( p != null ) { + ret.add(p); + } + } + + return ret; } finally { lock.unlock(); @@ -152,22 +163,32 @@ public Collection getArtifactProducers() { public Collection getArtifactConsumers() { Lock lock = readLock(); try { - return ImmutableSet.copyOf(projectConsumedArtifacts.keySet()); + final ArrayList ret = new ArrayList(); + for (String name: projectConsumedArtifacts.keySet()) { + final AbstractProject p = Hudson.getInstance().getItemByFullName(name, AbstractProject.class); + if ( p != null ) { + ret.add(p); + } + } + + return ret; } finally { lock.unlock(); } } - private Collection projectsContaining(final Multimap source, + private Collection projectsContaining(final Multimap source, final MavenCoordinatesDTO artifact) { assert source != null; assert artifact != null; Set projects = Sets.newHashSet(); - for (AbstractProject project : source.keySet()) { - if (source.containsEntry(project, artifact)) { - projects.add(project); + Hudson hudson = Hudson.getInstance(); + for (String projectName : source.keySet()) { + if (source.containsEntry(projectName, artifact)) { + AbstractProject p = hudson.getItemByFullName(projectName, AbstractProject.class); + projects.add(p); } } return projects; @@ -284,12 +305,12 @@ public boolean updateArtifacts(final AbstractProject project, final ArtifactsPai } } - private boolean updateArtifacts(final Multimap collection, + private boolean updateArtifacts(final Multimap collection, final AbstractProject project, final Collection artifacts) { assert collection != null; - Collection removed = collection.replaceValues(project, artifacts); + Collection removed = collection.replaceValues(project.getFullName(), artifacts); return CollectionsHelper.differs(artifacts, removed); } @@ -299,19 +320,19 @@ public void purgeArtifacts(final AbstractProject project) { Lock lock = writeLock(); try { - projectProducedArtifacts.removeAll(project); - projectConsumedArtifacts.removeAll(project); + projectProducedArtifacts.removeAll(project.getFullName()); + projectConsumedArtifacts.removeAll(project.getFullName()); } finally { lock.unlock(); } } - private boolean projectsContain(final Multimap source, final MavenCoordinatesDTO artifact) { + private boolean projectsContain(final Multimap source, final MavenCoordinatesDTO artifact) { assert source != null; assert artifact != null; - for (AbstractProject project : source.keySet()) { - if (source.containsEntry(project, artifact)) { + for (String name : source.keySet()) { + if (source.containsEntry(name, artifact)) { return true; } } diff --git a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/ui/gwt/buildinfo/MavenBuildInfoController.java b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/ui/gwt/buildinfo/MavenBuildInfoController.java index 9afa60d..496eef9 100644 --- a/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/ui/gwt/buildinfo/MavenBuildInfoController.java +++ b/maven3-plugin/src/main/java/org/hudsonci/maven/plugin/ui/gwt/buildinfo/MavenBuildInfoController.java @@ -25,25 +25,22 @@ package org.hudsonci.maven.plugin.ui.gwt.buildinfo; import com.allen_sauer.gwt.log.client.Log; +import static com.google.common.base.Preconditions.checkNotNull; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.HasWidgets; -import org.hudsonci.maven.model.state.BuildStateDTO; -import org.hudsonci.maven.model.state.MavenProjectDTO; - import javax.inject.Inject; import javax.inject.Singleton; - +import org.hudsonci.maven.model.state.BuildStateDTO; +import org.hudsonci.maven.model.state.MavenProjectDTO; import org.hudsonci.maven.plugin.ui.gwt.buildinfo.event.BuildStateLoadedEvent; import org.hudsonci.maven.plugin.ui.gwt.buildinfo.event.BuildStateSelectedEvent; import org.hudsonci.maven.plugin.ui.gwt.buildinfo.event.ModuleSelectedEvent; import org.hudsonci.maven.plugin.ui.gwt.buildinfo.internal.ArtifactDataProvider; import org.hudsonci.maven.plugin.ui.gwt.buildinfo.internal.ModuleDataProvider; -import static com.google.common.base.Preconditions.checkNotNull; - /** * Controls initial startup and extra configuration of the application. * diff --git a/maven3-plugin/src/main/resources/org/hudsonci/maven/plugin/builder/MavenBuilderDescriptor/common.jelly b/maven3-plugin/src/main/resources/org/hudsonci/maven/plugin/builder/MavenBuilderDescriptor/common.jelly index 2bcb92c..94cf3ef 100644 --- a/maven3-plugin/src/main/resources/org/hudsonci/maven/plugin/builder/MavenBuilderDescriptor/common.jelly +++ b/maven3-plugin/src/main/resources/org/hudsonci/maven/plugin/builder/MavenBuilderDescriptor/common.jelly @@ -30,6 +30,14 @@ THE SOFTWARE. + + + + + + +