Permalink
Browse files

google social button introduced

  • Loading branch information...
1 parent 5dead0f commit 561e0306e40ddc646386a897075aacea84ab7673 @sody committed Jan 20, 2012
Showing with 653 additions and 57 deletions.
  1. +9 −3 tapestry/tapestry-jquery/pom.xml
  2. +2 −1 tapestry/tapestry-jquery/src/main/java/com/example/components/FacebookConnect.java
  3. +154 −0 tapestry/tapestry-jquery/src/main/java/com/example/components/GoogleConnect.java
  4. +1 −0 tapestry/tapestry-jquery/src/main/java/com/example/components/TwitterConnect.java
  5. +25 −0 tapestry/tapestry-jquery/src/main/java/com/example/internal/google/Google.java
  6. +22 −0 tapestry/tapestry-jquery/src/main/java/com/example/internal/google/GoogleModule.java
  7. +18 −0 tapestry/tapestry-jquery/src/main/java/com/example/internal/google/GoogleOAuth2Template.java
  8. +97 −0 tapestry/tapestry-jquery/src/main/java/com/example/internal/google/GoogleProfile.java
  9. +43 −0 tapestry/tapestry-jquery/src/main/java/com/example/internal/google/GoogleProfileMixin.java
  10. +21 −0 tapestry/tapestry-jquery/src/main/java/com/example/internal/google/GoogleServiceProvider.java
  11. +58 −0 tapestry/tapestry-jquery/src/main/java/com/example/internal/google/GoogleTemplate.java
  12. +21 −0 tapestry/tapestry-jquery/src/main/java/com/example/internal/google/UserOperations.java
  13. +91 −0 tapestry/tapestry-jquery/src/main/java/com/example/internal/google/UserTemplate.java
  14. +27 −2 tapestry/tapestry-jquery/src/main/java/com/example/pages/Social.java
  15. +19 −4 tapestry/tapestry-jquery/src/main/java/com/example/services/UIModule.java
  16. +45 −47 tapestry/tapestry-jquery/src/main/resources/com/example/pages/Social.tml
