change path before renaming project to a more traditionnal name.



git-svn-id: https://svn.apache.org/repos/asf/maven/shared/trunk@1092789 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..bcc5720
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,289 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.maven.shared</groupId>
+    <artifactId>maven-shared-components</artifactId>
+    <version>16</version>
+    <relativePath>../maven-shared-components/pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.apache.maven.reporting</groupId>
+  <artifactId>maven-reporting-exec</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <name>Maven Reporting Executor</name>
+  <description>Classes to manage report plugin executions with Maven 3.</description>
+
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/maven/shared/trunk/maven-reporting-exec</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/shared/trunk/maven-reporting-exec</developerConnection>
+    <url>http://svn.apache.org/viewvc/maven/shared/trunk/maven-reporting-exec</url>
+  </scm>
+  <!--issueManagement>
+    <system>jira</system>
+    <url>http://jira.codehaus.org/browse/MSHARED/component/13274</url>
+  </issueManagement-->
+
+  <properties>
+    <mavenVersion>3.0</mavenVersion>
+    <plexusVersion>1.5.4</plexusVersion>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.reporting</groupId>
+      <artifactId>maven-reporting-api</artifactId>
+      <version>3.0</version>
+    </dependency>
+
+    <!-- Maven -->
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+      <version>${mavenVersion}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+      <version>${mavenVersion}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-model</artifactId>
+      <version>${mavenVersion}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>${mavenVersion}</version>
+    </dependency>
+
+    <!-- test -->
+    <dependency>
+      <groupId>org.apache.maven.plugin-testing</groupId>
+      <artifactId>maven-plugin-testing-harness</artifactId>
+      <version>2.0-alpha-1</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-container-default</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-compat</artifactId>
+      <version>${mavenVersion}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-embedder</artifactId>
+      <version>${mavenVersion}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-aether-provider</artifactId>
+      <version>${mavenVersion}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.sonatype.aether</groupId>
+      <artifactId>aether-connector-wagon</artifactId>
+      <version>1.7</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-container-default</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-http-lightweight</artifactId>
+      <version>1.0-beta-6</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-container-default</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>r07</version>
+      <scope>test</scope>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.apache.maven.doxia</groupId>
+      <artifactId>doxia-site-renderer</artifactId>
+      <version>1.1.4</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-container-default</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.velocity</groupId>
+          <artifactId>velocity</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.sonatype.sisu</groupId>
+      <artifactId>sisu-inject-plexus</artifactId>
+      <version>2.2.0</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.sonatype.sisu</groupId>
+      <artifactId>sisu-inject-bean</artifactId>
+      <version>2.2.0</version>
+      <scope>provided</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.sonatype.sisu</groupId>
+          <artifactId>sisu-guice</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.sonatype.sisu</groupId>
+      <artifactId>sisu-guice</artifactId>
+      <version>3.0.1</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-velocity</artifactId>
+      <version>1.1.8</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-container-default</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.velocity</groupId>
+      <artifactId>velocity</artifactId>
+      <version>1.5</version>
+    </dependency>
+
+    <dependency>
+      <groupId>velocity</groupId>
+      <artifactId>velocity</artifactId>
+      <version>1.5</version>
+    </dependency>
+
+
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <configuration>
+            <source>1.5</source>
+            <target>1.5</target>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.8</version>
+        <configuration>
+          <systemPropertyVariables>
+            <localRepository>${settings.localRepository}</localRepository>
+            <mavenHome>${env.M2_HOME}</mavenHome>
+          </systemPropertyVariables>
+          <!--
+          <forkMode>none</forkMode>
+          -->
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-component-metadata</artifactId>
+        <version>1.5.5</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>generate-metadata</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>1.0</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <id>ensure-no-container-api</id>
+            <configuration>
+              <rules>
+                <bannedDependencies>
+                  <excludes>
+                    <exclude>org.codehaus.plexus:plexus-component-api</exclude>
+                    <exclude>org.codehaus.plexus:plexus-container-default</exclude>
+                  </excludes>
+                  <message>The new containers are not supported. You probably added a dependency that is missing the exclusions.</message>
+                </bannedDependencies>
+              </rules>
+              <fail>true</fail>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/main/java/org/apache/maven/reporting/exec/DefaultMavenReportExecutor.java b/src/main/java/org/apache/maven/reporting/exec/DefaultMavenReportExecutor.java
new file mode 100644
index 0000000..4c472e3
--- /dev/null
+++ b/src/main/java/org/apache/maven/reporting/exec/DefaultMavenReportExecutor.java
@@ -0,0 +1,584 @@
+package org.apache.maven.reporting.exec;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import org.apache.maven.artifact.repository.DefaultRepositoryRequest;
+import org.apache.maven.artifact.repository.RepositoryRequest;
+import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.LifecycleExecutor;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.plugin.MavenPluginManager;
+import org.apache.maven.plugin.Mojo;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoNotFoundException;
+import org.apache.maven.plugin.PluginConfigurationException;
+import org.apache.maven.plugin.PluginContainerException;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.version.DefaultPluginVersionRequest;
+import org.apache.maven.plugin.version.PluginVersionRequest;
+import org.apache.maven.plugin.version.PluginVersionResolutionException;
+import org.apache.maven.plugin.version.PluginVersionResolver;
+import org.apache.maven.plugin.version.PluginVersionResult;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.reporting.MavenReport;
+import org.codehaus.classworlds.ClassRealm;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.codehaus.plexus.logging.Logger;
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomUtils;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.util.filter.ExclusionsDependencyFilter;
+
+/**
+ * <p>
+ *   This component will build some {@link MavenReportExecution} from {@link MavenReportExecutorRequest}.
+ *   If a {@link MavenReport} need to fork a lifecycle, this fork is executed here. 
+ *   It will ask the core to get some informations in order to correctly setup {@link MavenReport}.
+ * </p>
+ * <p>
+ *   <b>Note</b> if no version is defined in the report plugin the version will be search 
+ *   with method {@link #getPluginVersion(ReportPlugin, RepositoryRequest, MavenReportExecutorRequest)}
+ *   Steps to find a plugin version stop after each step if a non <code>null</code> value has been found:
+ *   <ul>
+ *     <li>use the one defined in the reportPlugin configuration</li>
+ *     <li>search similar (same groupId and artifactId) mojo in the build/plugins section of the pom</li>
+ *     <li>search similar (same groupId and artifactId) mojo in the build/pluginManagement section of the pom</li>
+ *     <li>ask {@link PluginVersionResolver} to get a version and display a warning as it's not a recommended use</li>  
+ *   </ul>
+ * </p>
+ * <p>
+ *   Following steps are done
+ *   <ul>
+ *     <li>get {@link PluginDescriptor} from the {@link MavenPluginManager#getPluginDescriptor(Plugin, RepositoryRequest)}</li>
+ *     <li>setup a {@link ClassLoader} with the Mojo Site plugin {@link ClassLoader} as parent for the report execution. 
+ *       You must note some classes are imported from the current Site Mojo {@link ClassRealm} see {@link #IMPORTS}.
+ *       The artifact resolution excludes the following artifacts (with using an {@link ExclusionSetFilter}: 
+ *       doxia-site-renderer, doxia-sink-api, maven-reporting-api.
+ *       done using {@link MavenPluginManager#setupPluginRealm(PluginDescriptor, org.apache.maven.execution.MavenSession, ClassLoader, List, org.apache.maven.artifact.resolver.filter.ArtifactFilter)}
+ *     </li>
+ *     <li>
+ *       setup the mojo using {@link MavenPluginManager#getConfiguredMojo(Class, org.apache.maven.execution.MavenSession, MojoExecution)}
+ *     </li>
+ *     <li>
+ *       verify with {@link LifecycleExecutor#calculateForkedExecutions(MojoExecution, org.apache.maven.execution.MavenSession)}
+ *       if any forked execution is needed: if yes executes the forked execution here
+ *     </li>
+ *   </ul>
+ * </p>
+ * @author Olivier Lamy
+ * @since 3.0-beta-1
+ */
+@Component( role = MavenReportExecutor.class )
+public class DefaultMavenReportExecutor
+    implements MavenReportExecutor
+{
+    @Requirement
+    private Logger logger;
+
+    @Requirement
+    protected MavenPluginManager mavenPluginManager;
+
+    @Requirement
+    protected LifecycleExecutor lifecycleExecutor;
+
+    @Requirement
+    protected PluginVersionResolver pluginVersionResolver;
+
+    private static final List<String> IMPORTS = Arrays.asList( "org.apache.maven.reporting.MavenReport",
+                                                               "org.apache.maven.reporting.MavenMultiPageReport",
+                                                               "org.apache.maven.doxia.siterenderer.Renderer",
+                                                               "org.apache.maven.doxia.sink.SinkFactory",
+                                                               "org.codehaus.doxia.sink.Sink",
+                                                               "org.apache.maven.doxia.sink.Sink",
+                                                               "org.apache.maven.doxia.sink.SinkEventAttributes" );
+
+    private static final ExclusionsDependencyFilter EXCLUDES =
+        new ExclusionsDependencyFilter( Arrays.asList( "doxia-site-renderer", "doxia-sink-api", "maven-reporting-api" ) );
+
+    public List<MavenReportExecution> buildMavenReports( MavenReportExecutorRequest mavenReportExecutorRequest )
+        throws MojoExecutionException
+    {
+        if ( mavenReportExecutorRequest.getReportPlugins() == null )
+        {
+            return Collections.emptyList();
+        }
+        getLog().debug( "DefaultMavenReportExecutor.buildMavenReports()" );
+
+        List<String> reportPluginKeys = new ArrayList<String>();
+        List<MavenReportExecution> reports = new ArrayList<MavenReportExecution>();
+
+        String pluginKey = "";
+        try
+        {
+            for ( ReportPlugin reportPlugin : mavenReportExecutorRequest.getReportPlugins() )
+            {
+                pluginKey = reportPlugin.getGroupId() + ":" + reportPlugin.getArtifactId();
+
+                buildReportPlugin( mavenReportExecutorRequest, reportPlugin, reportPluginKeys, reports );
+            }
+            return reports;
+        }
+        catch ( Exception e )
+        {
+            throw new MojoExecutionException( "failed to get report for " + pluginKey, e );
+        }
+    }
+
+    protected void buildReportPlugin( MavenReportExecutorRequest mavenReportExecutorRequest, ReportPlugin reportPlugin,
+                                      List<String> reportPluginKeys, List<MavenReportExecution> reports )
+        throws Exception
+    {
+        Plugin plugin = new Plugin();
+        plugin.setGroupId( reportPlugin.getGroupId() );
+        plugin.setArtifactId( reportPlugin.getArtifactId() );
+
+        String pluginKey = reportPlugin.getGroupId() + ":" + reportPlugin.getArtifactId();
+        if ( reportPluginKeys.contains( pluginKey ) )
+        {
+            logger.info( "plugin " + pluginKey + " will be executed more than one time" );
+        }
+        else
+        {
+            reportPluginKeys.add( pluginKey );
+        }
+
+        RepositoryRequest repositoryRequest = new DefaultRepositoryRequest();
+        repositoryRequest.setLocalRepository( mavenReportExecutorRequest.getLocalRepository() );
+        repositoryRequest.setRemoteRepositories( mavenReportExecutorRequest.getProject().getPluginArtifactRepositories() );
+
+        plugin.setVersion( getPluginVersion( reportPlugin, repositoryRequest, mavenReportExecutorRequest ) );
+
+        mergePluginToReportPlugin( mavenReportExecutorRequest, plugin, reportPlugin );
+
+        logger.info( "configuring report plugin " + plugin.getId() );
+
+        MavenSession session = mavenReportExecutorRequest.getMavenSession();
+        List<RemoteRepository> remoteRepositories = session.getCurrentProject().getRemotePluginRepositories();
+
+        PluginDescriptor pluginDescriptor =
+            mavenPluginManager.getPluginDescriptor( plugin, remoteRepositories, session.getRepositorySession() );
+
+        Map<String, PlexusConfiguration> goalsWithConfiguration = new TreeMap<String, PlexusConfiguration>();
+
+        if ( reportPlugin.getReportSets().isEmpty() && reportPlugin.getReports().isEmpty() )
+        {
+            List<MojoDescriptor> mojoDescriptors = pluginDescriptor.getMojos();
+            for ( MojoDescriptor mojoDescriptor : mojoDescriptors )
+            {
+                goalsWithConfiguration.put( mojoDescriptor.getGoal(), mojoDescriptor.getConfiguration() );
+            }
+        }
+        else
+        {
+            for ( ReportSet reportSet : reportPlugin.getReportSets() )
+            {
+                for ( String report : reportSet.getReports() )
+                {
+                    goalsWithConfiguration.put( report, reportSet.getConfiguration() );
+                }
+            }
+
+            for ( String report : reportPlugin.getReports() )
+            {
+                goalsWithConfiguration.put( report, reportPlugin.getConfiguration() );
+            }
+        }
+
+        for ( Entry<String, PlexusConfiguration> entry : goalsWithConfiguration.entrySet() )
+        {
+            MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( entry.getKey() );
+            if ( mojoDescriptor == null )
+            {
+                throw new MojoNotFoundException( entry.getKey(), pluginDescriptor );
+            }
+
+            MojoExecution mojoExecution = new MojoExecution( plugin, entry.getKey(), "report:" + entry.getKey() );
+
+            mojoExecution.setConfiguration( convert( mojoDescriptor ) );
+
+            if ( reportPlugin.getConfiguration() != null || entry.getValue() != null )
+            {
+                Xpp3Dom reportConfiguration =
+                    reportPlugin.getConfiguration() == null ? new Xpp3Dom( "fake" )
+                                    : convert( reportPlugin.getConfiguration() );
+
+                // MSITE-512 configuration from ReportSet must win
+                Xpp3Dom mergedConfigurationWithReportSet =
+                    Xpp3DomUtils.mergeXpp3Dom( convert( entry.getValue() ), reportConfiguration );
+
+                Xpp3Dom mergedConfiguration =
+                    Xpp3DomUtils.mergeXpp3Dom( mergedConfigurationWithReportSet, convert( mojoDescriptor ) );
+
+                Xpp3Dom cleanedConfiguration = new Xpp3Dom( "configuration" );
+                if ( mergedConfiguration.getChildren() != null )
+                {
+                    for ( Xpp3Dom parameter : mergedConfiguration.getChildren() )
+                    {
+                        if ( mojoDescriptor.getParameterMap().containsKey( parameter.getName() ) )
+                        {
+                            cleanedConfiguration.addChild( parameter );
+                        }
+                    }
+                }
+                if ( getLog().isDebugEnabled() )
+                {
+                    getLog().debug( "mojoExecution mergedConfiguration: " + mergedConfiguration );
+                    getLog().debug( "mojoExecution cleanedConfiguration: " + cleanedConfiguration );
+                }
+
+                mojoExecution.setConfiguration( cleanedConfiguration );
+            }
+
+            mojoExecution.setMojoDescriptor( mojoDescriptor );
+
+            mavenPluginManager.setupPluginRealm( pluginDescriptor, mavenReportExecutorRequest.getMavenSession(),
+                                                 Thread.currentThread().getContextClassLoader(), IMPORTS, EXCLUDES );
+            MavenReport mavenReport =
+                getConfiguredMavenReport( mojoExecution, pluginDescriptor, mavenReportExecutorRequest );
+
+            if ( mavenReport == null )
+            {
+                continue;
+            }
+
+            MavenReportExecution mavenReportExecution =
+                new MavenReportExecution( mojoExecution.getPlugin(), mavenReport, pluginDescriptor.getClassRealm() );
+
+            lifecycleExecutor.calculateForkedExecutions( mojoExecution, mavenReportExecutorRequest.getMavenSession() );
+
+            if ( !mojoExecution.getForkedExecutions().isEmpty() )
+            {
+                lifecycleExecutor.executeForkedExecutions( mojoExecution, mavenReportExecutorRequest.getMavenSession() );
+            }
+
+            if ( canGenerateReport( mavenReport, mojoExecution ) )
+            {
+                reports.add( mavenReportExecution );
+            }
+        }
+    }
+
+    private boolean canGenerateReport( MavenReport mavenReport, MojoExecution mojoExecution )
+    {
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+        try
+        {
+            Thread.currentThread().setContextClassLoader( mojoExecution.getMojoDescriptor().getRealm() );
+
+            return mavenReport.canGenerateReport();
+        }
+        finally
+        {
+            Thread.currentThread().setContextClassLoader( originalClassLoader );
+        } 
+    }
+
+    private MavenReport getConfiguredMavenReport( MojoExecution mojoExecution, PluginDescriptor pluginDescriptor,
+                                                  MavenReportExecutorRequest mavenReportExecutorRequest )
+        throws PluginContainerException, PluginConfigurationException
+    {
+        try
+        {
+            if ( !isMavenReport( mojoExecution, pluginDescriptor ) )
+            {
+                return null;
+            }
+
+            Mojo mojo = mavenPluginManager.getConfiguredMojo( Mojo.class,
+                                                              mavenReportExecutorRequest.getMavenSession(),
+                                                              mojoExecution );
+
+            return (MavenReport) mojo;
+        }
+        catch ( ClassCastException e )
+        {
+            getLog().warn( "skip ClassCastException " + e.getMessage() );
+            return null;
+        }
+        catch ( PluginContainerException e )
+        {
+            /**
+             * ignore old plugin which are using removed PluginRegistry
+             * [INFO] Caused by: java.lang.NoClassDefFoundError: org/apache/maven/plugin/registry/PluginRegistry
+             */
+            if ( e.getCause() != null && e.getCause() instanceof NoClassDefFoundError
+                && e.getMessage().contains( "PluginRegistry" ) )
+            {
+                getLog().warn( "skip NoClassDefFoundError with PluginRegistry " );
+                // too noisy, only in debug mode + e.getMessage() );
+                if ( getLog().isDebugEnabled() )
+                {
+                    getLog().debug( e.getMessage(), e );
+                }
+                return null;
+            }
+            throw e;
+        }
+    }
+
+    private boolean isMavenReport( MojoExecution mojoExecution, PluginDescriptor pluginDescriptor )
+    {
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+        Class<?> mojoClass;
+        Thread.currentThread().setContextClassLoader( mojoExecution.getMojoDescriptor().getRealm() );
+        try
+        {
+            mojoClass =
+                pluginDescriptor.getClassRealm().loadClass( mojoExecution.getMojoDescriptor().getImplementation() );
+        }
+        catch ( ClassNotFoundException e )
+        {
+            getLog().warn( "skip ClassNotFoundException mojoExecution.goal '" + mojoExecution.getGoal() + "': "
+                               + e.getMessage(), e );
+            return false;
+        }
+        finally
+        {
+            Thread.currentThread().setContextClassLoader( originalClassLoader );
+        }       
+
+        try
+        {
+            Thread.currentThread().setContextClassLoader( mojoExecution.getMojoDescriptor().getRealm() );
+            MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( mojoExecution.getGoal() );
+
+            boolean isMavenReport = MavenReport.class.isAssignableFrom( mojoClass );
+
+            if ( getLog().isDebugEnabled() )
+            {
+                if ( mojoDescriptor != null && mojoDescriptor.getImplementationClass() != null )
+                {
+                    getLog().debug( "class " + mojoDescriptor.getImplementationClass().getName() + " isMavenReport: "
+                                        + isMavenReport );
+                }
+
+                if ( !isMavenReport )
+                {
+                    getLog().debug( "skip non MavenReport " + mojoExecution.getMojoDescriptor().getId() );
+                }
+            }
+
+            return isMavenReport;
+        }
+        catch ( LinkageError e )
+        {
+            getLog().warn( "skip LinkageError mojoExecution.goal '" + mojoExecution.getGoal() + "': " + e.getMessage(),
+                           e );
+            return false;
+        }
+        finally
+        {
+            Thread.currentThread().setContextClassLoader( originalClassLoader );
+        }
+    }
+
+    private Xpp3Dom convert( MojoDescriptor mojoDescriptor )
+    {
+        PlexusConfiguration config = mojoDescriptor.getMojoConfiguration();
+        return ( config != null ) ? convert( config ) : new Xpp3Dom( "configuration" );
+    }
+
+    private Xpp3Dom convert( PlexusConfiguration config )
+    {
+        if ( config == null )
+        {
+            return null;
+        }
+
+        Xpp3Dom dom = new Xpp3Dom( config.getName() );
+        dom.setValue( config.getValue( null ) );
+
+        for ( String attrib : config.getAttributeNames() )
+        {
+            dom.setAttribute( attrib, config.getAttribute( attrib, null ) );
+        }
+
+        for ( int n = config.getChildCount(), i = 0; i < n; i++ )
+        {
+            dom.addChild( convert( config.getChild( i ) ) );
+        }
+
+        return dom;
+    }
+
+    private Logger getLog()
+    {
+        return logger;
+    }
+
+    /**
+     * Resolve report plugin version. 
+     * Steps to find a plugin version stop after each step if a non <code>null</code> value has been found:
+     * <ol>
+     *   <li>use the one defined in the reportPlugin configuration</li>
+     *   <li>search similar (same groupId and artifactId) mojo in the build/plugins section of the pom</li>
+     *   <li>search similar (same groupId and artifactId) mojo in the build/pluginManagement section of the pom</li>
+     *   <li>ask {@link PluginVersionResolver} to get a version and display a warning as it's not a recommended use</li>  
+     * </ol>
+     *
+     * @param reportPlugin the report plugin to resolve the version
+     * @param repositoryRequest TODO: unused, to be removed?
+     * @param mavenReportExecutorRequest the current report execution context
+     * @return the report plugin version
+     * @throws PluginVersionResolutionException
+     */
+    protected String getPluginVersion( ReportPlugin reportPlugin, RepositoryRequest repositoryRequest,
+                                       MavenReportExecutorRequest mavenReportExecutorRequest )
+        throws PluginVersionResolutionException
+    {
+        String reportPluginKey = reportPlugin.getGroupId() + ':' + reportPlugin.getArtifactId();
+        if ( getLog().isDebugEnabled() )
+        {
+            getLog().debug( "resolving version for " + reportPluginKey );
+        }
+
+        // look for version defined in the reportPlugin configuration
+        if ( reportPlugin.getVersion() != null )
+        {
+            if ( getLog().isDebugEnabled() )
+            {
+                logger.debug( "resolved " + reportPluginKey + " version from the reporting.plugins section: "
+                    + reportPlugin.getVersion() );
+            }
+            return reportPlugin.getVersion();
+        }
+
+        MavenProject project = mavenReportExecutorRequest.getProject();
+
+        // search in the build section
+        if ( project.getBuild() != null )
+        {
+            Plugin plugin = find( reportPlugin, project.getBuild().getPlugins() );
+
+            if ( plugin != null && plugin.getVersion() != null )
+            {
+                if ( getLog().isDebugEnabled() )
+                {
+                    logger.debug( "resolved " + reportPluginKey + " version from the build.plugins section: "
+                        + plugin.getVersion() );
+                }
+                return plugin.getVersion();
+            }
+        }
+
+        // search in pluginManagement section
+        if ( project.getBuild() != null && project.getBuild().getPluginManagement() != null )
+        {
+            Plugin plugin = find( reportPlugin, project.getBuild().getPluginManagement().getPlugins() );
+
+            if ( plugin != null && plugin.getVersion() != null )
+            {
+                if ( getLog().isDebugEnabled() )
+                {
+                    logger.debug( "resolved " + reportPluginKey
+                        + " version from the build.pluginManagement.plugins section: " + plugin.getVersion() );
+                }
+                return plugin.getVersion();
+            }
+        }
+
+
+        logger.warn( "Report plugin " + reportPluginKey + " has an empty version." );
+        logger.warn( "" );
+        logger.warn( "It is highly recommended to fix these problems"
+            + " because they threaten the stability of your build." );
+        logger.warn( "" );
+        logger.warn( "For this reason, future Maven versions might no"
+            + " longer support building such malformed projects." );
+
+        Plugin plugin = new Plugin();
+        plugin.setGroupId( reportPlugin.getGroupId() );
+        plugin.setArtifactId( reportPlugin.getArtifactId() );
+        
+        PluginVersionRequest pluginVersionRequest =
+            new DefaultPluginVersionRequest( plugin, mavenReportExecutorRequest.getMavenSession() );
+
+        PluginVersionResult result = pluginVersionResolver.resolve( pluginVersionRequest );
+        if ( getLog().isDebugEnabled() )
+        {
+            getLog().debug( "resolved " + reportPluginKey + " version from repository: " + result.getVersion() );
+        }
+        return result.getVersion();
+    }
+
+    /**
+     * Search similar (same groupId and artifactId) mojo as a given report plugin.
+     * 
+     * @param reportPlugin the report plugin to search for a similar mojo
+     * @param plugins the candidate mojos 
+     * @return the first similar mojo
+     */
+    private Plugin find( ReportPlugin reportPlugin, List<Plugin> plugins )
+    {
+        if ( plugins == null )
+        {
+            return null;
+        }
+        for ( Plugin plugin : plugins )
+        {
+            if ( StringUtils.equals( plugin.getArtifactId(), reportPlugin.getArtifactId() )
+                && StringUtils.equals( plugin.getGroupId(), reportPlugin.getGroupId() ) )
+            {
+                return plugin;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * TODO other stuff to merge ?
+     * <p>
+     * this method will "merge" some part of the plugin declaration existing in the build section 
+     * to the fake plugin build for report execution:
+     * <ul>
+     *   <li>dependencies</li>
+     * </ul>
+     * </p>
+     * @param mavenReportExecutorRequest
+     * @param buildPlugin
+     * @param reportPlugin
+     */
+    private void mergePluginToReportPlugin( MavenReportExecutorRequest mavenReportExecutorRequest, Plugin buildPlugin,
+                                            ReportPlugin reportPlugin )
+    {
+        Plugin configuredPlugin = find( reportPlugin, mavenReportExecutorRequest.getProject().getBuild().getPlugins() );
+        if ( configuredPlugin != null )
+        {
+            if ( !configuredPlugin.getDependencies().isEmpty() )
+            {
+                buildPlugin.getDependencies().addAll( configuredPlugin.getDependencies() );
+            }
+        }
+    }   
+}
diff --git a/src/main/java/org/apache/maven/reporting/exec/MavenReportExecution.java b/src/main/java/org/apache/maven/reporting/exec/MavenReportExecution.java
new file mode 100644
index 0000000..0debab9
--- /dev/null
+++ b/src/main/java/org/apache/maven/reporting/exec/MavenReportExecution.java
@@ -0,0 +1,95 @@
+package org.apache.maven.reporting.exec;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.model.Plugin;
+import org.apache.maven.reporting.MavenReport;
+
+/**
+ * <p>
+ *   Since maven 3 reporting plugin {@link MavenReport} are not anymore injected by maven core
+ *   This class will store all necessary information for {@link MavenReport} execution :
+ *   <ul>
+ *     <li>a build {@link MavenReport}</li>
+ *     <li>The associated {@link ClassLoader} for the Report Mojo execution</li>
+ *     <li>The {@link Plugin} associated to the {@link MavenReport}</li>
+ *   </ul> 
+ * </p>
+ * <p>
+ *   With this it's possible to execute the {@link MavenReport} generate with settings
+ *   the current {@link Thread} classLoader first with {@link #classLoader}
+ * </p>
+ * <p>
+ *   This beans will be build by {@link MavenReportExecutor}.
+ * </p>
+ * 
+ * @author Olivier Lamy
+ * @since 3.0-beta-1
+ */
+public class MavenReportExecution
+{
+    private MavenReport mavenReport;
+
+    private ClassLoader classLoader;
+
+    private Plugin plugin;
+
+    public MavenReportExecution( Plugin plugin, MavenReport mavenReport, ClassLoader classLoader )
+    {
+        this.setPlugin( plugin );
+        this.mavenReport = mavenReport;
+        this.classLoader = classLoader;
+    }
+
+    public MavenReportExecution( MavenReport mavenReport )
+    {
+        this( null, mavenReport, null );
+    }
+
+    public MavenReport getMavenReport()
+    {
+        return mavenReport;
+    }
+
+    public void setMavenReport( MavenReport mavenReport )
+    {
+        this.mavenReport = mavenReport;
+    }
+
+    public ClassLoader getClassLoader()
+    {
+        return classLoader;
+    }
+
+    public void setClassLoader( ClassLoader classLoader )
+    {
+        this.classLoader = classLoader;
+    }
+
+    public void setPlugin( Plugin plugin )
+    {
+        this.plugin = plugin;
+    }
+
+    public Plugin getPlugin()
+    {
+        return plugin;
+    }
+}
diff --git a/src/main/java/org/apache/maven/reporting/exec/MavenReportExecutor.java b/src/main/java/org/apache/maven/reporting/exec/MavenReportExecutor.java
new file mode 100644
index 0000000..9d7661e
--- /dev/null
+++ b/src/main/java/org/apache/maven/reporting/exec/MavenReportExecutor.java
@@ -0,0 +1,40 @@
+package org.apache.maven.reporting.exec;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.List;
+
+import org.apache.maven.plugin.MojoExecutionException;
+
+/**
+ *
+ * @author Olivier Lamy
+ * @since 3.0-beta-1
+ */
+public interface MavenReportExecutor
+{
+    /**
+     * @param mavenReportExecutorRequest
+     * @return
+     * @throws MojoExecutionException
+     */
+    List<MavenReportExecution> buildMavenReports( MavenReportExecutorRequest mavenReportExecutorRequest )
+        throws MojoExecutionException;
+}
diff --git a/src/main/java/org/apache/maven/reporting/exec/MavenReportExecutorRequest.java b/src/main/java/org/apache/maven/reporting/exec/MavenReportExecutorRequest.java
new file mode 100644
index 0000000..3d22344
--- /dev/null
+++ b/src/main/java/org/apache/maven/reporting/exec/MavenReportExecutorRequest.java
@@ -0,0 +1,86 @@
+package org.apache.maven.reporting.exec;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.project.MavenProject;
+
+/**
+ * <p>
+ *   Bean which contains necessay informations for build {@link MavenReportExecution} 
+ *   with {@link MavenReportExecutor}.
+ *   The goal is to store some informations regarding the current maven execution.
+ * </p>
+ * @author <a href="mailto:olamy@apache.org">olamy</a>
+ * @since 3.0-beta-1
+ * @version $Id$
+ */
+public class MavenReportExecutorRequest
+{
+    private ArtifactRepository localRepository;
+
+    private MavenSession mavenSession;
+
+    private MavenProject project;
+
+    private ReportPlugin[] reportPlugins;
+
+    public ArtifactRepository getLocalRepository()
+    {
+        return localRepository;
+    }
+
+    public void setLocalRepository( ArtifactRepository localRepository )
+    {
+        this.localRepository = localRepository;
+    }
+
+    public MavenSession getMavenSession()
+    {
+        return mavenSession;
+    }
+
+    public void setMavenSession( MavenSession mavenSession )
+    {
+        this.mavenSession = mavenSession;
+    }
+
+    public MavenProject getProject()
+    {
+        return project;
+    }
+
+    public void setProject( MavenProject project )
+    {
+        this.project = project;
+    }
+
+    public ReportPlugin[] getReportPlugins()
+    {
+        return reportPlugins;
+    }
+
+    public void setReportPlugins( ReportPlugin[] reportPlugins )
+    {
+        this.reportPlugins = reportPlugins;
+    }
+
+}
diff --git a/src/main/java/org/apache/maven/reporting/exec/ReportPlugin.java b/src/main/java/org/apache/maven/reporting/exec/ReportPlugin.java
new file mode 100644
index 0000000..a0f2832
--- /dev/null
+++ b/src/main/java/org/apache/maven/reporting/exec/ReportPlugin.java
@@ -0,0 +1,118 @@
+package org.apache.maven.reporting.exec;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.maven.model.Plugin;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+
+/**
+ * <p>
+ * Represents a reporting plugin and its executions. It basically contains similar informations
+ * as a {@link Plugin} but in order to decoupled reporting stuff from core some values are copied.
+ * </p>
+ * @since 3.0-beta-1
+ */
+public class ReportPlugin
+{
+
+    private String groupId = "org.apache.maven.plugins";
+
+    private String artifactId;
+
+    private String version;
+
+    private PlexusConfiguration configuration;
+
+    private List<ReportSet> reportSets;
+    
+    private List<String> reports;
+
+    public String getGroupId()
+    {
+        return this.groupId;
+    }
+
+    public void setGroupId( String groupId )
+    {
+        this.groupId = groupId;
+    }
+
+    public String getArtifactId()
+    {
+        return this.artifactId;
+    }
+
+    public void setArtifactId( String artifactId )
+    {
+        this.artifactId = artifactId;
+    }
+
+    public String getVersion()
+    {
+        return this.version;
+    }
+
+    public void setVersion( String version )
+    {
+        this.version = version;
+    }
+
+    public PlexusConfiguration getConfiguration()
+    {
+        return this.configuration;
+    }
+
+    public void setConfiguration( PlexusConfiguration configuration )
+    {
+        this.configuration = configuration;
+    }
+
+    public List<ReportSet> getReportSets()
+    {
+        if ( this.reportSets == null )
+        {
+            this.reportSets = new ArrayList<ReportSet>();
+        }
+
+        return this.reportSets;
+    }
+
+    public void setReportSets( List<ReportSet> reportSets )
+    {
+        this.reportSets = reportSets;
+    }
+
+    public List<String> getReports()
+    {
+        return reports == null ? Collections.<String>emptyList() : reports;
+    }
+
+    public void setReports( List<String> reports )
+    {
+        this.reports = reports;
+    }
+
+    
+
+}
diff --git a/src/main/java/org/apache/maven/reporting/exec/ReportSet.java b/src/main/java/org/apache/maven/reporting/exec/ReportSet.java
new file mode 100644
index 0000000..d7fa229
--- /dev/null
+++ b/src/main/java/org/apache/maven/reporting/exec/ReportSet.java
@@ -0,0 +1,81 @@
+package org.apache.maven.reporting.exec;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+
+/**
+ * Represents a set of reports and configuration to be used to generate them.
+ * @since 3.0-beta-1
+ */
+public class ReportSet
+{
+
+    private String id = "default";
+
+    private PlexusConfiguration configuration;
+
+    private List<String> reports;
+
+    public String getId()
+    {
+        return this.id;
+    }
+
+    public void setId( String id )
+    {
+        this.id = id;
+    }
+
+    public PlexusConfiguration getConfiguration()
+    {
+        return this.configuration;
+    }
+
+    public void setConfiguration( PlexusConfiguration configuration )
+    {
+        this.configuration = configuration;
+    }
+
+    public List<String> getReports()
+    {
+        if ( this.reports == null )
+        {
+            this.reports = new ArrayList<String>();
+        }
+
+        return this.reports;
+    }
+
+    public void setReports( List<String> reports )
+    {
+        this.reports = reports;
+    }
+
+    @Override
+    public String toString()
+    {
+        return getId();
+    }
+
+}
diff --git a/src/test/java/org/apache/maven/reporting/exec/TestDefaultMavenReportExecutor.java b/src/test/java/org/apache/maven/reporting/exec/TestDefaultMavenReportExecutor.java
new file mode 100644
index 0000000..0e97ea1
--- /dev/null
+++ b/src/test/java/org/apache/maven/reporting/exec/TestDefaultMavenReportExecutor.java
@@ -0,0 +1,292 @@
+package org.apache.maven.reporting.exec;
+
+import com.google.common.collect.Lists;
+import org.apache.maven.DefaultMaven;
+import org.apache.maven.Maven;
+import org.apache.maven.RepositoryUtils;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.cli.MavenCli;
+import org.apache.maven.execution.DefaultMavenExecutionRequest;
+import org.apache.maven.execution.DefaultMavenExecutionResult;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenExecutionRequestPopulator;
+import org.apache.maven.execution.MavenExecutionResult;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Build;
+import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.repository.RepositorySystem;
+import org.apache.maven.settings.Settings;
+import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
+import org.apache.maven.settings.building.SettingsBuilder;
+import org.apache.maven.settings.building.SettingsBuildingException;
+import org.apache.maven.settings.building.SettingsBuildingRequest;
+import org.codehaus.plexus.PlexusTestCase;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.logging.Logger;
+import org.sonatype.aether.RepositorySystemSession;
+import org.sonatype.aether.artifact.Artifact;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.repository.WorkspaceReader;
+import org.sonatype.aether.repository.WorkspaceRepository;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Olivier Lamy
+ */
+public class TestDefaultMavenReportExecutor
+    extends PlexusTestCase
+{
+
+    MavenExecutionRequest request = null;
+
+    ArtifactRepository localArtifactRepository;
+
+    public void testSimpleLookup()
+        throws Exception
+    {
+        MavenReportExecutor mavenReportExecutor = lookup( MavenReportExecutor.class );
+        assertNotNull( mavenReportExecutor );
+    }
+
+    public void testSimpleBuildReports()
+        throws Exception
+    {
+        ClassLoader orig = Thread.currentThread().getContextClassLoader();
+        ClassRealm realm = getContainer().getContainerRealm();
+        System.out.println( "realm " + Arrays.asList( realm.getURLs() ) );
+        Thread.currentThread().setContextClassLoader( realm );
+        try
+        {
+            MavenReportExecutorRequest mavenReportExecutorRequest = new MavenReportExecutorRequest();
+
+            mavenReportExecutorRequest.setLocalRepository( getLocalArtifactRepository() );
+
+            MavenProject mavenProject = getMavenProject();
+
+            mavenReportExecutorRequest.setProject( mavenProject );
+
+            MavenSession mavenSession = getMavenSession( getLocalArtifactRepository(), mavenProject );
+            mavenSession.setCurrentProject( mavenProject );
+            mavenSession.setProjects( Lists.<MavenProject>newArrayList( mavenProject ) );
+            mavenReportExecutorRequest.setMavenSession( mavenSession );
+
+            ReportPlugin reportPlugin = new ReportPlugin();
+            reportPlugin.setGroupId( "org.apache.maven.plugins" );
+            reportPlugin.setArtifactId( "maven-javadoc-plugin" );
+            reportPlugin.setVersion( "2.7" );
+
+            ReportSet reportSet = new ReportSet();
+            reportSet.getReports().add( "javadoc" );
+            reportSet.getReports().add( "test-javadoc" );
+            reportPlugin.getReportSets().add( reportSet );
+
+            List<ReportPlugin> reportPlugins = Lists.newArrayList( reportPlugin );
+
+            mavenReportExecutorRequest.setReportPlugins( reportPlugins.toArray( new ReportPlugin[1] ) );
+
+            MavenReportExecutor mavenReportExecutor = lookup( MavenReportExecutor.class );
+
+            List<MavenReportExecution> mavenReportExecutions =
+                mavenReportExecutor.buildMavenReports( mavenReportExecutorRequest );
+
+            assertNotNull( mavenReportExecutions );
+            assertEquals( 2, mavenReportExecutions.size() );
+            assertEquals( "apidocs/index", mavenReportExecutions.get( 0 ).getMavenReport().getOutputName() );
+            assertEquals( "testapidocs/index", mavenReportExecutions.get( 1 ).getMavenReport().getOutputName() );
+        }
+        finally
+        {
+            Thread.currentThread().setContextClassLoader( orig );
+        }
+    }
+
+    protected MavenSession getMavenSession( ArtifactRepository localRepository, final MavenProject mavenProject )
+        throws Exception
+    {
+        request = new DefaultMavenExecutionRequest();
+        request.setLocalRepository( localRepository );
+
+        request.setWorkspaceReader( new WorkspaceReader()
+        {
+            public WorkspaceRepository getRepository()
+            {
+                return new WorkspaceRepository();
+            }
+
+            public File findArtifact( Artifact artifact )
+            {
+                return null;
+            }
+
+            public List<String> findVersions( Artifact artifact )
+            {
+                return Collections.emptyList();
+            }
+        } );
+        final Settings settings = getSettings();
+
+        getContainer().lookup( MavenExecutionRequestPopulator.class ).populateFromSettings( request, settings );
+
+        getContainer().lookup( MavenExecutionRequestPopulator.class ).populateDefaults( request );
+
+        request.setLocalRepository( getLocalArtifactRepository() );
+        request.setLocalRepositoryPath( getLocalArtifactRepository().getBasedir() );
+        request.setCacheNotFound( false );
+
+        request.setLoggingLevel( MavenExecutionRequest.LOGGING_LEVEL_DEBUG );
+        getContainer().lookup( Logger.class ).setThreshold( 0 );
+
+        request.setSystemProperties( System.getProperties() );
+
+        MavenExecutionResult result = new DefaultMavenExecutionResult();
+
+        RepositorySystemSession repositorySystemSession = buildRepositorySystemSession( request );
+
+        MavenSession mavenSession = new MavenSession( getContainer(), repositorySystemSession, request, result )
+        {
+            @Override
+            public MavenProject getTopLevelProject()
+            {
+                return mavenProject;
+            }
+
+            @Override
+            public Settings getSettings()
+            {
+                return settings;
+            }
+
+            @Override
+            public List<MavenProject> getProjects()
+            {
+                return Lists.newArrayList( mavenProject );
+            }
+
+            @Override
+            public MavenProject getCurrentProject()
+            {
+                return mavenProject;
+            }
+
+        };
+        return mavenSession;
+    }
+
+    private ArtifactRepository getLocalArtifactRepository()
+        throws Exception
+    {
+        if ( localArtifactRepository != null )
+        {
+            return localArtifactRepository;
+        }
+        String localRepoPath =
+            System.getProperty( "localRepository", MavenCli.userMavenConfigurationHome.getPath() + "/repository" );
+
+        localArtifactRepository = lookup( RepositorySystem.class ).createLocalRepository( new File( localRepoPath ) );
+        return localArtifactRepository;
+    }
+
+    public Settings getSettings()
+        throws ComponentLookupException, SettingsBuildingException
+    {
+
+        SettingsBuildingRequest settingsBuildingRequest = new DefaultSettingsBuildingRequest();
+
+        settingsBuildingRequest.setGlobalSettingsFile( MavenCli.DEFAULT_GLOBAL_SETTINGS_FILE );
+
+        settingsBuildingRequest.setUserSettingsFile( MavenCli.DEFAULT_USER_SETTINGS_FILE );
+
+        settingsBuildingRequest.getSystemProperties().putAll( System.getProperties() );
+
+        Settings settings =
+            getContainer().lookup( SettingsBuilder.class ).build( settingsBuildingRequest ).getEffectiveSettings();
+
+        return settings;
+
+    }
+
+    protected MavenProject getMavenProject()
+    {
+        MavenProjectStub mavenProjectStub = new MavenProjectStub()
+        {
+            @Override
+            public List<RemoteRepository> getRemotePluginRepositories()
+            {
+                if ( super.getRemotePluginRepositories() == null )
+                {
+                    return RepositoryUtils.toRepos( request.getRemoteRepositories() );
+                }
+                return super.getRemotePluginRepositories();
+            }
+
+            @Override
+            public List getRemoteArtifactRepositories()
+            {
+                if ( super.getRemotePluginRepositories() == null )
+                {
+                    return RepositoryUtils.toRepos( request.getRemoteRepositories() );
+                }
+                return super.getRemotePluginRepositories();
+            }
+
+            @Override
+            public String getName()
+            {
+                return "foo";
+            }
+
+            @Override
+            public String getVersion()
+            {
+                return "1.0-SNAPSHOT";
+            }
+
+            @Override
+            public boolean isExecutionRoot()
+            {
+                return true;
+            }
+
+            @Override
+            public List getCompileSourceRoots()
+            {
+                return Lists.newArrayList( "src/main/java" );
+            }
+
+            @Override
+            public List getTestCompileSourceRoots()
+            {
+                return Lists.newArrayList( "src/test/java" );
+            }
+        };
+
+        mavenProjectStub.setPackaging( "jar" );
+
+        Build build = new Build();
+
+        build.setOutputDirectory( "target" );
+
+        build.setSourceDirectory( "src/main/java" );
+
+        build.setTestSourceDirectory( "src/test/java" );
+
+        mavenProjectStub.setBuild( build );
+
+        return mavenProjectStub;
+    }
+
+    private RepositorySystemSession buildRepositorySystemSession( MavenExecutionRequest request )
+        throws ComponentLookupException
+    {
+        DefaultMaven defaultMaven = (DefaultMaven) getContainer().lookup( Maven.class );
+
+        return defaultMaven.newRepositorySession( request );
+    }
+
+}