Refactoring of duplicated code

Change-Id: Id47d30495f5983679f8aef0fe4c5039a1d81365e
diff --git a/.gitignore b/.gitignore
index 446fb07..898d584 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
 /bazel-oauth
 /bazel-out
 /bazel-testlogs
+/.idea
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/CasApi.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/CasApi.java
index 3ae65dc..76d4011 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/CasApi.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/CasApi.java
@@ -16,12 +16,7 @@
 
 import org.scribe.builder.api.DefaultApi20;
 import org.scribe.model.OAuthConfig;
-import org.scribe.model.OAuthConstants;
-import org.scribe.model.OAuthRequest;
-import org.scribe.model.Response;
-import org.scribe.model.Token;
 import org.scribe.model.Verb;
-import org.scribe.model.Verifier;
 import org.scribe.oauth.OAuthService;
 import org.scribe.utils.OAuthEncoder;
 
@@ -53,54 +48,6 @@
 
   @Override
   public OAuthService createService(OAuthConfig config) {
-    return new CasOAuthService(this, config);
-  }
-
-  private static final class CasOAuthService implements OAuthService {
-    private static final String VERSION = "2.0";
-    private static final String GRANT_TYPE = "grant_type";
-    private static final String GRANT_TYPE_VALUE = "authorization_code";
-
-    private final DefaultApi20 api;
-    private final OAuthConfig config;
-
-    private CasOAuthService(DefaultApi20 api, OAuthConfig config) {
-      this.config = config;
-      this.api = api;
-    }
-
-    @Override
-    public Token getAccessToken(Token token, Verifier verifier) {
-      OAuthRequest request =
-          new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
-      request.addBodyParameter(GRANT_TYPE, GRANT_TYPE_VALUE);
-      request.addBodyParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
-      request.addBodyParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
-      request.addBodyParameter(OAuthConstants.CODE, verifier.getValue());
-      request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
-      Response response = request.send();
-      return api.getAccessTokenExtractor().extract(response.getBody());
-    }
-
-    @Override
-    public Token getRequestToken() {
-      throw new UnsupportedOperationException(
-          "Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
-    }
-
-    @Override
-    public String getVersion() {
-      return VERSION;
-    }
-
-    @Override
-    public void signRequest(Token token, OAuthRequest request) {
-      request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, token.getToken());
-    }
-
-    @Override
-    public String getAuthorizationUrl(Token token) {
-      return api.getAuthorizationUrl(config);
-    }
+    return new OAuth20ServiceImpl(this, config);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/DexApi.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/DexApi.java
index 389dd8e..2386e24 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/DexApi.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/DexApi.java
@@ -18,12 +18,7 @@
 import org.scribe.extractors.AccessTokenExtractor;
 import org.scribe.extractors.JsonTokenExtractor;
 import org.scribe.model.OAuthConfig;
-import org.scribe.model.OAuthConstants;
-import org.scribe.model.OAuthRequest;
-import org.scribe.model.Response;
-import org.scribe.model.Token;
 import org.scribe.model.Verb;
-import org.scribe.model.Verifier;
 import org.scribe.oauth.OAuthService;
 import org.scribe.utils.OAuthEncoder;
 
@@ -60,77 +55,11 @@
 
   @Override
   public OAuthService createService(OAuthConfig config) {
-    // TODO can't use this until updating to newer scribe lib
-    // return new OAuth20ServiceImpl(this,config);
-    return new DexOAuthService(this, config);
+    return new OAuth20ServiceImpl(this, config);
   }
 
   @Override
   public AccessTokenExtractor getAccessTokenExtractor() {
     return new JsonTokenExtractor();
   }
-
-  private static final class DexOAuthService implements OAuthService {
-
-    private static final String VERSION = "2.0";
-
-    private static final String GRANT_TYPE = "grant_type";
-    private static final String GRANT_TYPE_VALUE = "authorization_code";
-
-    private final DefaultApi20 api;
-    private final OAuthConfig config;
-
-    /**
-     * Default constructor
-     *
-     * @param api OAuth2.0 api information
-     * @param config OAuth 2.0 configuration param object
-     */
-    public DexOAuthService(DefaultApi20 api, OAuthConfig config) {
-      this.api = api;
-      this.config = config;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public Token getAccessToken(Token requestToken, Verifier verifier) {
-      OAuthRequest request =
-          new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
-      request.addBodyParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
-      request.addBodyParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
-      request.addBodyParameter(OAuthConstants.CODE, verifier.getValue());
-      request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
-      if (config.hasScope()) {
-        request.addBodyParameter(OAuthConstants.SCOPE, config.getScope());
-      }
-      request.addBodyParameter(GRANT_TYPE, GRANT_TYPE_VALUE);
-      Response response = request.send();
-      return api.getAccessTokenExtractor().extract(response.getBody());
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public Token getRequestToken() {
-      throw new UnsupportedOperationException(
-          "Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String getVersion() {
-      return VERSION;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void signRequest(Token accessToken, OAuthRequest request) {
-      request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken());
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String getAuthorizationUrl(Token requestToken) {
-      return api.getAuthorizationUrl(config);
-    }
-  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitLabApi.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitLabApi.java
index 898fbcc..2c27f35 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitLabApi.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitLabApi.java
@@ -20,12 +20,8 @@
 import org.scribe.exceptions.OAuthException;
 import org.scribe.extractors.AccessTokenExtractor;
 import org.scribe.model.OAuthConfig;
-import org.scribe.model.OAuthConstants;
-import org.scribe.model.OAuthRequest;
-import org.scribe.model.Response;
 import org.scribe.model.Token;
 import org.scribe.model.Verb;
-import org.scribe.model.Verifier;
 import org.scribe.oauth.OAuthService;
 import org.scribe.utils.Preconditions;
 
@@ -56,7 +52,7 @@
 
   @Override
   public OAuthService createService(OAuthConfig config) {
-    return new GitLabOAuthService(this, config);
+    return new OAuth20ServiceImpl(this, config);
   }
 
   @Override
@@ -64,69 +60,6 @@
     return new GitLabJsonTokenExtractor();
   }
 
-  private static final class GitLabOAuthService implements OAuthService {
-    private static final String VERSION = "2.0";
-
-    private static final String GRANT_TYPE = "grant_type";
-    private static final String GRANT_TYPE_VALUE = "authorization_code";
-
-    private final DefaultApi20 api;
-    private final OAuthConfig config;
-
-    /**
-     * Default constructor
-     *
-     * @param api OAuth2.0 api information
-     * @param config OAuth 2.0 configuration param object
-     */
-    public GitLabOAuthService(DefaultApi20 api, OAuthConfig config) {
-      this.api = api;
-      this.config = config;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public Token getAccessToken(Token requestToken, Verifier verifier) {
-      OAuthRequest request =
-          new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
-      request.addBodyParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
-      request.addBodyParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
-      request.addBodyParameter(OAuthConstants.CODE, verifier.getValue());
-      request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
-      if (config.hasScope()) {
-        request.addBodyParameter(OAuthConstants.SCOPE, config.getScope());
-      }
-      request.addBodyParameter(GRANT_TYPE, GRANT_TYPE_VALUE);
-      Response response = request.send();
-      return api.getAccessTokenExtractor().extract(response.getBody());
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public Token getRequestToken() {
-      throw new UnsupportedOperationException(
-          "Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String getVersion() {
-      return VERSION;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void signRequest(Token accessToken, OAuthRequest request) {
-      request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken());
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String getAuthorizationUrl(Token requestToken) {
-      return api.getAuthorizationUrl(config);
-    }
-  }
-
   private static final class GitLabJsonTokenExtractor implements AccessTokenExtractor {
     private Pattern accessTokenPattern = Pattern.compile("\"access_token\"\\s*:\\s*\"(\\S*?)\"");
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/Google2Api.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/Google2Api.java
index 3db9dbf..ed48549 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/Google2Api.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/Google2Api.java
@@ -22,12 +22,8 @@
 import org.scribe.exceptions.OAuthException;
 import org.scribe.extractors.AccessTokenExtractor;
 import org.scribe.model.OAuthConfig;
-import org.scribe.model.OAuthConstants;
-import org.scribe.model.OAuthRequest;
-import org.scribe.model.Response;
 import org.scribe.model.Token;
 import org.scribe.model.Verb;
-import org.scribe.model.Verifier;
 import org.scribe.oauth.OAuthService;
 import org.scribe.utils.Preconditions;
 
@@ -61,7 +57,7 @@
 
   @Override
   public OAuthService createService(OAuthConfig config) {
-    return new GoogleOAuthService(this, config);
+    return new OAuth20ServiceImpl(this, config);
   }
 
   @Override
@@ -69,67 +65,6 @@
     return new GoogleJsonTokenExtractor();
   }
 
-  private static final class GoogleOAuthService implements OAuthService {
-    private static final String VERSION = "2.0";
-
-    private static final String GRANT_TYPE = "grant_type";
-    private static final String GRANT_TYPE_VALUE = "authorization_code";
-
-    private final DefaultApi20 api;
-    private final OAuthConfig config;
-
-    /**
-     * Default constructor
-     *
-     * @param api OAuth2.0 api information
-     * @param config OAuth 2.0 configuration param object
-     */
-    public GoogleOAuthService(DefaultApi20 api, OAuthConfig config) {
-      this.api = api;
-      this.config = config;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public Token getAccessToken(Token requestToken, Verifier verifier) {
-      OAuthRequest request =
-          new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
-      request.addBodyParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
-      request.addBodyParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
-      request.addBodyParameter(OAuthConstants.CODE, verifier.getValue());
-      request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
-      if (config.hasScope()) request.addBodyParameter(OAuthConstants.SCOPE, config.getScope());
-      request.addBodyParameter(GRANT_TYPE, GRANT_TYPE_VALUE);
-      Response response = request.send();
-      return api.getAccessTokenExtractor().extract(response.getBody());
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public Token getRequestToken() {
-      throw new UnsupportedOperationException(
-          "Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String getVersion() {
-      return VERSION;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void signRequest(Token accessToken, OAuthRequest request) {
-      request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken());
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String getAuthorizationUrl(Token requestToken) {
-      return api.getAuthorizationUrl(config);
-    }
-  }
-
   private static final class GoogleJsonTokenExtractor implements AccessTokenExtractor {
     private Pattern accessTokenPattern = Pattern.compile("\"access_token\"\\s*:\\s*\"(\\S*?)\"");
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/OAuth20ServiceImpl.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/OAuth20ServiceImpl.java
new file mode 100644
index 0000000..a9eaddb
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/OAuth20ServiceImpl.java
@@ -0,0 +1,83 @@
+// 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.oauth;
+
+import org.scribe.builder.api.DefaultApi20;
+import org.scribe.model.OAuthConfig;
+import org.scribe.model.OAuthConstants;
+import org.scribe.model.OAuthRequest;
+import org.scribe.model.Response;
+import org.scribe.model.Token;
+import org.scribe.model.Verifier;
+import org.scribe.oauth.OAuthService;
+
+/** TODO(gildur): remove when updating to newer scribe lib */
+final class OAuth20ServiceImpl implements OAuthService {
+
+  private static final String VERSION = "2.0";
+
+  private static final String GRANT_TYPE = "grant_type";
+  private static final String GRANT_TYPE_VALUE = "authorization_code";
+
+  private final DefaultApi20 api;
+  private final OAuthConfig config;
+
+  /**
+   * Default constructor
+   *
+   * @param api OAuth2.0 api information
+   * @param config OAuth 2.0 configuration param object
+   */
+  public OAuth20ServiceImpl(DefaultApi20 api, OAuthConfig config) {
+    this.api = api;
+    this.config = config;
+  }
+
+  @Override
+  public Token getAccessToken(Token requestToken, Verifier verifier) {
+    OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
+    request.addBodyParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
+    request.addBodyParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
+    request.addBodyParameter(OAuthConstants.CODE, verifier.getValue());
+    request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
+    if (config.hasScope()) {
+      request.addBodyParameter(OAuthConstants.SCOPE, config.getScope());
+    }
+    request.addBodyParameter(GRANT_TYPE, GRANT_TYPE_VALUE);
+    Response response = request.send();
+    return api.getAccessTokenExtractor().extract(response.getBody());
+  }
+
+  @Override
+  public Token getRequestToken() {
+    throw new UnsupportedOperationException(
+        "Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
+  }
+
+  @Override
+  public String getVersion() {
+    return VERSION;
+  }
+
+  @Override
+  public void signRequest(Token accessToken, OAuthRequest request) {
+    request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken());
+  }
+
+  @Override
+  public String getAuthorizationUrl(Token requestToken) {
+    return api.getAuthorizationUrl(config);
+  }
+}