
hudson.maven.agent.PluginManagerInterceptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of maven-interceptor Show documentation
Show all versions of maven-interceptor Show documentation
Plexus module that intercepts invocations of key Maven components
so that Hudson can monitor what's going on in Maven.
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* 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 hudson.maven.agent;
import java.io.IOException;
import java.lang.reflect.Method;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.DefaultPluginManager;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.PluginConfigurationException;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.artifact.InvalidDependencyVersionException;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
import org.codehaus.plexus.component.configurator.ConfigurationListener;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.configuration.PlexusConfiguration;
/**
* Description in META-INF/plexus/components.xml makes it possible to use this instead of the default
* plugin manager.
*
* @author Kohsuke Kawaguchi
*/
public class PluginManagerInterceptor extends DefaultPluginManager {
/**
* {@link PluginManagerListener} that receives events.
* There's no way external code can connect to a running instance of
* {@link PluginManagerInterceptor}, so this cannot be made instance fields.
*/
private static PluginManagerListener listener;
/**
* {@link ComponentConfigurator} filter to intercept the mojo configuration.
*/
private ComponentConfiguratorFilter configuratorFilter;
public static void setListener(PluginManagerListener _listener) {
listener = _listener;
}
@Override
public void initialize() {
super.initialize();
container = new ContainerFilter(container) {
/**
* {@link DefaultPluginManager} uses it to load plugins and their configurators.
*
* @param name
* groupId+':'+artifactId of the plugin.
*/
public PlexusContainer getChildContainer(String name) {
PlexusContainer child = super.getChildContainer(name);
if(child==null) return null;
return new ContainerFilter(child) {
public Object lookup(String componentKey) throws ComponentLookupException {
return wrap(super.lookup(componentKey), componentKey);
}
public Object lookup(String role, String roleHint) throws ComponentLookupException {
return wrap(super.lookup(role,roleHint), role);
}
public void release(Object component) throws ComponentLifecycleException {
if(component==configuratorFilter)
super.release(configuratorFilter.core);
else
super.release(component);
}
private Object wrap(Object c, String componentKey) {
if(configuratorFilter==null)
return c; // not activated
if(c!=null && componentKey.equals(ComponentConfigurator.ROLE)) {
if(configuratorFilter.core!=null)
throw new IllegalStateException("ComponentConfigurationFilter being reused. " +
"This is a bug in Hudson. Please report that to the development team.");
configuratorFilter.core = (ComponentConfigurator)c;
c = configuratorFilter;
}
return c;
}
};
}
};
}
/**
* Intercepts the {@link Mojo} configuration and grabs some key Maven objects that are used for configuration,
* then call {@link #pre(Object, PlexusConfiguration, ExpressionEvaluator)} to provide an opportunity
* to alter the configuration.
*/
private abstract class MojoIntercepter extends ComponentConfiguratorFilter {
// these are the key objects involved in configuring a mojo
PlexusConfiguration config;
ExpressionEvaluator eval;
Mojo mojo;
MojoIntercepter() {
super(null);
// it is the caller's responsibility to set 'configuratorFilter' to null when the interception is over.
configuratorFilter = this;
}
@Override
public void configureComponent(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator, ClassRealm containerRealm, ConfigurationListener configListener) throws ComponentConfigurationException {
try {
this.config = configuration;
this.eval = expressionEvaluator;
this.mojo = (Mojo)component;
pre(component, configuration, expressionEvaluator);
super.configureComponent(component, configuration, expressionEvaluator, containerRealm, configListener);
} catch (IOException e) {
throw new ComponentConfigurationException(e);
} catch (InterruptedException e) {
// orderly abort
throw new AbortException("Execution aborted",e);
}
}
protected abstract void pre(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator) throws IOException, InterruptedException;
}
@Override
public void executeMojo(final MavenProject project, final MojoExecution mojoExecution, MavenSession session) throws ArtifactResolutionException, MojoExecutionException, MojoFailureException, ArtifactNotFoundException, InvalidDependencyVersionException, PluginManagerException, PluginConfigurationException {
class MojoIntercepterImpl extends MojoIntercepter {
@Override
protected void pre(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator) throws IOException, InterruptedException {
if(listener!=null)
// this lets preExecute a chance to modify the mojo configuration
listener.preExecute(project,mojoExecution, (Mojo)component, configuration,expressionEvaluator);
}
void callPost(Exception exception) throws IOException, InterruptedException {
if(listener!=null)
listener.postExecute(project,mojoExecution,mojo,config,eval,exception);
}
}
// prepare interception of ComponentConfigurator, so that we can get the final PlexusConfiguration object
// representing the configuration before Mojo object is filled with that.
MojoIntercepterImpl interceptor = new MojoIntercepterImpl();
try {
try {
// inside the executeMojo but before the mojo actually gets executed,
// we should be able to trap the mojo configuration.
super.executeMojo(project, mojoExecution, session);
interceptor.callPost(null);
} catch (MojoExecutionException e) {
interceptor.callPost(e);
throw e;
} catch (MojoFailureException e) {
interceptor.callPost(e);
throw e;
}
} catch (InterruptedException e) {
// orderly abort
throw new AbortException("Execution aborted",e);
} catch (IOException e) {
// we can't use two-args constructor. see the comment from steffeng on Mon Sep 14 20:22:32 HUDSON-2373.
throw (PluginManagerException)new PluginManagerException(e.getMessage()).initCause(e);
} finally {
configuratorFilter = null;
}
}
/**
* Intercepts the creation of {@link MavenReport}, to intercept
* the execution of it. This is used to discover the execution
* of certain reporting.
*/
@Override
public MavenReport getReport(MavenProject project, final MojoExecution mojoExecution, MavenSession session) throws ArtifactNotFoundException, PluginConfigurationException, PluginManagerException, ArtifactResolutionException {
// intercept the MavenReport object creation.
final MojoIntercepter interceptor = new MojoIntercepter() {
protected void pre(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator) throws IOException, InterruptedException {
}
};
MavenReport r;
try {
r = super.getReport(project, mojoExecution, session);
} finally {
configuratorFilter = null;
}
if(r==null) return null;
r = new ComponentInterceptor() {
/**
* Intercepts the execution of methods on {@link MavenReport}.
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("generate")) {
Object r = super.invoke(proxy, method, args);
// on successul execution of the generate method, raise an event
try {
listener.onReportGenerated(delegate,mojoExecution,interceptor.config,interceptor.eval);
} catch (InterruptedException e) {
// orderly abort
throw new AbortException("Execution aborted",e);
} catch (IOException e) {
throw new MavenReportException(e.getMessage(),e);
}
return r;
}
// delegate by default
return super.invoke(proxy, method, args);
}
}.wrap(r);
return r;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy