Add capability of getting cpuInfo.

Understands the { "cpuInfo": true } request returning the cpuInfo
as understood by JHardware.

Change-Id: I9ba1b8322d0a6558ece6944350a2de64878a6165
diff --git a/README.md b/README.md
index 5145daf..245dd27 100644
--- a/README.md
+++ b/README.md
@@ -15,5 +15,4 @@
    $ sbt assembly
    [...]
    [info] Packaging /Users/lucamilanesio/gerrithub/gerrit-support/target/scala-2.11/gerrit-support.jar ...
-```
-
+```
\ No newline at end of file
diff --git a/build.sbt b/build.sbt
index f259ef9..fb48094 100644
--- a/build.sbt
+++ b/build.sbt
@@ -6,30 +6,23 @@
 
 scalaVersion := "2.11.8"
 
-val guiceV = "3.0"
-val gerritV = "2.11"
 val scalatraV = "2.5.+"
-val scalatestV = "3.0.1"
-val gsonV = "2.7" // same version provided by Gerrit
-val jodaV = "2.9.4" // same version provided by Gerrit
-val scalaGuiceV = "4.1.0"
-
 
 libraryDependencies ++= Seq(
   // provided by gerrit
-  "com.google.inject"     %   "guice"             % guiceV      % Provided,
-  "com.google.gerrit"     %   "gerrit-plugin-api" % gerritV     % Provided,
-  "com.google.code.gson"  %   "gson"              % gsonV       % Provided,
-  "joda-time"             %   "joda-time"         % jodaV       % Provided,
+  "com.google.inject"     %   "guice"             % "3.0"       % Provided,
+  "com.google.gerrit"     %   "gerrit-plugin-api" % "2.11"      % Provided,
+  "com.google.code.gson"  %   "gson"              % "2.7"       % Provided,
+  "joda-time"             %   "joda-time"         % "2.9.4"     % Provided,
 
   // added to assembly
   "org.scalatra"          %%  "scalatra"          % scalatraV,
-
+  "org.jhardware"         %   "jHardware"         % "0.8.4",
 
   // test dependencies
   "org.scalatra"          %%  "scalatra-scalatest"% scalatraV   % Test,
-  "org.scalatest"         %%  "scalatest"         % scalatestV  % Test,
-  "net.codingwell"        %%  "scala-guice"       % scalaGuiceV % Test
+  "org.scalatest"         %%  "scalatest"         % "3.0.1"     % Test,
+  "net.codingwell"        %%  "scala-guice"       % "4.1.0"     % Test
   )
 
 assemblyJarName in assembly := s"$pluginName.jar"
