GeezerVison is showing github.com — Add Salesforce API · crazycode/scribejava@821bc7c
File treeExpand file treeCollapse file tree Open diff view settings main/java/com/github/scribejava/apis test/java/com/github/scribejava/apis/examples
Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: README.md +1Lines changed: 1 addition & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -47,6 +47,7 @@ You can use ning async http client out-of-box, just use ServiceBuilderAsync | 47 | 47 | * Pinterest (https://www.pinterest.com/) | 48 | 48 | * 500px (https://500px.com/) | 49 | 49 | * Renren (http://renren.com/) | | 50 | +* Salesforce (https://www.salesforce.com/) | 50 | 51 | * Sina (http://www.sina.com.cn/ http://weibo.com/login.php) | 51 | 52 | * Skyrock (http://skyrock.com/) | 52 | 53 | * sohu 搜狐 (http://www.sohu.com/) | |
Collapse file Copy file name to clipboardExpand all lines: changelog +3Lines changed: 3 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +[SNAPSHOT] | | 2 | + * add Salesforce API | | 3 | + | 1 | 4 | [2.7.3] | 2 | 5 | * FIX: ScribeJava shouldn't require all async http client provider to be on the classpath if using only one of them | 3 | 6 |
| |
Collapse file Copy file name to clipboard +115Lines changed: 115 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +package com.github.scribejava.apis; | | 2 | + | | 3 | +import javax.net.ssl.SSLContext; | | 4 | + | | 5 | +import com.github.scribejava.apis.salesforce.SalesforceJsonTokenExtractor; | | 6 | +import com.github.scribejava.core.builder.api.DefaultApi20; | | 7 | +import com.github.scribejava.core.extractors.TokenExtractor; | | 8 | +import com.github.scribejava.core.model.OAuth2AccessToken; | | 9 | +import com.github.scribejava.core.model.Verb; | | 10 | +import java.io.IOException; | | 11 | +import java.security.KeyManagementException; | | 12 | +import java.security.NoSuchAlgorithmException; | | 13 | +import javax.net.ssl.SSLSocket; | | 14 | + | | 15 | +/** | | 16 | + * This class is an implementation of the Salesforce OAuth2 API. | | 17 | + */ | | 18 | +public class SalesforceApi extends DefaultApi20 { | | 19 | + | | 20 | + private static final String BASE_URL = "https://login.salesforce.com/services/oauth2"; | | 21 | + private static final String ACCESS_URL = BASE_URL + "/token"; | | 22 | + private static final String AUTHORIZE_URL = BASE_URL + "/authorize"; | | 23 | + | | 24 | + protected SalesforceApi() { | | 25 | + | | 26 | + try { | | 27 | + final SSLSocket socket = (SSLSocket) SSLContext.getDefault().getSocketFactory().createSocket(); | | 28 | + if (!isTLSv11orUpperEnabled(socket)) { | | 29 | + throw new IllegalStateException("Salesforce API required to use TLSv1.1 or upper. " | | 30 | + + "Enabled it by invoking method initTLSv11orUpper or somehow else"); | | 31 | + } | | 32 | + } catch (NoSuchAlgorithmException | IOException ex) { | | 33 | + throw new IllegalStateException("Salesforce API required to use TLSv1.1 or upper. " | | 34 | + + "Enabled it by invoking method initTLSv11orUpper or somehow else"); | | 35 | + } | | 36 | + } | | 37 | + | | 38 | + private static class InstanceHolder { | | 39 | + | | 40 | + private static final SalesforceApi INSTANCE = new SalesforceApi(); | | 41 | + } | | 42 | + | | 43 | + public static SalesforceApi instance() { | | 44 | + return InstanceHolder.INSTANCE; | | 45 | + } | | 46 | + | | 47 | + @Override | | 48 | + public Verb getAccessTokenVerb() { | | 49 | + return Verb.POST; | | 50 | + } | | 51 | + | | 52 | + @Override | | 53 | + public String getAccessTokenEndpoint() { | | 54 | + return ACCESS_URL; | | 55 | + } | | 56 | + | | 57 | + @Override | | 58 | + protected String getAuthorizationBaseUrl() { | | 59 | + return AUTHORIZE_URL; | | 60 | + } | | 61 | + | | 62 | + @Override | | 63 | + public TokenExtractor<OAuth2AccessToken> getAccessTokenExtractor() { | | 64 | + return SalesforceJsonTokenExtractor.instance(); | | 65 | + } | | 66 | + | | 67 | + private static boolean isTLSv11orUpperEnabled(final SSLSocket socket) { | | 68 | + for (String protocol : socket.getEnabledProtocols()) { | | 69 | + if ("TLSv1.2".equals(protocol) || "TLSv1.1".equals(protocol)) { | | 70 | + return true; | | 71 | + } | | 72 | + } | | 73 | + return false; | | 74 | + } | | 75 | + | | 76 | + /** | | 77 | + * Salesforce API required to use TLSv1.1 or upper. | | 78 | + * <p> | | 79 | + * Java 8 have TLS 1.2 enabled by default. java 7 - no, you should invoke this method or turn TLS>=1.1 somehow | | 80 | + * else</p> | | 81 | + * | | 82 | + * @throws java.security.NoSuchAlgorithmException in case your jvm doesn't support TLSv1.1 and TLSv1.2 | | 83 | + * @throws java.security.KeyManagementException | | 84 | + * @throws java.io.IOException | | 85 | + */ | | 86 | + public static void initTLSv11orUpper() throws NoSuchAlgorithmException, KeyManagementException, IOException { | | 87 | + final SSLSocket socket = (SSLSocket) SSLContext.getDefault().getSocketFactory().createSocket(); | | 88 | + if (isTLSv11orUpperEnabled(socket)) { | | 89 | + return; | | 90 | + } | | 91 | + boolean supportTLSv11 = false; | | 92 | + boolean supportTLSv12 = false; | | 93 | + for (String protocol : socket.getSupportedProtocols()) { | | 94 | + if ("TLSv1.2".equals(protocol)) { | | 95 | + supportTLSv12 = true; | | 96 | + break; | | 97 | + } | | 98 | + if ("TLSv1.1".equals(protocol)) { | | 99 | + supportTLSv11 = true; | | 100 | + } | | 101 | + } | | 102 | + | | 103 | + final SSLContext context; | | 104 | + if (supportTLSv12) { | | 105 | + context = SSLContext.getInstance("TLSv1.2"); | | 106 | + } else if (supportTLSv11) { | | 107 | + context = SSLContext.getInstance("TLSv1.1"); | | 108 | + } else { | | 109 | + throw new NoSuchAlgorithmException("for Salesforce API to work you need jvm with TLS 1.1 or 1.2 support"); | | 110 | + } | | 111 | + | | 112 | + context.init(null, null, null); | | 113 | + SSLContext.setDefault(context); | | 114 | + } | | 115 | +} |
Collapse file Copy file name to clipboardExpand all lines: scribejava-apis/src/main/java/com/github/scribejava/apis/google/GoogleJsonTokenExtractor.java +1-2Lines changed: 1 addition & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | package com.github.scribejava.apis.google; | 2 | 2 |
| 3 | 3 | import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; | 4 | | -import com.github.scribejava.core.model.OAuth2AccessToken; | 5 | 4 |
| 6 | 5 | /** | 7 | 6 | * additionally parses OpenID id_token | @@ -23,7 +22,7 @@ public static GoogleJsonTokenExtractor instance() { | 23 | 22 | } | 24 | 23 |
| 25 | 24 | @Override | 26 | | - protected OAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, | | 25 | + protected GoogleToken createToken(String accessToken, String tokenType, Integer expiresIn, | 27 | 26 | String refreshToken, String scope, String response) { | 28 | 27 | return new GoogleToken(accessToken, tokenType, expiresIn, refreshToken, scope, | 29 | 28 | extractParameter(response, ID_TOKEN_REGEX, false), response); | |
Collapse file Copy file name to clipboardExpand all lines: scribejava-apis/src/main/java/com/github/scribejava/apis/google/GoogleToken.java +4-21Lines changed: 4 additions & 21 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -34,12 +34,7 @@ public String getOpenIdToken() { | 34 | 34 |
| 35 | 35 | @Override | 36 | 36 | public int hashCode() { | 37 | | - int hash = 5; | 38 | | - hash = 37 * hash + Objects.hashCode(getAccessToken()); | 39 | | - hash = 37 * hash + Objects.hashCode(getTokenType()); | 40 | | - hash = 37 * hash + Objects.hashCode(getExpiresIn()); | 41 | | - hash = 37 * hash + Objects.hashCode(getRefreshToken()); | 42 | | - hash = 37 * hash + Objects.hashCode(getScope()); | | 37 | + int hash = super.hashCode(); | 43 | 38 | hash = 37 * hash + Objects.hashCode(openIdToken); | 44 | 39 | return hash; | 45 | 40 | } | @@ -55,23 +50,11 @@ public boolean equals(Object obj) { | 55 | 50 | if (getClass() != obj.getClass()) { | 56 | 51 | return false; | 57 | 52 | } | 58 | | - final GoogleToken other = (GoogleToken) obj; | 59 | | - if (!Objects.equals(getAccessToken(), other.getAccessToken())) { | | 53 | + if (!super.equals(obj)) { | 60 | 54 | return false; | 61 | 55 | } | 62 | | - if (!Objects.equals(getTokenType(), other.getTokenType())) { | 63 | | - return false; | 64 | | - } | 65 | | - if (!Objects.equals(getRefreshToken(), other.getRefreshToken())) { | 66 | | - return false; | 67 | | - } | 68 | | - if (!Objects.equals(getScope(), other.getScope())) { | 69 | | - return false; | 70 | | - } | 71 | | - if (!Objects.equals(openIdToken, other.getOpenIdToken())) { | 72 | | - return false; | 73 | | - } | 74 | | - return Objects.equals(getExpiresIn(), other.getExpiresIn()); | | 56 | + | | 57 | + return Objects.equals(openIdToken, ((GoogleToken) obj).getOpenIdToken()); | 75 | 58 | } | 76 | 59 |
| 77 | 60 | @Override | |
Collapse file Copy file name to clipboard +31Lines changed: 31 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +package com.github.scribejava.apis.salesforce; | | 2 | + | | 3 | +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; | | 4 | + | | 5 | +/** | | 6 | + * This extractor parses in addition to the standard Extractor the instance_url | | 7 | + * of the used Salesforce organization. | | 8 | + */ | | 9 | +public class SalesforceJsonTokenExtractor extends OAuth2AccessTokenJsonExtractor { | | 10 | + | | 11 | + private static final String INSTANCE_URL_REGEX = "\"instance_url\"\\s*:\\s*\"(\\S*?)\""; | | 12 | + | | 13 | + protected SalesforceJsonTokenExtractor() { | | 14 | + } | | 15 | + | | 16 | + private static class InstanceHolder { | | 17 | + | | 18 | + private static final SalesforceJsonTokenExtractor INSTANCE = new SalesforceJsonTokenExtractor(); | | 19 | + } | | 20 | + | | 21 | + public static SalesforceJsonTokenExtractor instance() { | | 22 | + return InstanceHolder.INSTANCE; | | 23 | + } | | 24 | + | | 25 | + @Override | | 26 | + protected SalesforceToken createToken(String accessToken, String tokenType, Integer expiresIn, | | 27 | + String refreshToken, String scope, String response) { | | 28 | + return new SalesforceToken(accessToken, tokenType, expiresIn, refreshToken, scope, | | 29 | + extractParameter(response, INSTANCE_URL_REGEX, true), response); | | 30 | + } | | 31 | +} |
Collapse file Copy file name to clipboard +65Lines changed: 65 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +package com.github.scribejava.apis.salesforce; | | 2 | + | | 3 | +import java.util.Objects; | | 4 | + | | 5 | +import com.github.scribejava.core.model.OAuth2AccessToken; | | 6 | + | | 7 | +public class SalesforceToken extends OAuth2AccessToken { | | 8 | + | | 9 | + private static final long serialVersionUID = 7845679917727899612L; | | 10 | + | | 11 | + /** | | 12 | + * This token model includes the instance_url to address the needed | | 13 | + * Salesforce organization instance. | | 14 | + */ | | 15 | + private final String instanceUrl; | | 16 | + | | 17 | + public SalesforceToken(String accessToken, String instanceUrl, String rawResponse) { | | 18 | + this(accessToken, null, null, null, null, instanceUrl, rawResponse); | | 19 | + } | | 20 | + | | 21 | + public SalesforceToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, String scope, | | 22 | + String instanceUrl, String rawResponse) { | | 23 | + super(accessToken, tokenType, expiresIn, refreshToken, scope, rawResponse); | | 24 | + this.instanceUrl = instanceUrl; | | 25 | + } | | 26 | + | | 27 | + public String getInstanceUrl() { | | 28 | + return instanceUrl; | | 29 | + } | | 30 | + | | 31 | + @Override | | 32 | + public int hashCode() { | | 33 | + int hash = super.hashCode(); | | 34 | + hash = 37 * hash + Objects.hashCode(instanceUrl); | | 35 | + return hash; | | 36 | + } | | 37 | + | | 38 | + @Override | | 39 | + public boolean equals(Object obj) { | | 40 | + if (this == obj) { | | 41 | + return true; | | 42 | + } | | 43 | + if (obj == null) { | | 44 | + return false; | | 45 | + } | | 46 | + if (getClass() != obj.getClass()) { | | 47 | + return false; | | 48 | + } | | 49 | + if (!super.equals(obj)) { | | 50 | + return false; | | 51 | + } | | 52 | + return Objects.equals(instanceUrl, ((SalesforceToken) obj).getInstanceUrl()); | | 53 | + } | | 54 | + | | 55 | + @Override | | 56 | + public String toString() { | | 57 | + return "SalesforceToken{" | | 58 | + + "access_token=" + getAccessToken() | | 59 | + + ", token_type=" + getTokenType() | | 60 | + + ", expires_in=" + getExpiresIn() | | 61 | + + ", refresh_token=" + getRefreshToken() | | 62 | + + ", scope=" + getScope() | | 63 | + + ", instance_url=" + instanceUrl + '}'; | | 64 | + } | | 65 | +} |
Collapse file Copy file name to clipboard +83Lines changed: 83 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +package com.github.scribejava.apis.examples; | | 2 | + | | 3 | +import java.io.IOException; | | 4 | +import java.net.URLDecoder; | | 5 | +import java.net.URLEncoder; | | 6 | +import java.util.Scanner; | | 7 | + | | 8 | +import com.github.scribejava.apis.SalesforceApi; | | 9 | +import com.github.scribejava.apis.salesforce.SalesforceToken; | | 10 | +import com.github.scribejava.core.builder.ServiceBuilder; | | 11 | +import com.github.scribejava.core.model.OAuthRequest; | | 12 | +import com.github.scribejava.core.model.Response; | | 13 | +import com.github.scribejava.core.model.Verb; | | 14 | +import com.github.scribejava.core.oauth.OAuth20Service; | | 15 | +import java.security.KeyManagementException; | | 16 | +import java.security.NoSuchAlgorithmException; | | 17 | + | | 18 | +public abstract class SalesforceExample { | | 19 | + | | 20 | + private static final String NETWORK_NAME = "Salesforce"; | | 21 | + | | 22 | + public static void main(String... args) throws IOException, NoSuchAlgorithmException, KeyManagementException { | | 23 | + // Replace these with your client id and secret | | 24 | + final String clientId = "your client id"; | | 25 | + final String clientSecret = "your client secret"; | | 26 | + //IT's important! Salesforce upper require TLS v1.1 or 1.2 | | 27 | + SalesforceApi.initTLSv11orUpper(); | | 28 | + final OAuth20Service service = new ServiceBuilder() | | 29 | + .apiKey(clientId) | | 30 | + .apiSecret(clientSecret) | | 31 | + .callback("https://www.example.com/callback") | | 32 | + .build(SalesforceApi.instance()); | | 33 | + | | 34 | + System.out.println("=== " + NETWORK_NAME + "'s OAuth20 Workflow ==="); | | 35 | + System.out.println(); | | 36 | + | | 37 | + // Obtain the Authorization URL | | 38 | + System.out.println("Fetching the Authorization URL..."); | | 39 | + final String authorizationUrl = service.getAuthorizationUrl(); | | 40 | + System.out.println("Got the Authorization URL!"); | | 41 | + System.out.println("Now go and authorize ScribeJava here:"); | | 42 | + System.out.println(authorizationUrl); | | 43 | + System.out.println("And paste the authorization code here"); | | 44 | + System.out.print(">>"); | | 45 | + final String code; | | 46 | + try (Scanner in = new Scanner(System.in)) { | | 47 | + code = in.nextLine(); | | 48 | + } | | 49 | + System.out.println(); | | 50 | + | | 51 | + // The code needs to be URL decoded | | 52 | + final String codeEncoded = URLDecoder.decode(code, "UTF-8"); | | 53 | + | | 54 | + // Trade the Request Token and Verifier for the Access Token | | 55 | + System.out.println("Trading the Request Token for an Access Token..."); | | 56 | + final SalesforceToken accessToken = (SalesforceToken) service.getAccessToken(codeEncoded); | | 57 | + System.out.println("Got the Access Token!"); | | 58 | + System.out.println("(if your curious it looks like this: " + accessToken + ", 'rawResponse'='" | | 59 | + + accessToken.getRawResponse() + "')"); | | 60 | + System.out.println(); | | 61 | + | | 62 | + System.out.println("instance_url is: " + accessToken.getInstanceUrl()); | | 63 | + | | 64 | + // Now let's go and ask for a protected resource! | | 65 | + System.out.println("Now we're reading accounts from the Salesforce org (maxing them to 10)."); | | 66 | + | | 67 | + // Sample SOQL statement | | 68 | + final String queryEncoded = URLEncoder.encode("Select Id, Name from Account LIMIT 10", "UTF-8"); | | 69 | + | | 70 | + // Building the query URI. We've parsed the instance URL from the accessToken request. | | 71 | + final String url = accessToken.getInstanceUrl() + "/services/data/v36.0/query?q=" + queryEncoded; | | 72 | + | | 73 | + System.out.println(); | | 74 | + System.out.println("Full URL: " + url); | | 75 | + | | 76 | + final OAuthRequest request = new OAuthRequest(Verb.GET, url, service); | | 77 | + request.addHeader("Authorization", "Bearer " + accessToken.getAccessToken()); | | 78 | + final Response response = request.send(); | | 79 | + System.out.println(); | | 80 | + System.out.println(response.getCode()); | | 81 | + System.out.println(response.getBody()); | | 82 | + } | | 83 | +} |
|