Port plugin code to Scala

Change-Id: Ic15d871b6cd1ae383986f3221b0c2418fb5c20b5
diff --git a/build.sbt b/build.sbt
index 1bcb710..dc579ab 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,20 +1,18 @@
-import sbt.Keys._
-
 val gerritApiVersion = "2.13.7"
-
 val pluginName = "analytics"
+val pluginVersion = "1.1-SNAPSHOT"
 
 lazy val root = (project in file("."))
   .settings(
     name := pluginName,
 
-    version := "1.0-SNAPSHOT",
+    version := pluginVersion,
 
     scalaVersion := "2.11.8",
 
     libraryDependencies ++= Seq(
       "io.fabric8" % "gitective-core" % "0.9.19"
-        exclude ("org.eclipse.jgit", "org.eclipse.jgit"),
+        exclude("org.eclipse.jgit", "org.eclipse.jgit"),
 
       "com.google.inject" % "guice" % "3.0" % Provided,
       "com.google.gerrit" % "gerrit-plugin-api" % gerritApiVersion % Provided withSources(),
@@ -36,7 +34,3 @@
     )
   )
 
-
-
-
-
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/CommitInfo.java b/src/main/java/com/googlesource/gerrit/plugins/analytics/CommitInfo.java
deleted file mode 100644
index d7fbd9a..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/CommitInfo.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed 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.
-
-package com.googlesource.gerrit.plugins.analytics;
-
-public class CommitInfo {
-  public final String sha1;
-  public final long date;
-  public final boolean merge;
-
-  public CommitInfo(String sha1, long date, boolean merge) {
-    super();
-    this.sha1 = sha1;
-    this.date = date;
-    this.merge = merge;
-  }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/ContributorsCommand.java b/src/main/java/com/googlesource/gerrit/plugins/analytics/ContributorsCommand.java
deleted file mode 100644
index 0105ea5..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/ContributorsCommand.java
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed 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.
-
-package com.googlesource.gerrit.plugins.analytics;
-
-import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
-import com.google.gerrit.server.project.ProjectResource;
-import com.google.gerrit.server.project.ProjectsCollection;
-import com.google.gerrit.sshd.CommandMetaData;
-import com.google.gerrit.sshd.SshCommand;
-import com.google.inject.Inject;
-
-import org.kohsuke.args4j.Argument;
-
-import java.io.IOException;
-
-@CommandMetaData(name = "contributors", description = "Extracts the list of contributors to a project")
-public class ContributorsCommand extends SshCommand {
-  private final ProjectsCollection projects;
-  private final ContributorsResource contributors;
-  private final GsonFormatter gsonFmt;
-
-  @Inject
-  public ContributorsCommand(ProjectsCollection projects,
-      ContributorsResource contributors, GsonFormatter gsonFmt) {
-    this.projects = projects;
-    this.contributors = contributors;
-    this.gsonFmt = gsonFmt;
-  }
-
-  @Argument(usage = "project name", metaVar = "PROJECT", required = true)
-  void setProject(String project) throws IllegalArgumentException {
-    try {
-      this.projectRes = projects.parse(project);
-    } catch (UnprocessableEntityException e) {
-      throw new IllegalArgumentException(e.getLocalizedMessage(), e);
-    } catch (IOException e) {
-      throw new IllegalArgumentException(
-          "I/O Error while trying to access project " + project, e);
-    }
-  }
-
-  private ProjectResource projectRes;
-
-  @Override
-  protected void run() throws UnloggedFailure, Failure, Exception {
-    gsonFmt.format(contributors.getStream(projectRes), stdout);
-  }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/ContributorsResource.java b/src/main/java/com/googlesource/gerrit/plugins/analytics/ContributorsResource.java
deleted file mode 100644
index d9963de..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/ContributorsResource.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed 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.
-
-package com.googlesource.gerrit.plugins.analytics;
-
-import com.google.gerrit.extensions.restapi.BinaryResult;
-import com.google.gerrit.extensions.restapi.Response;
-import com.google.gerrit.extensions.restapi.RestReadView;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.project.ProjectResource;
-import com.google.inject.Inject;
-
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
-import org.eclipse.jgit.lib.Repository;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.stream.Stream;
-
-class ContributorsResource implements RestReadView<ProjectResource> {
-  private final GitRepositoryManager repoManager;
-  private final UserSummaryExport userSummary;
-  private final GsonFormatter gsonFmt;
-
-  class JsonStreamedResult<T> extends BinaryResult {
-    private final Stream<T> committers;
-
-    public JsonStreamedResult(Stream<T> committers) {
-      this.committers = committers;
-    }
-
-    @Override
-    public void writeTo(OutputStream os) throws IOException {
-      try (PrintWriter sout = new PrintWriter(os)) {
-        gsonFmt.format(committers, sout);
-      }
-    }
-  }
-
-  @Inject
-  public ContributorsResource(GitRepositoryManager repoManager,
-      UserSummaryExport userSummary, GsonFormatter gsonFmt) {
-    this.repoManager = repoManager;
-    this.userSummary = userSummary;
-    this.gsonFmt = gsonFmt;
-  }
-
-  @Override
-  public Response<BinaryResult> apply(ProjectResource projectRes)
-      throws RepositoryNotFoundException, IOException {
-    return Response.ok(new JsonStreamedResult<>(getStream(projectRes)));
-  }
-
-  public Stream<UserActivitySummary> getStream(ProjectResource projectRes)
-      throws RepositoryNotFoundException, IOException {
-    try (Repository repo = repoManager.openRepository(projectRes.getNameKey())) {
-      return userSummary.getCommittersStream(repo);
-    }
-  }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/GsonFormatter.java b/src/main/java/com/googlesource/gerrit/plugins/analytics/GsonFormatter.java
deleted file mode 100644
index eecd33b..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/GsonFormatter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed 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.
-
-package com.googlesource.gerrit.plugins.analytics;
-
-import com.google.gerrit.server.OutputFormat;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-
-import java.io.PrintWriter;
-import java.util.stream.Stream;
-
-@Singleton
-public class GsonFormatter {
-  private GsonBuilder gsonBuilder;
-
-  @Inject
-  public GsonFormatter() {
-    gsonBuilder = OutputFormat.JSON_COMPACT.newGsonBuilder();
-  }
-
-  public <T> void format(Stream<T> values, PrintWriter out) {
-    final Gson gson = gsonBuilder.create();
-
-    values.sequential().forEach((T value) -> {
-      gson.toJson(value, out);
-      out.println();
-    });
-  }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/Module.java b/src/main/java/com/googlesource/gerrit/plugins/analytics/Module.java
deleted file mode 100644
index 3d2f6eb..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/Module.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed 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.
-
-package com.googlesource.gerrit.plugins.analytics;
-
-import static com.google.gerrit.server.project.ProjectResource.PROJECT_KIND;
-
-import com.google.gerrit.extensions.restapi.RestApiModule;
-import com.google.inject.AbstractModule;
-
-public class Module extends AbstractModule {
-
-  @Override
-  protected void configure() {
-
-    install(new RestApiModule() {
-      @Override
-      protected void configure() {
-        get(PROJECT_KIND, "contributors").to(ContributorsResource.class);
-      }
-    });
-  }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/UserActivitySummary.java b/src/main/java/com/googlesource/gerrit/plugins/analytics/UserActivitySummary.java
deleted file mode 100644
index f94d7be..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/UserActivitySummary.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed 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.
-
-package com.googlesource.gerrit.plugins.analytics;
-
-
-import org.eclipse.jgit.lib.ObjectId;
-// import org.gitective.core.stat.UserCommitActivity;
-import org.gitective.core.stat.UserCommitActivity;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class UserActivitySummary {
-  public final String name;
-  public final String email;
-  public final int numCommits;
-  public final List<CommitInfo> commits;
-  public final long lastCommitDate;
-
-
-  public UserActivitySummary(String name, String email, int numCommits,
-      List<CommitInfo> commits, long lastCommitDate) {
-    this.name = name;
-    this.email = email;
-    this.numCommits = numCommits;
-    this.commits = commits;
-    this.lastCommitDate = lastCommitDate;
-  }
-
-  public static UserActivitySummary fromUserActivity(UserCommitActivity uca) {
-    return new UserActivitySummary(uca.getName(), uca.getEmail(),
-        uca.getCount(), getCommits(uca.getIds(), uca.getTimes(),
-            uca.getMerges()), uca.getLatest());
-  }
-
-  private static List<CommitInfo> getCommits(ObjectId[] ids, long[] times,
-      boolean[] merges) {
-    List<CommitInfo> commits = new ArrayList<>(ids.length);
-
-    for (int i = 0; i < ids.length; i++) {
-      commits.add(new CommitInfo(ids[i].name(), times[i], merges[i]));
-    }
-
-    return commits;
-  }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/UserSummaryExport.java b/src/main/java/com/googlesource/gerrit/plugins/analytics/UserSummaryExport.java
deleted file mode 100644
index 953dc3a..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/UserSummaryExport.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed 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.
-
-package com.googlesource.gerrit.plugins.analytics;
-
-import com.google.inject.Singleton;
-
-import org.eclipse.jgit.lib.Repository;
-import org.gitective.core.CommitFinder;
-import org.gitective.core.stat.AuthorHistogramFilter;
-import org.gitective.core.stat.CommitHistogram;
-import org.gitective.core.stat.CommitHistogramFilter;
-import org.gitective.core.stat.UserCommitActivity;
-
-import java.util.stream.Stream;
-
-@Singleton
-public class UserSummaryExport {
-
-  public Stream<UserActivitySummary> getCommittersStream(Repository repo) {
-    CommitFinder finder = new CommitFinder(repo);
-    CommitHistogramFilter filter = new AuthorHistogramFilter();
-    finder.setFilter(filter).find();
-    CommitHistogram histogram = filter.getHistogram();
-    UserCommitActivity[] authorActivity = histogram.getUserActivity();
-
-    return Stream.of(authorActivity)
-        .parallel()
-        .map(UserActivitySummary::fromUserActivity);
-  }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/SshModule.java b/src/main/scala/com/googlesource/gerrit/plugins/analytics/CommitInfo.scala
similarity index 70%
rename from src/main/java/com/googlesource/gerrit/plugins/analytics/SshModule.java
rename to src/main/scala/com/googlesource/gerrit/plugins/analytics/CommitInfo.scala
index 7f015f9..d0ac124 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/SshModule.java
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/CommitInfo.scala
@@ -12,14 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.googlesource.gerrit.plugins.analytics;
+package com.googlesource.gerrit.plugins.analytics
 
-import com.google.gerrit.sshd.PluginCommandModule;
-
-public class SshModule extends PluginCommandModule {
-
-  @Override
-  protected void configureCommands() {
-    command(ContributorsCommand.class);
-  }
-}
+case class CommitInfo(val sha1: String, val date: Long, val merge: Boolean)
\ No newline at end of file
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/ContributorsCommand.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/ContributorsCommand.scala
new file mode 100644
index 0000000..a53c632
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/ContributorsCommand.scala
@@ -0,0 +1,47 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed 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.
+
+package com.googlesource.gerrit.plugins.analytics
+
+import java.io.IOException
+
+import com.google.gerrit.extensions.restapi.UnprocessableEntityException
+import com.google.gerrit.server.project.{ProjectResource, ProjectsCollection}
+import com.google.gerrit.sshd.{CommandMetaData, SshCommand}
+import com.google.inject.Inject
+import org.kohsuke.args4j.Argument
+
+@CommandMetaData(name = "contributors", description = "Extracts the list of contributors to a project")
+class ContributorsCommand @Inject() (
+  val projects: ProjectsCollection,
+  val contributors: ContributorsResource,
+  val gsonFmt: GsonFormatter) extends SshCommand {
+
+  @Argument(usage = "project name", metaVar = "PROJECT", required = true)
+  def setProject(project: String): Unit = {
+    try {
+      this.projectRes = projects.parse(project)
+    } catch {
+      case e: UnprocessableEntityException =>
+        throw new IllegalArgumentException(e.getLocalizedMessage, e)
+      case e: IOException =>
+        throw new IllegalArgumentException("I/O Error while trying to access project " + project, e)
+    }
+  }
+
+  private var projectRes: ProjectResource = null
+  override protected def run(): Unit = {
+    gsonFmt.format(contributors.get(projectRes), stdout)
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/ContributorsResource.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/ContributorsResource.scala
new file mode 100644
index 0000000..3d43a18
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/ContributorsResource.scala
@@ -0,0 +1,40 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed 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.
+
+package com.googlesource.gerrit.plugins.analytics
+
+import java.io.{OutputStream, PrintWriter}
+
+import com.google.gerrit.extensions.restapi.{BinaryResult, Response, RestReadView}
+import com.google.gerrit.server.git.GitRepositoryManager
+import com.google.gerrit.server.project.ProjectResource
+import com.google.inject.Inject
+import com.googlesource.gerrit.plugins.analytics.ManagedResource.use
+
+class ContributorsResource @Inject()(val repoManager: GitRepositoryManager,
+                                     val userSummary: UserSummaryExport,
+                                     val gsonFmt: GsonFormatter) extends RestReadView[ProjectResource] {
+
+  private[analytics] class JsonStreamedResult[T](val committers: TraversableOnce[T]) extends BinaryResult {
+    override def writeTo(os: OutputStream) {
+      use(new PrintWriter(os)) { gsonFmt.format(committers, _) }
+    }
+  }
+
+  override def apply(projectRes: ProjectResource): Response[BinaryResult] =
+    Response.ok(new JsonStreamedResult[UserActivitySummary](get(projectRes)))
+
+  def get(projectRes: ProjectResource): TraversableOnce[UserActivitySummary] =
+    use(repoManager.openRepository(projectRes.getNameKey)) { userSummary.getCommitters }
+}
\ No newline at end of file
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/GsonFormatter.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/GsonFormatter.scala
new file mode 100644
index 0000000..d400ad8
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/GsonFormatter.scala
@@ -0,0 +1,34 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed 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.
+
+package com.googlesource.gerrit.plugins.analytics
+
+import java.io.PrintWriter
+
+import com.google.gerrit.server.OutputFormat
+import com.google.gson.{Gson, GsonBuilder}
+import com.google.inject.Singleton
+
+@Singleton
+class GsonFormatter {
+  val gsonBuilder: GsonBuilder = OutputFormat.JSON_COMPACT.newGsonBuilder
+
+  def format[T](values: TraversableOnce[T], out: PrintWriter) {
+    val gson: Gson = gsonBuilder.create
+    for (value <- values) {
+      gson.toJson(value, out)
+      out.println()
+    }
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/SshModule.java b/src/main/scala/com/googlesource/gerrit/plugins/analytics/ManagedResources.scala
similarity index 70%
copy from src/main/java/com/googlesource/gerrit/plugins/analytics/SshModule.java
copy to src/main/scala/com/googlesource/gerrit/plugins/analytics/ManagedResources.scala
index 7f015f9..741f91c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/SshModule.java
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/ManagedResources.scala
@@ -12,14 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.googlesource.gerrit.plugins.analytics;
+package com.googlesource.gerrit.plugins.analytics
 
-import com.google.gerrit.sshd.PluginCommandModule;
-
-public class SshModule extends PluginCommandModule {
-
-  @Override
-  protected void configureCommands() {
-    command(ContributorsCommand.class);
-  }
+object ManagedResource {
+  def use[A <: { def close(): Unit }, B](resource: A)(code: A ⇒ B): B =
+    try
+      code(resource)
+    finally
+      resource.close()
 }
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/Module.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/Module.scala
new file mode 100644
index 0000000..1c804ad
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/Module.scala
@@ -0,0 +1,32 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed 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.
+
+package com.googlesource.gerrit.plugins.analytics
+
+import com.google.gerrit.extensions.restapi.RestApiModule
+import com.google.gerrit.server.project.ProjectResource.PROJECT_KIND
+import com.google.inject.AbstractModule
+
+class Module extends AbstractModule {
+
+  override protected def configure() {
+
+    install(new RestApiModule() {
+
+      override protected def configure() = {
+        get(PROJECT_KIND, "contributors").to(classOf[ContributorsResource])
+      }
+    })
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/analytics/SshModule.java b/src/main/scala/com/googlesource/gerrit/plugins/analytics/SshModule.scala
similarity index 70%
copy from src/main/java/com/googlesource/gerrit/plugins/analytics/SshModule.java
copy to src/main/scala/com/googlesource/gerrit/plugins/analytics/SshModule.scala
index 7f015f9..5995de5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/analytics/SshModule.java
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/SshModule.scala
@@ -12,14 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.googlesource.gerrit.plugins.analytics;
+package com.googlesource.gerrit.plugins.analytics
 
-import com.google.gerrit.sshd.PluginCommandModule;
+import com.google.gerrit.sshd.PluginCommandModule
 
-public class SshModule extends PluginCommandModule {
-
-  @Override
-  protected void configureCommands() {
-    command(ContributorsCommand.class);
+class SshModule extends PluginCommandModule {
+  override protected def configureCommands {
+    command(classOf[ContributorsCommand])
   }
-}
+}
\ No newline at end of file
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/UserActivitySummary.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/UserActivitySummary.scala
new file mode 100644
index 0000000..bde6731
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/UserActivitySummary.scala
@@ -0,0 +1,32 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed 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.
+
+package com.googlesource.gerrit.plugins.analytics
+
+import org.eclipse.jgit.lib.ObjectId
+import org.gitective.core.stat.UserCommitActivity
+
+object UserActivitySummary {
+  def fromUserActivity(uca: UserCommitActivity) =
+    UserActivitySummary(uca.getName, uca.getEmail, uca.getCount,
+      getCommits(uca.getIds, uca.getTimes, uca.getMerges), uca.getLatest)
+
+  private def getCommits(ids: Array[ObjectId], times: Array[Long], merges: Array[Boolean]):
+  Array[CommitInfo] = {
+    (ids, times, merges).zipped.map((id, time, merge) => CommitInfo(id.name, time, merge))
+  }
+}
+
+case class UserActivitySummary(name: String, email: String, numCommits: Int,
+                               commits: Array[CommitInfo], lastCommitDate: Long)
\ No newline at end of file
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/UserSummaryExport.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/UserSummaryExport.scala
new file mode 100644
index 0000000..d4a5142
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/UserSummaryExport.scala
@@ -0,0 +1,32 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed 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.
+
+package com.googlesource.gerrit.plugins.analytics
+
+import com.google.inject.Singleton
+import org.eclipse.jgit.lib.Repository
+import org.gitective.core.CommitFinder
+import org.gitective.core.stat.AuthorHistogramFilter
+
+@Singleton
+class UserSummaryExport {
+  def getCommitters(repo: Repository): TraversableOnce[UserActivitySummary] = {
+    val finder = new CommitFinder(repo)
+    val filter = new AuthorHistogramFilter
+    finder.setFilter(filter).find
+    val histogram = filter.getHistogram
+    val authorActivity = histogram.getUserActivity
+    authorActivity.par.map(UserActivitySummary.fromUserActivity).toStream
+  }
+}
\ No newline at end of file