package com.atlassian.maven.plugins.amps;

import java.io.File;
import java.lang.reflect.Method;
import java.util.List;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.ProjectBuilderConfiguration;
import org.jfrog.maven.annomojo.annotations.MojoGoal;
import org.jfrog.maven.annomojo.annotations.MojoParameter;
import org.jfrog.maven.annomojo.annotations.MojoRequiresProject;

import static java.util.Collections.singletonList;

/**
 * Run the webapp without a plugin project
 */
@MojoGoal ("run-standalone")
@MojoRequiresProject (false)
public class RunStandaloneMojo extends AbstractProductHandlerMojo
{
    private final String
        GROUP_ID = "com.atlassian.amps",
        ARTIFACT_ID = "standalone";

    @MojoParameter (expression = "${component.org.apache.maven.project.MavenProjectBuilder}", required = true, readonly = true)
    private MavenProjectBuilder projectBuilder;

    @SuppressWarnings("unchecked")
    protected void doExecute() throws MojoExecutionException, MojoFailureException
    {
        final String version = getPluginInformation().getVersion();
        final Artifact artifact = artifactFactory.createProjectArtifact(GROUP_ID, ARTIFACT_ID, version);
        try
        {
            // overall goal here is to create a new MavenContext / MavenGoals for the standalone project
            final MavenContext oldContext = getMavenContext();

            // construct new project for new context
            final MavenProject
                oldProject = oldContext.getProject(),
                newProject = projectBuilder.buildFromRepository(artifact, repositories, localRepository);

            // horrible hack #1: buildFromRepository() doesn't actually set the project's remote repositories
            newProject.setRemoteArtifactRepositories(oldProject.getRemoteArtifactRepositories());
            newProject.setPluginArtifactRepositories(oldProject.getPluginArtifactRepositories());

            // horrible hack #2: we need to modify the session to use the new project as its reactor
            final List<MavenProject> newReactor = singletonList(newProject);
            final MavenSession
                oldSession = oldContext.getSession(),
                newSession = new MavenSession(
                    oldSession.getContainer(),
                    oldSession.getSettings(),
                    oldSession.getLocalRepository(),
                    oldSession.getEventDispatcher(),
                    new ReactorManager(newReactor),
                    oldSession.getGoals(),
                    oldSession.getExecutionRootDirectory(),
                    oldSession.getExecutionProperties(),
                    oldSession.getUserProperties(),
                    oldSession.getStartTime()
                );

            // horrible hack #3: we need to create a base directory from scratch, and convince the project to like it
            final String baseDir = System.getProperty("user.dir") + "/amps-standalone/";
            newProject.setFile(new File(baseDir, "pom.xml"));

            ProjectBuilderConfiguration projectBuilderConfiguration;

            /**
             * newSession.getProjectBuilderConfiguration() works at runtime with Maven 2 but isn't
             * available at compile time when we build with Maven 3 artifacts.
             */
            try
            {
                Method m = MavenSession.class.getMethod("getProjectBuilderConfiguration");
                projectBuilderConfiguration = (ProjectBuilderConfiguration) m.invoke(newSession);
            }
            catch (NoSuchMethodException e)
            {
                throw new MojoExecutionException("Maven 3 is not supported for run-standalone", e);
            }

            projectBuilder.calculateConcreteState(newProject, projectBuilderConfiguration);

            // finally, execute run goal against standalone project
            final MavenContext newContext = oldContext.with(
                newProject,
                newReactor,
                newSession);
            new MavenGoals(newContext).executeAmpsRecursively(version, "run");
        }
        catch (Exception e)
        {
            throw new MojoExecutionException(e.getMessage(), e);
        }
    }
}

@@ -57,16 +57,68 @@
 o.File;%0A
+import java.lang.reflect.InvocationTargetException;%0A
 import j
@@ -3483,26 +3483,10 @@
 tion
-;%0A%0A            /**
+ =
 %0A   
@@ -3499,21 +3499,15 @@
     
-* newSession.
+       
 getP
@@ -3536,161 +3536,288 @@
 tion
-() works at runtime with Maven 2 but isn't%0A             * available at compile time when we build with Maven 3 artifacts.%0A             */%0A            try
+FromMavenSession(newSession);%0A%0A            projectBuilder.calculateConcreteState(newProject, projectBuilderConfiguration);%0A%0A            // finally, execute run goal against standalone project%0A            final MavenContext newContext = oldContext.with(%0A                newProject,
 %0A   
@@ -3829,196 +3829,129 @@
     
-%7B%0A
     
-            Method m = MavenSession.class.getMethod(%22getProjectBuilderConfiguration%22);%0A                projectBuilderConfiguration = (ProjectBuilderConfiguration) m.invoke(newSession
+newReactor,%0A                newSession);%0A            new MavenGoals(newContext).executeAmpsRecursively(version, %22run%22
 );%0A 
@@ -3953,34 +3953,26 @@
 %22);%0A        
-  
-  %7D%0A    
+%7D%0A
         catc
@@ -3978,20 +3978,8 @@
 ch (
-NoSuchMethod
 Exce
@@ -3991,34 +3991,26 @@
  e)%0A        
-    %7B%0A    
+%7B%0A
             
@@ -4046,53 +4046,22 @@
 ion(
-%22Maven 3 is not supported for run-standalone%22
+e.getMessage()
 , e)
@@ -4066,24 +4066,26 @@
 e);%0A        
+%7D%0A
     %7D%0A%0A     
@@ -4087,264 +4087,403 @@
     
+/**%0A
      
-   projectBuilder.calculateConcreteState(newProject, projectBuilderConfiguration);%0A%0A            // finally, execute run goal against standalone project%0A  
+* MavenSession.getProjectBuilderConfiguration() works at runtime with Maven 2 but isn't%0A     * available at compile time when we build with Maven 3 artifacts.%0A
      
+*/%0A
     
- final MavenContext newContext = oldContext.with(%0A                newProject,%0A  
+private static ProjectBuilderConfiguration getProjectBuilderConfigurationFromMavenSession(MavenSession session)%0A        throws MojoExecutionException, InvocationTargetException, IllegalAccessException%0A    %7B%0A
         
     
@@ -4478,33 +4478,29 @@
         
+try%0A
       
-newReactor,
+  %7B
 %0A       
@@ -4508,101 +4508,148 @@
     
-    newSession);%0A            new MavenGoals(newContext).executeAmpsRecursively(version, %22run%22
+Method m = MavenSession.class.getMethod(%22getProjectBuilderConfiguration%22);%0A            return (ProjectBuilderConfiguration) m.invoke(session
 );%0A 
@@ -4664,32 +4664,44 @@
 %0A        catch (
+NoSuchMethod
 Exception e)%0A   
@@ -4748,38 +4748,69 @@
 onException(
-e.getMessage()
+%22Maven 3 is not supported for run-standalone%22
 , e);%0A      

Refactor use of reflection into a separate method.