Gerrit ver. < 2.15 permissions fix

When using an older Gerrit version, the new 2.15 classes would not
be accessible. Rely on reflection to avoid failing for class not found.

Change-Id: I5f352993fdbe08468a9c48dae092b35daf95e851
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/CollectServerDataCapability.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/CollectServerDataCapability.scala
deleted file mode 100644
index c85f461..0000000
--- a/src/main/scala/com/googlesource/gerrit/plugins/support/CollectServerDataCapability.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.gerrit.extensions.api.access.PluginPermission
-import com.google.gerrit.extensions.config.CapabilityDefinition
-import com.google.gerrit.server.account.CapabilityControl
-
-import scala.util.Try
-
-class CollectServerDataCapability extends CapabilityDefinition {
-  override def getDescription: String = "Collect Server Data"
-}
-
-object CollectServerDataCapability {
-  val COLLECT_SERVER_DATA = "collectServerData"
-
-  val pluginName = "gerrit-support"
-
-  implicit class PimpedCapabilityControl(val capabilityControl: CapabilityControl) extends AnyVal {
-
-    def legacyCanPerform(operation: String): Try[Boolean] = Try {
-      val canPerform = capabilityControl.getClass.getMethod("canPerform", classOf[String])
-      canPerform.invoke(capabilityControl, operation).asInstanceOf[Boolean]
-    }
-
-    implicit def stringToGlobalOrPluginPermissions(operation: String) = new PluginPermission(pluginName, operation)
-
-    def canDo(operation: String): Boolean =
-      legacyCanPerform(operation).getOrElse {
-        capabilityControl.doCanForDefaultPermissionBackend(operation)
-      }
-  }
-}
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/GerritFacade.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/GerritFacade.scala
new file mode 100644
index 0000000..2736b9f
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/GerritFacade.scala
@@ -0,0 +1,47 @@
+/*
+ * 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.gerrit.server.account.CapabilityControl
+import com.googlesource.gerrit.plugins.support.latest.LatestCapabilityControl
+import com.googlesource.gerrit.plugins.support.legacy.LegacyCapabilityControl
+
+import scala.util.{Failure, Success, Try}
+
+object GerritFacade {
+
+  class PluginName(val value: String) extends AnyRef
+
+  implicit class PimpedCapabilityControl(val cc: CapabilityControl) extends AnyVal {
+
+    def canDo(operation: String)(implicit pluginName: PluginName) =
+      LatestCapabilityControl(cc).canPerform(operation)
+        .orElse(LegacyCapabilityControl(cc).canPerform(operation))
+        .get
+  }
+}
+
+object TryAll {
+  def apply[T](block: => T): Try[T] = {
+    try {
+      val res:T = block
+      Success(res)
+    } catch {
+      case t: Throwable => Failure(t)
+    }
+  }
+}
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportServlet.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportServlet.scala
index 13621d6..960c8c3 100644
--- a/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportServlet.scala
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportServlet.scala
@@ -18,9 +18,11 @@
 
 import java.io.{File, FileNotFoundException}
 
+import com.google.gerrit.extensions.annotations.{PluginName => GerritPlugiName}
 import com.google.gerrit.server.CurrentUser
 import com.google.inject.{Inject, Provider, Singleton}
-import com.googlesource.gerrit.plugins.support.CollectServerDataCapability._
+import com.googlesource.gerrit.plugins.support.GerritFacade._
+import com.googlesource.gerrit.plugins.support.latest.CollectServerDataCapability._
 import eu.medsea.mimeutil.detector.ExtensionMimeDetector
 import org.scalatra._
 import org.scalatra.util.Mimes
@@ -29,13 +31,16 @@
 import scala.util.{Failure, Success}
 
 @Singleton
-class GerritSupportServlet @Inject() (val processor: RequestProcessor,
-                                      bundleFactory: SupportBundleFile,
-                                      mimeDetector: ExtensionMimeDetector,
-                                      currentUserProvider: Provider[CurrentUser])
-    extends ScalatraServlet with Mimes {
+class GerritSupportServlet @Inject()(val processor: RequestProcessor,
+                                     bundleFactory: SupportBundleFile,
+                                     mimeDetector: ExtensionMimeDetector,
+                                     currentUserProvider: Provider[CurrentUser],
+                                     @GerritPlugiName gerritPluginName: String)
+  extends ScalatraServlet with Mimes {
 
-  post("/") (requireAdministrateServerPermissions {
+  implicit val pluginName = new PluginName(gerritPluginName)
+
+  post("/")(requireAdministrateServerPermissions {
     processor.processRequest(request.body) match {
       case Success(zipped) =>
         Created("OK", Map(
@@ -45,7 +50,7 @@
     }
   })
 
-  get("/:filename") (requireAdministrateServerPermissions {
+  get("/:filename")(requireAdministrateServerPermissions {
     val bundleFilename = params.getOrElse("filename", halt(BadRequest("Missing or invalid bundle name")))
 
     bundleFactory(bundleFilename) match {
@@ -60,7 +65,8 @@
   })
 
   private def requireAdministrateServerPermissions(block: => ActionResult) = {
-    currentUserProvider.get match {
+    val currentUser = currentUserProvider.get
+    currentUser match {
       case user if user.isIdentifiedUser && user.getCapabilities.canDo(COLLECT_SERVER_DATA) => block
       case _ => Forbidden("NOT ALLOWED to collect server data")
     }
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/Module.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/Module.scala
index cc871e5..38b01b1 100644
--- a/src/main/scala/com/googlesource/gerrit/plugins/support/Module.scala
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/Module.scala
@@ -16,10 +16,11 @@
 
 package com.googlesource.gerrit.plugins.support
 
-import com.google.inject.AbstractModule
 import com.google.gerrit.extensions.annotations.Exports
 import com.google.gerrit.extensions.config.CapabilityDefinition
-import CollectServerDataCapability.COLLECT_SERVER_DATA
+import com.google.inject.AbstractModule
+import com.googlesource.gerrit.plugins.support.latest.CollectServerDataCapability
+import com.googlesource.gerrit.plugins.support.latest.CollectServerDataCapability.COLLECT_SERVER_DATA
 
 class Module extends AbstractModule {
   override def configure() {
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/latest/CollectServerDataCapability.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/latest/CollectServerDataCapability.scala
new file mode 100644
index 0000000..fd1f432
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/latest/CollectServerDataCapability.scala
@@ -0,0 +1,29 @@
+/*
+ * 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.latest
+
+import com.google.gerrit.extensions.config.CapabilityDefinition
+
+class CollectServerDataCapability extends CapabilityDefinition {
+  override def getDescription: String = "Collect Server Data"
+}
+
+object CollectServerDataCapability {
+  val COLLECT_SERVER_DATA = "collectServerData"
+}
+
+
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/latest/CollectServerDataPermission.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/latest/CollectServerDataPermission.scala
new file mode 100644
index 0000000..8d83978
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/latest/CollectServerDataPermission.scala
@@ -0,0 +1,23 @@
+/*
+ * 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.latest
+
+import com.google.gerrit.extensions.api.access.PluginPermission
+
+class CollectServerDataPermission(pluginName: String) extends
+  PluginPermission(pluginName, CollectServerDataCapability.COLLECT_SERVER_DATA)
+
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/latest/LatestCapabilityControl.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/latest/LatestCapabilityControl.scala
new file mode 100644
index 0000000..b2430ca
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/latest/LatestCapabilityControl.scala
@@ -0,0 +1,59 @@
+/*
+ * 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.latest
+
+import com.google.gerrit.server.account.CapabilityControl
+import com.googlesource.gerrit.plugins.support.GerritFacade.PluginName
+
+import scala.util.Try
+import com.googlesource.gerrit.plugins.support.TryAll
+
+class LatestCapabilityControl(val capabilityControl: CapabilityControl)(implicit pluginName: PluginName) {
+
+  import LatestCapabilityControl._
+
+  def canPerform(operation: String): Try[Boolean] = TryAll {
+    for (
+      permissionConstructor <- CollectServerDataPermissionConstructor;
+      checkMedhod <- checkPermissionMethod
+    ) yield {
+      val permission = permissionConstructor.newInstance(pluginName.value).asInstanceOf[Object]
+      val result: Object = checkMedhod.invoke(capabilityControl, permission)
+      result.asInstanceOf[Boolean]
+    }
+  }.flatten
+}
+
+object LatestCapabilityControl {
+  lazy val GlobalOrPluginPermissionClass = TryAll {
+    Class.forName("com.google.gerrit.extensions.api.access.GlobalOrPluginPermission")
+  }
+
+  lazy val CollectServerDataPermissionClass = TryAll {
+    Class.forName("com.googlesource.gerrit.plugins.support.latest.CollectServerDataPermission")
+  }
+
+  lazy val CollectServerDataPermissionConstructor = TryAll {
+    CollectServerDataPermissionClass.map(_.getConstructor(classOf[String]))
+  }.flatten
+
+  lazy val checkPermissionMethod = TryAll {
+    GlobalOrPluginPermissionClass.map(classOf[CapabilityControl].getMethod("doCanForDefaultPermissionBackend", _))
+  }.flatten
+
+  def apply(cc: CapabilityControl)(implicit pluginName: PluginName) = new LatestCapabilityControl(cc)
+}
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/legacy/LegacyCapabilityControl.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/legacy/LegacyCapabilityControl.scala
new file mode 100644
index 0000000..b00e988
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/legacy/LegacyCapabilityControl.scala
@@ -0,0 +1,40 @@
+/*
+ * 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.legacy
+
+import com.google.gerrit.server.account.CapabilityControl
+import com.googlesource.gerrit.plugins.support.GerritFacade.PluginName
+import com.googlesource.gerrit.plugins.support.TryAll
+
+import scala.util.Try
+
+class LegacyCapabilityControl(val capabilityControl: CapabilityControl)(implicit pluginName: PluginName) {
+
+  import LegacyCapabilityControl._
+
+  def canPerform(operation: String): Try[Boolean] = TryAll {
+    canPerformMethod.map(_.invoke(capabilityControl, s"${pluginName.value}-$operation").asInstanceOf[Boolean])
+  }.flatten
+}
+
+object LegacyCapabilityControl {
+  lazy val canPerformMethod = TryAll {
+    classOf[CapabilityControl].getMethod("canPerform", classOf[String])
+  }
+
+  def apply(cc: CapabilityControl)(implicit pluginName: PluginName) = new LegacyCapabilityControl(cc)
+}