diff --git a/pom.xml b/pom.xml
index e9e2d2e..f1398e8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,5 +20,10 @@
maven-core
3.0.3
+
+ junit
+ junit
+ 4.8.2
+
diff --git a/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java b/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java
new file mode 100644
index 0000000..e13202c
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java
@@ -0,0 +1,79 @@
+package io.tesla.lifecycle.profiler;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.apache.maven.eventspy.AbstractEventSpy;
+import org.apache.maven.execution.ExecutionEvent;
+
+/**
+ * @author Jason van Zyl
+ */
+@Named
+@Singleton
+public class LifecycleProfiler extends AbstractEventSpy {
+
+ private SessionProfile sessionProfile;
+ private ProjectProfile projectProfile;
+ private PhaseProfile phaseProfile;
+ private MojoProfile mojoProfile;
+
+ @Override
+ public void init(Context context) throws Exception {
+ }
+
+ @Override
+ public void onEvent(Object event) throws Exception {
+ if (event instanceof ExecutionEvent) {
+
+
+ ExecutionEvent executionEvent = (ExecutionEvent) event;
+ if (executionEvent.getType() == ExecutionEvent.Type.SessionStarted) {
+ //
+ //
+ //
+ sessionProfile = new SessionProfile();
+ } else if (executionEvent.getType() == ExecutionEvent.Type.SessionEnded) {
+ //
+ //
+ //
+ sessionProfile.stop();
+
+ SessionProfileRenderer r = new SessionProfileRenderer();
+ r.render(sessionProfile);
+
+ } else if (executionEvent.getType() == ExecutionEvent.Type.ProjectStarted) {
+ //
+ // We need to collect the mojoExecutions within each project
+ //
+ projectProfile = new ProjectProfile(executionEvent.getProject());
+ } else if (executionEvent.getType() == ExecutionEvent.Type.ProjectSucceeded || executionEvent.getType() == ExecutionEvent.Type.ProjectFailed) {
+ //
+ //
+ //
+ projectProfile.stop();
+ sessionProfile.addProjectProfile(projectProfile);
+ } else if (executionEvent.getType() == ExecutionEvent.Type.MojoStarted) {
+ String phase = executionEvent.getMojoExecution().getLifecyclePhase();
+ //
+ // Create a new phase profile if one doesn't exist or the phase has changed.
+ //
+ if(phaseProfile == null) {
+ phaseProfile = new PhaseProfile(phase);
+ } else if (!phaseProfile.getPhase().equals(phase)) {
+ phaseProfile.stop();
+ System.out.println(">> phase time : " + phaseProfile.getElapsedTime());
+ projectProfile.addPhaseProfile(phaseProfile);
+ phaseProfile = new PhaseProfile(phase);
+ }
+ mojoProfile = new MojoProfile(executionEvent.getMojoExecution());
+ } else if (executionEvent.getType() == ExecutionEvent.Type.MojoSucceeded || executionEvent.getType() == ExecutionEvent.Type.MojoFailed) {
+ //
+ //
+ //
+ mojoProfile.stop();
+ phaseProfile.addMojoProfile(mojoProfile);
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java b/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java
new file mode 100644
index 0000000..7d51916
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java
@@ -0,0 +1,18 @@
+package io.tesla.lifecycle.profiler;
+
+import org.apache.maven.plugin.MojoExecution;
+
+public class MojoProfile extends Profile {
+
+ private MojoExecution mojoExecution;
+
+ protected MojoProfile(MojoExecution mojoExecution) {
+ super(new Timer());
+ this.mojoExecution = mojoExecution;
+ }
+
+ public String getId() {
+ return mojoExecution.getGroupId() + ":" + mojoExecution.getArtifactId() + ":" + mojoExecution.getVersion() + " (" + mojoExecution.getExecutionId() + ") ";
+ }
+
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java b/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java
new file mode 100644
index 0000000..90dd838
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java
@@ -0,0 +1,28 @@
+package io.tesla.lifecycle.profiler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PhaseProfile extends Profile {
+
+ private String phase;
+ private List mojoProfiles;
+
+ public PhaseProfile(String phase) {
+ super(new Timer());
+ this.phase = phase;
+ this.mojoProfiles = new ArrayList();
+ }
+
+ public void addMojoProfile(MojoProfile mojoProfile) {
+ mojoProfiles.add(mojoProfile);
+ }
+
+ public String getPhase() {
+ return phase;
+ }
+
+ public List getMojoProfiles() {
+ return mojoProfiles;
+ }
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/Profile.java b/src/main/java/io/tesla/lifecycle/profiler/Profile.java
new file mode 100644
index 0000000..4988ac7
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/Profile.java
@@ -0,0 +1,26 @@
+package io.tesla.lifecycle.profiler;
+
+public class Profile {
+
+ protected long elapsedTime;
+ protected Timer timer;
+
+ protected Profile(Timer timer) {
+ this.timer = timer;
+ }
+
+ public void stop() {
+ timer.stop();
+ }
+
+ void setElapsedTime(long elapsedTime) {
+ this.elapsedTime = elapsedTime;
+ }
+
+ public long getElapsedTime() {
+ if(elapsedTime != 0) {
+ return elapsedTime;
+ }
+ return timer.getTime();
+ }
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/ProjectProfile.java b/src/main/java/io/tesla/lifecycle/profiler/ProjectProfile.java
new file mode 100644
index 0000000..c9262f0
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/ProjectProfile.java
@@ -0,0 +1,30 @@
+package io.tesla.lifecycle.profiler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.maven.project.MavenProject;
+
+public class ProjectProfile extends Profile {
+
+ private MavenProject project;
+ private List phaseProfiles;
+
+ public ProjectProfile(MavenProject project) {
+ super(new Timer());
+ this.project = project;
+ this.phaseProfiles = new ArrayList();
+ }
+
+ public void addPhaseProfile(PhaseProfile phaseProfile) {
+ phaseProfiles.add(phaseProfile);
+ }
+
+ public String getProjectName() {
+ return project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion();
+ }
+
+ public List getPhaseProfile() {
+ return phaseProfiles;
+ }
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java b/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java
new file mode 100644
index 0000000..0e6c2de
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java
@@ -0,0 +1,22 @@
+package io.tesla.lifecycle.profiler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SessionProfile extends Profile {
+
+ private List projectProfiles;
+
+ public SessionProfile() {
+ super(new Timer());
+ this.projectProfiles = new ArrayList();
+ }
+
+ public void addProjectProfile(ProjectProfile projectProfile) {
+ projectProfiles.add(projectProfile);
+ }
+
+ public List getProjectProfiles() {
+ return projectProfiles;
+ }
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/SessionProfileRenderer.java b/src/main/java/io/tesla/lifecycle/profiler/SessionProfileRenderer.java
new file mode 100644
index 0000000..9816006
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/SessionProfileRenderer.java
@@ -0,0 +1,22 @@
+package io.tesla.lifecycle.profiler;
+
+public class SessionProfileRenderer {
+
+ public void render(SessionProfile sessionProfile) {
+
+ for(ProjectProfile pp : sessionProfile.getProjectProfiles()) {
+ render(pp.getProjectName());
+ for(PhaseProfile phaseProfile : pp.getPhaseProfile()) {
+ render(" " + phaseProfile.getPhase() + " " + Timer.formatTime(phaseProfile.getElapsedTime()));
+ for(MojoProfile mp : phaseProfile.getMojoProfiles()) {
+ render(" " + mp.getId() + Timer.formatTime(mp.getElapsedTime()));
+ }
+ }
+ render("");
+ }
+ }
+
+ private void render(String s) {
+ System.out.println(s);
+ }
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/Timer.java b/src/main/java/io/tesla/lifecycle/profiler/Timer.java
new file mode 100644
index 0000000..c008881
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/Timer.java
@@ -0,0 +1,47 @@
+package io.tesla.lifecycle.profiler;
+
+public class Timer {
+ public static final int MS_PER_SEC = 1000;
+ public static final int SEC_PER_MIN = 60;
+ private long start;
+ private long time;
+
+ public Timer() {
+ start = System.currentTimeMillis();
+ }
+
+ public void stop() {
+ time = elapsedTime();
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ private long elapsedTime() {
+ return System.currentTimeMillis() - start;
+ }
+
+ public static String formatTime(long ms) {
+ long secs = ms / MS_PER_SEC;
+ long mins = secs / SEC_PER_MIN;
+ secs = secs % SEC_PER_MIN;
+ long fractionOfASecond = ms - (secs * 1000);
+// System.out.println("mins " + mins);
+// System.out.println("secs " + secs);
+// System.out.println(fractionOfASecond);
+// System.out.println(">> " + fractionOfASecond);
+
+ String msg = mins + "m " + secs + "." + fractionOfASecond;
+
+ if (msg.length() == 3) {
+ msg += "00s";
+ } else if (msg.length() == 4) {
+ msg += "0s";
+ } else {
+ msg += "s";
+ }
+
+ return msg;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/META-INF/plexus/components.xml b/src/main/resources/META-INF/plexus/components.xml
new file mode 100644
index 0000000..c8d2c8b
--- /dev/null
+++ b/src/main/resources/META-INF/plexus/components.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ org.apache.maven.eventspy.EventSpy
+ default
+ io.tesla.lifecycle.profiler.LifecycleProfiler
+
+ false
+
+
+
diff --git a/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java b/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java
new file mode 100644
index 0000000..585caa9
--- /dev/null
+++ b/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java
@@ -0,0 +1,63 @@
+package io.tesla.lifecycle.profiler;
+
+import junit.framework.TestCase;
+
+import org.apache.maven.model.Plugin;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.project.MavenProject;
+
+
+public class LifecycleProfilerTest extends TestCase {
+
+ public void testSessionProfile() {
+
+ SessionProfile s = new SessionProfile();
+
+ ProjectProfile p0 = new ProjectProfile(project("g0", "a0", "v0"));
+ PhaseProfile ph0 = new PhaseProfile("phase0");
+ MojoProfile m0 = new MojoProfile(mojoExecution("goal0","m0"));
+ m0.setElapsedTime(3000);
+ ph0.addMojoProfile(m0);
+ MojoProfile m00 = new MojoProfile(mojoExecution("goal00","m00"));
+ m00.setElapsedTime(5492009);
+ ph0.addMojoProfile(m00);
+ p0.addPhaseProfile(ph0);
+ s.addProjectProfile(p0);
+
+ ProjectProfile p1 = new ProjectProfile(project("g1", "a1", "v1"));
+ PhaseProfile ph1 = new PhaseProfile("phase1");
+ MojoProfile m1 = new MojoProfile(mojoExecution("goal1", "m1"));
+ m1.setElapsedTime(2500);
+ ph1.addMojoProfile(m1);
+ p1.addPhaseProfile(ph1);
+ s.addProjectProfile(p1);
+
+ ProjectProfile p2 = new ProjectProfile(project("g2", "a2", "v2"));
+ PhaseProfile ph2 = new PhaseProfile("phase2");
+ MojoProfile m2 = new MojoProfile(mojoExecution("goal2","m2"));
+ m2.setElapsedTime(5000);
+ ph2.addMojoProfile(m2);
+ p2.addPhaseProfile(ph2);
+ s.addProjectProfile(p2);
+
+ SessionProfileRenderer r = new SessionProfileRenderer();
+ r.render(s);
+ }
+
+ protected MavenProject project(String g, String a, String v) {
+ MavenProject p = new MavenProject();
+ p.setGroupId(g);
+ p.setArtifactId(a);
+ p.setVersion(v);
+ return p;
+ }
+
+ protected MojoExecution mojoExecution(String goal, String executionId) {
+ Plugin p = new Plugin();
+ p.setGroupId("groupId");
+ p.setArtifactId("artifactId");
+ p.setVersion("version");
+ MojoExecution me = new MojoExecution(p, goal, executionId);
+ return me;
+ }
+}