diff --git a/src/main/resources/Documentation/rest-api.md b/src/main/resources/Documentation/rest-api.md
new file mode 100644
index 0000000..8933f56
--- /dev/null
+++ b/src/main/resources/Documentation/rest-api.md
@@ -0,0 +1,61 @@
+gerrit-support REST API
+==============================
+
+NAME
+----
+collect/1 - Prepare a support .zip file
+
+SYNOPSIS
+--------
+>     POST /plugins/gerrit-support/collect
+
+DESCRIPTION
+-----------
+Prepares a zip file collecting information requested in the JSON request.
+
+The JSON payload contains a series of flags with the list of information to be
+collected and archived in the .zip file.
+
+- gerritVersion - JSON String with the version of running Gerrit server
+- cpuInfo - JSON Object with all the CPU information collected by [jHardware](https://github.com/profesorfalken/jHardware)
+
+
+EXAMPLES
+--------
+
+Ask the server to prepare zip file for version and cpuinfo
+
+>     curl -v -H "Content-Type: application/json" \
+>        -d '{"gerritVersion": true,"cpuInfo": true }' \
+>        http://host:port/plugins/gerrit-support/collect
+
+```
+< HTTP/1.1 201 Created
+< Date: Tue, 04 Apr 2017 22:53:33 GMT
+< Content-Type: text/plain; charset=UTF-8
+< Location: /plugins/gerrit-support/collect/20170405-005334-collect-b6d2bc6a-7f01-4b93-9f74-ad28b4a68e67.zip
+< Content-Length: 2
+
+```
+NOTE: Location header gives the name of the prepared file created on Gerrit server.
+
+NAME
+----
+collect/2 - Download a support file
+
+SYNOPSIS
+--------
+>     GET /plugins/gerrit-support/collect/<zip file name>
+
+DESCRIPTION
+-----------
+Download a Gerrit support .zip file previously prepared.
+
+EXAMPLES
+--------
+
+Download the .zip support file
+
+>     curl http://host:port/plugins/gerrit-support/collect/20170405-005334-collect-b6d2bc6a-7f01-4b93-9f74-ad28b4a68e67.zip \
+>          -o received.zip
+
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportCommands.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportCommands.scala
index 5f53b9c..e8c9480 100644
--- a/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportCommands.scala
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportCommands.scala
@@ -17,8 +17,11 @@
 package com.googlesource.gerrit.plugins.support
 
 import com.google.gerrit.common.Version
-import com.google.gson.{JsonElement, JsonPrimitive}
+import com.google.gson.{Gson, JsonElement, JsonObject, JsonPrimitive}
 import com.google.inject._
+import org.jutils.jhardware.HardwareInfo.getProcessorInfo
+
+import scala.util.Try
 
 case class CommandResult(entryName: String, content: JsonElement)
 
@@ -36,4 +39,26 @@
 
 class GerritVersionCommand extends GerritSupportCommand {
   def execute = CommandResult("version.json", new JsonPrimitive(Version.getVersion))
+}
+
+class CpuInfoCommand extends GerritSupportCommand {
+  implicit val gson = new Gson
+
+  def execute = CommandResult("cpu-info.json",
+    gson.toJsonTree(
+      Try {
+        getProcessorInfo
+      } getOrElse {
+        ErrorInfo("error" -> s"CPU info not available on ${System.getProperty("os.name")}")
+      }))
+}
+
+object ErrorInfo {
+  def apply[T](attributes: (String, T)*)(implicit gson: Gson): JsonObject =
+    attributes.foldLeft(new JsonObject) {
+      (json, pair) => {
+        json.add(pair._1, gson.toJsonTree(pair._2))
+        json
+      }
+    }
 }
\ No newline at end of file
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/support/GerritSupportTest.scala b/src/test/scala/com/googlesource/gerrit/plugins/support/GerritSupportTest.scala
index f4b8eb0..60adf74 100644
--- a/src/test/scala/com/googlesource/gerrit/plugins/support/GerritSupportTest.scala
+++ b/src/test/scala/com/googlesource/gerrit/plugins/support/GerritSupportTest.scala
@@ -17,14 +17,15 @@
 package com.googlesource.gerrit.plugins.support
 
 import java.io.File
-import java.util.zip.{ZipEntry, ZipFile}
+import java.util.zip.ZipFile
 
 import com.google.gson.{Gson, JsonPrimitive}
+import com.googlesource.gerrit.plugins.support.FileMatchers._
 import org.scalatest.{FlatSpec, Matchers}
-import FileMatchers._
+
 import scala.collection.JavaConverters._
 
-class GerritSupportTest extends FlatSpec with Matchers {
+class GerritSupportTest extends FlatSpec with Matchers with JsonMatcher {
   val tmpPath = File.createTempFile(classOf[GerritSupportTest].getName, "").getParentFile
 
   def tmpFile = {
@@ -39,6 +40,13 @@
     version.getAsString should not be null
   }
 
+  "cpu-info command" should "return a json object with some fields" in {
+    val cpuInfo = new CpuInfoCommand().execute.content
+
+    cpuInfo should not be null
+    cpuInfo.getAsJsonObject should haveValidFields
+  }
+
   "Bundle builder" should "create an output zip file" in {
     val zipFile = new SupportBundleBuilder(tmpPath.toPath, new Gson).build
 
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/support/JsonMatcher.scala b/src/test/scala/com/googlesource/gerrit/plugins/support/JsonMatcher.scala
new file mode 100644
index 0000000..c1e8c96
--- /dev/null
+++ b/src/test/scala/com/googlesource/gerrit/plugins/support/JsonMatcher.scala
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 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.support
+
+import com.google.gson.JsonObject
+import org.scalatest.matchers.{MatchResult, Matcher}
+
+import scala.collection.JavaConverters._
+
+trait JsonMatcher {
+  def haveValidFields =
+    Matcher { (left: JsonObject) =>
+      MatchResult(
+        left.entrySet().asScala.filter( _.getValue != null).size > 0,
+        left + " had not valid fields",
+        left + " had valid fields"
+      )
+    }
+
+}