diff --git a/pom.xml b/pom.xml
index a3b01964f..1058d0e32 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,13 @@
diegossilveira@gmail.com
-3
+
+ ezgraphs
+ C S
+ ezgraphs@gmail.com
+ -3
+
+
@@ -56,17 +63,43 @@
4.8.1
test
+
+
+
+ com.google.code.gson
+ gson
+ 1.7.1
+ compile
+
+
-
-
-
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.2.1
+
+ java
+
+ -classpath
+
+ org.scribe.examples.GooglePlusExample
+
+
+
+
+
+
maven-compiler-plugin
1.5
1.5
+
diff --git a/src/main/java/org/scribe/builder/api/DefaultApi20a.java b/src/main/java/org/scribe/builder/api/DefaultApi20a.java
new file mode 100644
index 000000000..6696abcef
--- /dev/null
+++ b/src/main/java/org/scribe/builder/api/DefaultApi20a.java
@@ -0,0 +1,69 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+/**
+ * Default implementation of the OAuth protocol, version 2.0 (draft 11)
+ *
+ * This class is meant to be extended by concrete implementations of the API,
+ * providing the endpoints and endpoint-http-verbs.
+ *
+ * If your Api adheres to the 2.0 (draft 11) protocol correctly, you just need to extend
+ * this class and define the getters for your endpoints.
+ *
+ * If your Api does something a bit different, you can override the different
+ * extractors or services, in order to fine-tune the process. Please read the
+ * javadocs of the interfaces to get an idea of what to do.
+ *
+ * @author Diego Silveira
+ *
+ */
+public abstract class DefaultApi20a extends DefaultApi20 implements Api
+{
+
+ /**
+ * Returns the access token extractor.
+ *
+ * @return json token extractor
+ */
+ public AccessTokenExtractor getAccessTokenExtractor() {
+ return new JsonTokenExtractor();
+ }
+
+ /**
+ * Returns the verb for the access token endpoint (defaults to GET)
+ *
+ * @return access token endpoint verb
+ */
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.POST;
+ }
+
+ /**
+ * Returns the URL that receives the access token requests.
+ *
+ * @return access token URL
+ */
+ public abstract String getAccessTokenEndpoint();
+
+ /**
+ * Returns the URL where you should redirect your users to authenticate
+ * your application.
+ *
+ * @param config OAuth 2.0 configuration param object
+ * @return the URL where you should redirect your users
+ */
+ public abstract String getAuthorizationUrl(OAuthConfig config);
+
+ /**
+ * {@inheritDoc}
+ */
+ public OAuthService createService(OAuthConfig config)
+ {
+ return new OAuth20aServiceImpl(this, config);
+ }
+
+}
diff --git a/src/main/java/org/scribe/builder/api/GooglePlusApi.java b/src/main/java/org/scribe/builder/api/GooglePlusApi.java
new file mode 100644
index 000000000..83e930ed1
--- /dev/null
+++ b/src/main/java/org/scribe/builder/api/GooglePlusApi.java
@@ -0,0 +1,36 @@
+package org.scribe.builder.api;
+
+import org.scribe.builder.api.DefaultApi20a;
+import org.scribe.extractors.AccessTokenExtractor;
+import org.scribe.extractors.JsonTokenExtractor;
+import org.scribe.model.OAuthConfig;
+import org.scribe.model.Verb;
+import org.scribe.utils.OAuthEncoder;
+
+/**
+ * User: ezgraphs
+ * Date: 12/27/11
+ * Time: 8:54 AM
+ */
+public class GooglePlusApi extends DefaultApi20a {
+
+ private static final String BASE_URL = "https://accounts.google.com/o/oauth2";
+ private static final String AUTHORIZE_URL = BASE_URL + "/auth?response_type=code&client_id=%s&scope=%s&redirect_uri=%s";
+
+
+ @Override
+ public String getAccessTokenEndpoint() {
+
+ return BASE_URL + "/token";
+ }
+
+ @Override
+ public AccessTokenExtractor getAccessTokenExtractor() {
+ return new JsonTokenExtractor();
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config) {
+ return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getScope()), OAuthEncoder.encode(config.getCallback()));
+ }
+}
diff --git a/src/main/java/org/scribe/examples/GooglePlusExample.java b/src/main/java/org/scribe/examples/GooglePlusExample.java
new file mode 100644
index 000000000..e91822139
--- /dev/null
+++ b/src/main/java/org/scribe/examples/GooglePlusExample.java
@@ -0,0 +1,81 @@
+package org.scribe.examples;
+
+import com.google.gson.*;
+import java.util.*;
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+// https://developers.google.com/+/api/
+// https://developers.google.com/+/api/latest/people/get#try-it
+// http://code.google.com/apis/accounts/docs/OAuth2WebServer.html#callinganapi
+
+// https://code.google.com/apis/console/#project:419708088990:quotas
+// https://code.google.com/apis/console/#project:419708088990:access
+// http://sites.google.com/site/gson/gson-user-guide#TOC-Overview
+
+public class GooglePlusExample{
+
+ public static void main(String args[]) throws Exception {
+
+ String apiKey = "419708088990.apps.googleusercontent.com";
+ String secret = "tNpXobmvQ3tM2234BW2OsjXT";
+ String callback = "http://www.r-chart.com";
+ String scope = "https://www.googleapis.com/auth/plus.me";
+
+ OAuthService service = new ServiceBuilder()
+ .provider(GooglePlusApi.class)
+ .apiKey(apiKey)
+ .apiSecret(secret)
+ .callback(callback)
+ .scope(scope)
+ .build();
+
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(null);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ String code = in.nextLine();
+
+ Verifier verifier = new Verifier(code);
+ System.out.println("Trading the Request Token for an Access Token...");
+
+ Token accessToken = service.getAccessToken(null, verifier);
+
+ System.out.println("Now we're going to access a protected resource...creating request");
+ String url = "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + accessToken.getToken();
+ System.out.println("Trying userInfo url: " + url);
+ OAuthRequest request = new OAuthRequest(Verb.GET, url);
+
+ System.out.println("Sending request... getting response");
+
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ String b = response.getBody();
+ System.out.println(b);
+
+ String id = extractId(b);
+ System.out.println("Sending request... getting response");
+ request = new OAuthRequest(Verb.GET, "https://www.googleapis.com/plus/v1/people/me?access_token=" + accessToken.getToken());
+ response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ }
+
+ public static String extractId(String body) {
+ JsonParser parser = new JsonParser();
+ JsonElement e = parser.parse(body);
+ return e.getAsJsonObject().get("id").getAsString();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/scribe/extractors/JsonTokenExtractor.java b/src/main/java/org/scribe/extractors/JsonTokenExtractor.java
index 7c1ee04e1..5bec42379 100644
--- a/src/main/java/org/scribe/extractors/JsonTokenExtractor.java
+++ b/src/main/java/org/scribe/extractors/JsonTokenExtractor.java
@@ -10,7 +10,6 @@ public class JsonTokenExtractor implements AccessTokenExtractor
{
private Pattern accessTokenPattern = Pattern.compile("\"access_token\":\\s*\"(\\S*?)\"");
- @Override
public Token extract(String response)
{
Preconditions.checkEmptyString(response, "Cannot extract a token from a null or empty String");
diff --git a/src/main/java/org/scribe/oauth/OAuth20aServiceImpl.java b/src/main/java/org/scribe/oauth/OAuth20aServiceImpl.java
new file mode 100644
index 000000000..6bb9a1184
--- /dev/null
+++ b/src/main/java/org/scribe/oauth/OAuth20aServiceImpl.java
@@ -0,0 +1,73 @@
+package org.scribe.oauth;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import org.scribe.builder.api.DefaultApi20a;
+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.OAuth20ServiceImpl;
+import org.scribe.oauth.OAuthService;
+
+/**
+ * User: ezgraphs
+ * Date: 12/27/11
+ * Time: 11:16 AM
+ */
+public class OAuth20aServiceImpl extends OAuth20ServiceImpl implements OAuthService {
+
+ private final DefaultApi20a api;
+ private final OAuthConfig config;
+
+ /**
+ * Replicate api and config variables and assignment
+ * since the superclass declares these private
+ *
+ * @param api
+ * @param config
+ */
+ public OAuth20aServiceImpl(DefaultApi20 api, OAuthConfig config) {
+ super(api, config);
+ this.api = (DefaultApi20a) api;
+ this.config = config;
+ }
+
+ /**
+ * The method overwritten below was required because parameters are body parameters in the
+ * Google version of the API. In addition, a body parameter of type grant_type is needed.
+ *
+ * {@inheritDoc}
+ */
+ public Token getAccessToken(Token requestToken, Verifier verifier) {
+ OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
+
+ request.addBodyParameter("grant_type", "authorization_code");
+ request.addBodyParameter(OAuthConstants.CODE, verifier.getValue());
+ request.addBodyParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
+ request.addBodyParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
+ request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
+ if (config.hasScope()) request.addBodyParameter(OAuthConstants.SCOPE, config.getScope());
+ Response response = request.send();
+ String body = response.getBody();
+ System.out.println("body:\n" + body);
+ return extract(body);
+ }
+
+ /**
+ * @param body
+ *
+ * @return
+ */
+ private Token extract(String body) {
+ JsonParser parser = new JsonParser();
+ JsonElement e = parser.parse(body);
+
+ String accessToken = e.getAsJsonObject().get("access_token").getAsString();
+ String id = e.getAsJsonObject().get("id_token").getAsString();
+ return new Token(accessToken, id);
+ }
+}
\ No newline at end of file