SetPreferences: Enforce download scheme is registered

Now that the set of allowed schemes is documented, enforce this by
iterating the DynamicMap<DownloadScheme> at runtime.

Unfortunately, acceptance tests for this functionality would not be
straightforward, as we would first have to be able to register
plugins.

Change-Id: I36a982bd8e709e00d962ada635c2b888b15618ff
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
index efa9eed..c7725c5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
@@ -23,7 +23,10 @@
 import static com.google.gerrit.server.account.GetPreferences.URL_ALIAS;
 
 import com.google.common.base.Strings;
+import com.google.gerrit.extensions.config.DownloadScheme;
+import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.TopMenu;
@@ -79,22 +82,27 @@
   private final Provider<ReviewDb> db;
   private final MetaDataUpdate.User metaDataUpdateFactory;
   private final AllUsersName allUsersName;
+  private final DynamicMap<DownloadScheme> downloadSchemes;
 
   @Inject
-  SetPreferences(Provider<CurrentUser> self, AccountCache cache,
-      Provider<ReviewDb> db, MetaDataUpdate.User metaDataUpdateFactory,
-      AllUsersName allUsersName) {
+  SetPreferences(Provider<CurrentUser> self,
+      AccountCache cache,
+      Provider<ReviewDb> db,
+      MetaDataUpdate.User metaDataUpdateFactory,
+      AllUsersName allUsersName,
+      DynamicMap<DownloadScheme> downloadSchemes) {
     this.self = self;
     this.cache = cache;
     this.db = db;
     this.metaDataUpdateFactory = metaDataUpdateFactory;
     this.allUsersName = allUsersName;
+    this.downloadSchemes = downloadSchemes;
   }
 
   @Override
   public GetPreferences.PreferenceInfo apply(AccountResource rsrc, Input i)
-      throws AuthException, ResourceNotFoundException, OrmException,
-      IOException, ConfigInvalidException {
+      throws AuthException, ResourceNotFoundException, BadRequestException,
+      OrmException, IOException, ConfigInvalidException {
     if (self.get() != rsrc.getUser()
         && !self.get().getCapabilities().canModifyAccount()) {
       throw new AuthException("restricted to members of Modify Accounts");
@@ -133,7 +141,7 @@
         p.setUseFlashClipboard(i.useFlashClipboard);
       }
       if (i.downloadScheme != null) {
-        p.setDownloadUrl(i.downloadScheme);
+        setDownloadScheme(p, i.downloadScheme);
       }
       if (i.downloadCommand != null) {
         p.setDownloadCommand(i.downloadCommand);
@@ -224,4 +232,16 @@
       }
     }
   }
+
+  private void setDownloadScheme(AccountGeneralPreferences p, String scheme)
+      throws BadRequestException {
+    for (DynamicMap.Entry<DownloadScheme> e : downloadSchemes) {
+      if (e.getExportName().equals(scheme)
+          && e.getProvider().get().isEnabled()) {
+        p.setDownloadUrl(scheme);
+        return;
+      }
+    }
+    throw new BadRequestException("Unsupported download scheme: " + scheme);
+  }
 }