@@ -65,19 +65,25 @@
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-facebook</artifactId>
- <version>1.0.0.RELEASE</version>
+ <version>1.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-twitter</artifactId>
- <version>1.0.0.RELEASE</version>
+ <version>1.0.1.RELEASE</version>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>3.1.0.RELEASE</version>
+ </dependency>
+
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
- <version>3.1.0.RC3</version>
+ <version>3.1.0.RELEASE</version>
</dependency>
<dependency>
@@ -117,7 +117,7 @@ Object connected(
if (code != null) {
final AccessGrant accessGrant;
try {
- // request for access token from twitter
+ // request for access token from facebook
accessGrant = facebookService.getOAuthOperations().exchangeForAccess(code, getRedirectUri(), null);
// create success even context
final Object[] context = {accessGrant.getAccessToken()};
@@ -131,6 +131,7 @@ Object connected(
return null;
} catch (Exception e) {
// error occurs, so failure event will be triggered
+ e.printStackTrace();
}
}
@@ -0,0 +1,154 @@
+package com.example.components;
+
+import com.example.internal.google.Google;
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.Link;
+import org.apache.tapestry5.annotations.Cached;
+import org.apache.tapestry5.annotations.OnEvent;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.RequestParameter;
+import org.apache.tapestry5.corelib.base.AbstractComponentEventLink;
+import org.apache.tapestry5.internal.util.CaptureResultCallback;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.ioc.annotations.InjectService;
+import org.springframework.social.oauth2.AccessGrant;
+import org.springframework.social.oauth2.GrantType;
+import org.springframework.social.oauth2.OAuth2Parameters;
+import org.springframework.social.oauth2.OAuth2ServiceProvider;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * This component represents link that connects users to their google accounts using OAuth2 protocol. After clicking
+ * this link users will be redirected to google authorization page and then returned back to the page where they come
+ * from. After google authorization this component triggers {@link EventConstants#SUCCESS} or
+ * {@link EventConstants#FAILURE} events according to authorization result. Success event comes with access token
+ * as event context, so developers can then use it to access google api.
+ *
+ * @author Ivan Khalopik
+ * @since 1.0
+ */
+public class GoogleConnect extends AbstractComponentEventLink {
+ private static final String CONNECT_EVENT = "connect";
+ private static final String CONNECTED_EVENT = "connected";
+
+ /**
+ * This parameter defines OAuth2 application scope.
+ */
+ @Parameter(defaultPrefix = BindingConstants.LITERAL)
+ private String scope;
+
+ @Inject
+ private ComponentResources resources;
+
+ /**
+ * Injected spring-social OAuth2 service for facebook. It should be configured somewhere in application modules.
+ */
+ @InjectService("googleService")
+ private OAuth2ServiceProvider<Google> googleService;
+
+ /**
+ * Generates OAuth2 redirectUri as event link to current component with internal {@code 'connected'} event.
+ * This event will be processed inside this component later.
+ *
+ * @return OAuth2 redirectUri
+ */
+ @Cached
+ protected String getRedirectUri() {
+ return resources.createEventLink(CONNECTED_EVENT).toAbsoluteURI();
+ }
+
+ /**
+ * Generates component link that will present on html markup as a connect URL. This link will produce internal
+ * {@code 'connect'} event. Then this event will be processed by this component to generate correct facebook
+ * authorization URL.
+ *
+ * @param eventContext event context
+ * @return link that will present on html markup as a connect URL
+ */
+ @Override
+ protected Link createLink(final Object[] eventContext) {
+ return resources.createEventLink(CONNECT_EVENT);
+ }
+
+ /**
+ * Event handler for internal {@code 'connect'} event. Generates correct google authorization URL with all needed
+ * parameters.
+ *
+ * @return google authorization URL
+ * @throws MalformedURLException for incorrect URL produced by google service
+ */
+ @OnEvent(CONNECT_EVENT)
+ URL connect() throws MalformedURLException {
+ // generate oauth parameters with redirect uri
+ final OAuth2Parameters parameters = new OAuth2Parameters();
+ if (scope != null) {
+ parameters.setScope(scope);
+ }
+ parameters.setRedirectUri(getRedirectUri());
+ // build and return connection url as redirect response
+ return new URL(buildConnectURL(parameters));
+ }
+
+ /**
+ * Event handler for internal {@code 'connected'} event. Processes reply came from google authorization page. If
+ * access was granted then it tries to get OAuth2 access token and triggers {@link EventConstants#SUCCESS} event with
+ * access token as event context. If access was denied or error occurs while getting access token then
+ * {@link EventConstants#FAILURE} event will be triggered.
+ *
+ * @param code authorized OAuth token came from google
+ * @param error error came from google
+ * @return result came from container for triggered events or null if was not processed.
+ */
+ @OnEvent(CONNECTED_EVENT)
+ Object connected(
+ @RequestParameter(value = "code", allowBlank = true) final String code,
+ @RequestParameter(value = "error", allowBlank = true) final String error) {
+
+ final CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>();
+ // null code means that access was not granted
+ if (code != null) {
+ final AccessGrant accessGrant;
+ try {
+ // request for access token from google
+ accessGrant = googleService.getOAuthOperations().exchangeForAccess(code, getRedirectUri(), null);
+ // create success even context
+ final Object[] context = {accessGrant.getAccessToken()};
+ // trigger success event
+ final boolean handled = resources.triggerEvent(EventConstants.SUCCESS, context, callback);
+ // if event was processed return result
+ if (handled) {
+ return callback.getResult();
+ }
+ // return null if not processed
+ return null;
+ } catch (Exception e) {
+ // error occurs, so failure event will be triggered
+ e.printStackTrace();
+ }
+ }
+
+ final Object[] context = {error};
+ // handle failure event if access was denied or error occurs while requesting access token
+ final boolean handled = resources.triggerEvent(EventConstants.FAILURE, context, callback);
+ // if event was processed return result
+ if (handled) {
+ return callback.getResult();
+ }
+ // return null if not processed
+ return null;
+ }
+
+ /**
+ * Generates OAuth2 authorization URL according to specified parameters.
+ *
+ * @param parameters OAuth2 parameters
+ * @return OAuth2 authorization URL
+ */
+ private String buildConnectURL(final OAuth2Parameters parameters) {
+ return googleService.getOAuthOperations().buildAuthorizeUrl(GrantType.AUTHORIZATION_CODE, parameters);
+ }
+}
@@ -127,6 +127,7 @@ Object connected(
return null;
} catch (Exception e) {
// error occurs, so failure event will be triggered
+ e.printStackTrace();
}
}
@@ -0,0 +1,25 @@
+package com.example.internal.google;
+
+import org.springframework.social.ApiBinding;
+
+/**
+ * Interface specifying a basic set of operations for interacting with Google APIs.
+ *
+ * @author Ivan Khalopik
+ * @since 1.0
+ */
+public interface Google extends ApiBinding {
+
+ /**
+ * Base Google APIs URL.
+ */
+ String API_URL_BASE = "https://www.googleapis.com/oauth2/v2/";
+
+ /**
+ * API for performing operations on Google user profiles.
+ *
+ * @return google user profiles operations, not {@code null}
+ */
+ UserOperations userOperations();
+
+}
@@ -0,0 +1,22 @@
+package com.example.internal.google;
+
+import org.codehaus.jackson.Version;
+import org.codehaus.jackson.map.module.SimpleModule;
+
+/**
+ * Jackson module for setting up mixin annotations on Google model types. This enables the use of Jackson annotations
+ * without directly annotating the model classes themselves.
+ *
+ * @author Ivan Khalopik
+ * @since 1.0
+ */
+public class GoogleModule extends SimpleModule {
+ public GoogleModule() {
+ super("GoogleModule", new Version(1, 0, 0, "alpha-1"));
+ }
+
+ @Override
+ public void setupModule(final SetupContext context) {
+ context.setMixInAnnotations(GoogleProfile.class, GoogleProfileMixin.class);
+ }
+}
@@ -0,0 +1,18 @@
+package com.example.internal.google;
+
+import org.springframework.social.oauth2.OAuth2Template;
+
+/**
+ * This class represents Google-specific extension of OAuth2Template.
+ *
+ * @author Ivan Khalopik
+ * @since 1.0
+ */
+public class GoogleOAuth2Template extends OAuth2Template {
+ private static final String AUTHORIZE_URL = "https://accounts.google.com/o/oauth2/auth";
+ private static final String ACCESS_TOKEN_URL = "https://accounts.google.com/o/oauth2/token";
+
+ public GoogleOAuth2Template(final String clientId, final String clientSecret) {
+ super(clientId, clientSecret, AUTHORIZE_URL, ACCESS_TOKEN_URL);
+ }
+}
@@ -0,0 +1,97 @@
+package com.example.internal.google;
+
+import java.io.Serializable;
+import java.util.Locale;
+
+/**
+ * This class represents model containing a Google user's profile information.
+ *
+ * @author Ivan Khalopik
+ * @since 1.0
+ */
+public class GoogleProfile implements Serializable {
+ private final String id;
+ private String name;
+ private String givenName;
+ private String familyName;
+ private String gender;
+ private Locale locale;
+ private String link;
+ private String pictureUrl;
+
+ public GoogleProfile(final String id) {
+ this.id = id;
+ }
+
+ /**
+ * Gets user's Google ID.
+ *
+ * @return user's Google ID, not {@code null}
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Gets user's full name.
+ *
+ * @return user's full name, can be {@code null}
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets user's first name.
+ *
+ * @return user's first name, can be {@code null}
+ */
+ public String getGivenName() {
+ return givenName;
+ }
+
+ /**
+ * Gets user's last name.
+ *
+ * @return user's last name, can be {@code null}
+ */
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ /**
+ * Gets user's gender.
+ *
+ * @return user's gender, can be {@code null}
+ */
+ public String getGender() {
+ return gender;
+ }
+
+ /**
+ * Gets user's locale.
+ *
+ * @return user's locale, can be {@code null}
+ */
+ public Locale getLocale() {
+ return locale;
+ }
+
+ /**
+ * Gets link to the user's profile on Google.
+ *
+ * @return user's profile link, can be {@code null}
+ */
+ public String getLink() {
+ return link;
+ }
+
+ /**
+ * Gets user's profile picture as a url.
+ *
+ * @return user's profile picture url, can be {@code null}
+ */
+ public String getPictureUrl() {
+ return pictureUrl;
+ }
+}
Oops, something went wrong.

0 comments on commit 561e030

Please sign in to comment.