Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0386df2606 | ||
|
|
ca0076c043 | ||
|
|
70358ad651 | ||
|
|
0f39d37ddc | ||
|
|
da3a3f4a0d | ||
|
|
380d858b13 | ||
|
|
9c4f5bc337 | ||
|
|
09ee10dbd1 | ||
|
|
690b9d4e21 | ||
|
|
080dd962a9 | ||
|
|
40bb525374 | ||
|
|
8e23e81c57 | ||
|
|
1f055d7eeb | ||
|
|
1f36fd0f32 | ||
|
|
9ea686a3f8 | ||
|
|
7e92db3413 | ||
|
|
f6c3cb9bdb | ||
|
|
088fc5e443 | ||
|
|
27bac50073 | ||
|
|
6fc5146706 | ||
|
|
0e5ae92d3e | ||
|
|
c145ee8842 | ||
|
|
bdfd14309f | ||
|
|
82f03604c3 | ||
|
|
5ac849313d | ||
|
|
c12da16a38 | ||
|
|
b78ca90df4 | ||
|
|
577c18c752 | ||
|
|
41cbee06d7 | ||
|
|
8eb2062e95 | ||
|
|
8f0760664f | ||
|
|
0be82d6832 | ||
|
|
d0fa8689cb | ||
|
|
896e738156 | ||
|
|
cf84381127 | ||
|
|
806d548629 | ||
|
|
959c093620 | ||
|
|
fc2c46bd3a | ||
|
|
f1ecabdb52 | ||
|
|
83f17b0652 | ||
|
|
ebe0ff9eda | ||
|
|
6e141ba6a2 | ||
|
|
23af69cbf8 | ||
|
|
c0d24b556c | ||
|
|
99a03b4679 | ||
|
|
9337ac01d9 | ||
|
|
dee0f55b1e | ||
|
|
377c3233d9 | ||
|
|
029125490d | ||
|
|
20b200c7bc | ||
|
|
3e7291eaee | ||
|
|
149756e5ed | ||
|
|
9cb2af37c7 | ||
|
|
ed0970c8cb | ||
|
|
58991e81ef | ||
|
|
db27be9e2b | ||
|
|
874e959e09 | ||
|
|
545867ca1d | ||
|
|
8bd1e94287 | ||
|
|
843d9feddc | ||
|
|
9b85863edf | ||
|
|
59f16bfdda | ||
|
|
aad8dac580 | ||
|
|
50b54fbfb6 | ||
|
|
5d86982421 | ||
|
|
1f94997120 | ||
|
|
c3f113f39b | ||
|
|
32b08788c9 | ||
|
|
91c64ff08b | ||
|
|
ffb1042146 | ||
|
|
fbee85ec08 | ||
|
|
f59c9543d5 | ||
|
|
94df2504ec | ||
|
|
36aeaeed2f | ||
|
|
50c35bc686 | ||
|
|
8c8f26e134 | ||
|
|
608f56d59f |
No files matched your search
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010 Pablo Fenandez
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -32,6 +32,12 @@ h3. Supports all major OAuth APIs out-of-the-box
|
||||
|
||||
* Foursquare
|
||||
|
||||
* Evernote
|
||||
|
||||
* Vimeo
|
||||
|
||||
* Yammer
|
||||
|
||||
* and many more! check the "examples folder":http://github.com/fernandezpablo85/scribe-java/tree/master/src/test/java/org/scribe/examples
|
||||
|
||||
h3. Small and modular
|
||||
@@ -48,6 +54,16 @@ Good test coverage to keep you safe from harm.
|
||||
|
||||
When something bad actually happens, Scribe's meaningful error messages will tell you exactly what went wrong, when and where.
|
||||
|
||||
h3. Pull it from Maven! (new)
|
||||
|
||||
You can pull scribe from a maven repository, just add this to your __pom.xml__ file:
|
||||
|
||||
@<dependency>@
|
||||
@<groupId>org.scribe</groupId>@
|
||||
@<artifactId>scribe</artifactId>@
|
||||
@<version>1.0.6</version>@
|
||||
@</dependency>@
|
||||
|
||||
h1. Getting started in less than 2 minutes
|
||||
|
||||
Check the "Getting Started":http://wiki.github.com/fernandezpablo85/scribe-java/getting-started page and start rocking!
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
[1.0.6]
|
||||
|
||||
* FEATURE: Available in maven central repositories.
|
||||
|
||||
[1.0.7]
|
||||
|
||||
* FEATURE: Added support for Yammer and Evernote ( thanks oparrsih )
|
||||
* FIX: Fixed bug that preventing setting the scope param on Google Api
|
||||
|
||||
[1.0.8]
|
||||
|
||||
* FEATURE: Added setConnectTimeout and setReadTimeout for the Request Object
|
||||
* FIX: Fixed Evernote Api (uses GET for request and access tokens)
|
||||
* REFACTOR: URLEncoding stuff. LinkedIn specific decoder is no longer needed
|
||||
* FEATURE: Added Google example
|
||||
|
||||
[1.0.9]
|
||||
|
||||
* FEATURE: Token made Serializable
|
||||
* FIX: Google Api encoding issues (thanks @roger and @klakegg)
|
||||
|
||||
[1.1.0]
|
||||
|
||||
* FEATURE: OAuth 2.0 Support and Facebook support out of the box (thanks Diego Silveira)
|
||||
* REFACTOR: Api creation and OAuthService refactors
|
||||
* REFACTOR: Connections are created lazily (just before sending the request)
|
||||
|
||||
[1.1.1]
|
||||
|
||||
* FIX: Removed isEmpty() from OAuth2.0 code in order to support older JVMs
|
||||
* FEATURE: Overloaded provider() method to support instances as well as classes (thanks dustismo)
|
||||
@@ -4,8 +4,44 @@
|
||||
<groupId>org.scribe</groupId>
|
||||
<artifactId>scribe</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0.2</version>
|
||||
<name>OAuth Library</name>
|
||||
<version>1.1.0</version>
|
||||
<name>Scribe OAuth Library</name>
|
||||
<description>The best OAuth library out there</description>
|
||||
<url>http://github.com/fernandezpablo85/scribe-java</url>
|
||||
|
||||
<parent>
|
||||
<groupId>org.sonatype.oss</groupId>
|
||||
<artifactId>oss-parent</artifactId>
|
||||
<version>5</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>fernandezpablo85</id>
|
||||
<name>Pablo Fernandez</name>
|
||||
<email>fernandezpablo85@gmail.com</email>
|
||||
<timezone>-3</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>diegossilveira</id>
|
||||
<name>Diego Silveira</name>
|
||||
<email>diegossilveira@gmail.com</email>
|
||||
<timezone>-3</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>MIT</name>
|
||||
<url>http://github.com/fernandezpablo85/scribe-java/blob/master/LICENSE.txt</url>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:http://github.com/fernandezpablo85/scribe-java.git</connection>
|
||||
<developerConnection>scm:http://github.com/fernandezpablo85/scribe-java.git</developerConnection>
|
||||
<url>http://github.com/fernandezpablo85/scribe-java.git</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -18,6 +54,7 @@
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
@@ -30,6 +67,19 @@
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -2,7 +2,6 @@ package org.scribe.builder;
|
||||
|
||||
import org.scribe.builder.api.*;
|
||||
import org.scribe.exceptions.*;
|
||||
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.oauth.*;
|
||||
import org.scribe.utils.*;
|
||||
@@ -20,7 +19,11 @@ public class ServiceBuilder
|
||||
private String apiSecret;
|
||||
private String callback;
|
||||
private Api api;
|
||||
private String scope;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public ServiceBuilder()
|
||||
{
|
||||
this.callback = OAuthConstants.OUT_OF_BAND;
|
||||
@@ -52,7 +55,22 @@ public class ServiceBuilder
|
||||
}
|
||||
return api;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configures the {@link Api}
|
||||
*
|
||||
* Overloaded version. Let's you use an instance instead of a class.
|
||||
*
|
||||
* @param api instance of {@link Api}s
|
||||
* @return the {@link ServiceBuilder} instance for method chaining
|
||||
*/
|
||||
public ServiceBuilder provider(Api api)
|
||||
{
|
||||
Preconditions.checkNotNull(api, "Api cannot be null");
|
||||
this.api = api;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an OAuth callback url
|
||||
*
|
||||
@@ -92,6 +110,19 @@ public class ServiceBuilder
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the OAuth scope. This is only necessary in some APIs (like Google's).
|
||||
*
|
||||
* @param scope The OAuth scope
|
||||
* @return the {@link ServiceBuilder} instance for method chaining
|
||||
*/
|
||||
public ServiceBuilder scope(String scope)
|
||||
{
|
||||
Preconditions.checkEmptyString(scope, "Invalid OAuth scope");
|
||||
this.scope = scope;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully configured {@link OAuthService}
|
||||
*
|
||||
@@ -102,6 +133,6 @@ public class ServiceBuilder
|
||||
Preconditions.checkNotNull(api, "You must specify a valid api through the provider() method");
|
||||
Preconditions.checkEmptyString(apiKey, "You must provide an api key");
|
||||
Preconditions.checkEmptyString(apiSecret, "You must provide an api secret");
|
||||
return api.createService(apiKey, apiSecret, callback);
|
||||
return api.createService(new OAuthConfig(apiKey, apiSecret, callback), scope);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.oauth.*;
|
||||
|
||||
/**
|
||||
@@ -16,8 +17,9 @@ public interface Api
|
||||
* @param apiKey your application api key
|
||||
* @param apiSecret your application api secret
|
||||
* @param callback the callback url (or 'oob' for out of band OAuth)
|
||||
* @param scope the OAuth scope
|
||||
*
|
||||
* @return fully configured {@link OAuthService}
|
||||
*/
|
||||
OAuthService createService(String apiKey, String apiSecret, String callback);
|
||||
OAuthService createService(OAuthConfig config, String scope);
|
||||
}
|
||||
@@ -5,74 +5,144 @@ import org.scribe.model.*;
|
||||
import org.scribe.oauth.*;
|
||||
import org.scribe.services.*;
|
||||
|
||||
/**
|
||||
* Default implementation of the OAuth protocol, version 1.0a
|
||||
*
|
||||
* 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 1.0a 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 Pablo Fernandez
|
||||
*
|
||||
*/
|
||||
public abstract class DefaultApi10a implements Api
|
||||
{
|
||||
/**
|
||||
* Returns the access token extractor.
|
||||
*
|
||||
* @return access token extractor
|
||||
*/
|
||||
public AccessTokenExtractor getAccessTokenExtractor()
|
||||
{
|
||||
return new TokenExtractorImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base string extractor.
|
||||
*
|
||||
* @return base string extractor
|
||||
*/
|
||||
public BaseStringExtractor getBaseStringExtractor()
|
||||
{
|
||||
return new BaseStringExtractorImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header extractor.
|
||||
*
|
||||
* @return header extractor
|
||||
*/
|
||||
public HeaderExtractor getHeaderExtractor()
|
||||
{
|
||||
return new HeaderExtractorImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request token extractor.
|
||||
*
|
||||
* @return request token extractor
|
||||
*/
|
||||
public RequestTokenExtractor getRequestTokenExtractor()
|
||||
{
|
||||
return new TokenExtractorImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signature service.
|
||||
*
|
||||
* @return signature service
|
||||
*/
|
||||
public SignatureService getSignatureService()
|
||||
{
|
||||
return new HMACSha1SignatureService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timestamp service.
|
||||
*
|
||||
* @return timestamp service
|
||||
*/
|
||||
public TimestampService getTimestampService()
|
||||
{
|
||||
return new TimestampServiceImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the verb for the access token endpoint (defaults to POST)
|
||||
*
|
||||
* @return access token endpoint verb
|
||||
*/
|
||||
public Verb getAccessTokenVerb()
|
||||
{
|
||||
return Verb.POST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the verb for the request token endpoint (defaults to POST)
|
||||
*
|
||||
* @return request token endpoint verb
|
||||
*/
|
||||
public Verb getRequestTokenVerb()
|
||||
{
|
||||
return Verb.POST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL that receives the request token requests.
|
||||
*
|
||||
* @return request token URL
|
||||
*/
|
||||
public abstract String getRequestTokenEndpoint();
|
||||
|
||||
/**
|
||||
* Returns the URL that receives the access token requests.
|
||||
*
|
||||
* @return access token URL
|
||||
*/
|
||||
public abstract String getAccessTokenEndpoint();
|
||||
|
||||
@Override
|
||||
public OAuthService createService(String apiKey, String apiSecret, String callback)
|
||||
/**
|
||||
* Returns the URL where you should redirect your users to authenticate
|
||||
* your application.
|
||||
*
|
||||
* @param requestToken the request token you need to authorize
|
||||
* @return the URL where you should redirect your users
|
||||
*/
|
||||
public abstract String getAuthorizationUrl(Token requestToken);
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuthService} for this Api
|
||||
*
|
||||
* @param apiKey Key
|
||||
* @param apiSecret Api Secret
|
||||
* @param callback OAuth callback (either URL or 'oob')
|
||||
* @param scope OAuth scope (optional)
|
||||
*/
|
||||
public OAuthService createService(OAuthConfig config, String scope)
|
||||
{
|
||||
return new OAuth10aServiceImpl( getSignatureService(),
|
||||
getTimestampService(),
|
||||
getBaseStringExtractor(),
|
||||
getHeaderExtractor(),
|
||||
getRequestTokenExtractor(),
|
||||
getAccessTokenExtractor(),
|
||||
createConfig(apiKey, apiSecret, callback));
|
||||
OAuthService service = doCreateService(config);
|
||||
service.addScope(scope);
|
||||
return service;
|
||||
}
|
||||
|
||||
private OAuthConfig createConfig(String apiKey, String apiSecret, String callback)
|
||||
|
||||
private OAuthService doCreateService(OAuthConfig config)
|
||||
{
|
||||
OAuthConfig config = new OAuthConfig();
|
||||
config.setRequestTokenVerb(getRequestTokenVerb());
|
||||
config.setRequestTokenEndpoint(getRequestTokenEndpoint());
|
||||
config.setAccessTokenVerb(getAccessTokenVerb());
|
||||
config.setAccessTokenEndpoint(getAccessTokenEndpoint());
|
||||
config.setApiKey(apiKey);
|
||||
config.setApiSecret(apiSecret);
|
||||
config.setCallback(callback);
|
||||
return config;
|
||||
return new OAuth10aServiceImpl(this, config);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
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 DefaultApi20 implements Api
|
||||
{
|
||||
|
||||
/**
|
||||
* 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, String scope)
|
||||
{
|
||||
return new OAuth20ServiceImpl(this, config);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.Token;
|
||||
import org.scribe.model.Verb;
|
||||
|
||||
public class EvernoteApi extends DefaultApi10a
|
||||
{
|
||||
private static final String AUTHORIZATION_URL = "https://www.evernote.com/OAuth.action?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public Verb getRequestTokenVerb()
|
||||
{
|
||||
return Verb.GET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return "https://www.evernote.com/oauth";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Verb getAccessTokenVerb()
|
||||
{
|
||||
return Verb.GET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return "https://www.evernote.com/oauth";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZATION_URL, requestToken.getToken());
|
||||
}
|
||||
|
||||
public static class Sandbox extends EvernoteApi
|
||||
{
|
||||
private static final String SANDBOX_URL = "https://sandbox.evernote.com/oauth";
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return SANDBOX_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return SANDBOX_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(SANDBOX_URL + "?oauth_token=%s", requestToken.getToken());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.utils.*;
|
||||
|
||||
public class FacebookApi extends DefaultApi20
|
||||
{
|
||||
private static final String AUTHORIZE_URL = "https://graph.facebook.com/oauth/authorize?response_type=token&client_id=%s&redirect_uri=%s";
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(OAuthConfig config)
|
||||
{
|
||||
Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Facebook does not support OOB");
|
||||
return String.format(AUTHORIZE_URL, config.getApiKey(), URLUtils.urlEncodeWrapper(config.getCallback()));
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.Token;
|
||||
|
||||
public class FoursquareApi extends DefaultApi10a
|
||||
{
|
||||
private static final String AUTHORIZATION_URL = "http://foursquare.com/oauth/authorize?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
@@ -13,4 +17,10 @@ public class FoursquareApi extends DefaultApi10a
|
||||
{
|
||||
return "http://foursquare.com/oauth/request_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZATION_URL, requestToken.getToken());
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,38 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
public class GoogleApi extends DefaultApi10a
|
||||
{
|
||||
private static final String AUTHORIZATION_URL = "https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return "https://www.google.com/accounts/OAuthGetRequestToken";
|
||||
return "https://www.google.com/accounts/OAuthGetAccessToken";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return "https://www.google.com/accounts/OAuthGetAccessToken";
|
||||
return "https://www.google.com/accounts/OAuthGetRequestToken";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Verb getAccessTokenVerb()
|
||||
{
|
||||
return Verb.GET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Verb getRequestTokenVerb()
|
||||
{
|
||||
return Verb.GET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZATION_URL, requestToken.getToken());
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.extensions.linkedin.*;
|
||||
import org.scribe.extractors.*;
|
||||
import org.scribe.model.*;
|
||||
|
||||
public class LinkedInApi extends DefaultApi10a
|
||||
{
|
||||
private static final String AUTHORIZE_URL = "https://api.linkedin.com/uas/oauth/authorize?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
@@ -19,9 +19,9 @@ public class LinkedInApi extends DefaultApi10a
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseStringExtractor getBaseStringExtractor()
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return new LinkedInBaseStringExtractorImpl();
|
||||
return String.format(AUTHORIZE_URL, requestToken.getToken());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,16 +1,26 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.Token;
|
||||
|
||||
public class TwitterApi extends DefaultApi10a
|
||||
{
|
||||
private static final String AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return "http://twitter.com/oauth/access_token";
|
||||
return "http://api.twitter.com/oauth/access_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return "http://twitter.com/oauth/request_token";
|
||||
return "http://api.twitter.com/oauth/request_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZE_URL, requestToken.getToken());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.Token;
|
||||
|
||||
public class VimeoApi extends DefaultApi10a
|
||||
{
|
||||
private static final String AUTHORIZATION_URL = "http://vimeo.com/oauth/authorize?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return "http://vimeo.com/oauth/access_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return "http://vimeo.com/oauth/request_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZATION_URL, requestToken.getToken());
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.Token;
|
||||
|
||||
public class YahooApi extends DefaultApi10a
|
||||
{
|
||||
private static final String AUTHORIZE_URL = "https://api.login.yahoo.com/oauth/v2/request_auth?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
@@ -13,4 +17,10 @@ public class YahooApi extends DefaultApi10a
|
||||
{
|
||||
return "https://api.login.yahoo.com/oauth/v2/get_request_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZE_URL, requestToken.getToken());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.Token;
|
||||
|
||||
public class YammerApi extends DefaultApi10a
|
||||
{
|
||||
private static final String AUTHORIZATION_URL = "'https://www.yammer.com/oauth/authorize?oauth_token=%s'";
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return "https://www.yammer.com/oauth/request_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return "https://www.yammer.com/oauth/access_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZATION_URL, requestToken.getToken());
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,33 @@
|
||||
package org.scribe.exceptions;
|
||||
|
||||
/**
|
||||
* Default scribe exception.
|
||||
* Represents a problem in the OAuth signing process
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class OAuthException extends RuntimeException
|
||||
{
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
* @param message message explaining what went wrong
|
||||
* @param e original exception
|
||||
*/
|
||||
public OAuthException(String message, Exception e)
|
||||
{
|
||||
super(message, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* No-exception constructor. Used when there is no original exception
|
||||
*
|
||||
* @param message message explaining what went wrong
|
||||
*/
|
||||
public OAuthException(String message)
|
||||
{
|
||||
super(message, null);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
@@ -2,6 +2,11 @@ package org.scribe.exceptions;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
/**
|
||||
* Specialized exception that represents a missing OAuth parameter.
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class OAuthParametersMissingException extends OAuthException
|
||||
{
|
||||
|
||||
@@ -9,6 +14,11 @@ public class OAuthParametersMissingException extends OAuthException
|
||||
private static final String MSG = "Could not find oauth parameters in request: %s. "
|
||||
+ "OAuth parameters must be specified with the addOAuthParameter() method";
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* @param request OAuthRequest that caused the error
|
||||
*/
|
||||
public OAuthParametersMissingException(OAuthRequest request)
|
||||
{
|
||||
super(String.format(MSG, request));
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
package org.scribe.exceptions;
|
||||
|
||||
/**
|
||||
* Specialized exception that represents a problem in the signature
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class OAuthSignatureException extends OAuthException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param stringToSign plain string that gets signed (HMAC-SHA, etc)
|
||||
* @param e original exception
|
||||
*/
|
||||
public OAuthSignatureException(String stringToSign, Exception e)
|
||||
{
|
||||
super("Error while signing string: " + stringToSign, e);
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.scribe.extensions.linkedin;
|
||||
|
||||
import org.scribe.extractors.*;
|
||||
import org.scribe.model.*;
|
||||
|
||||
public class LinkedInBaseStringExtractorImpl extends BaseStringExtractorImpl
|
||||
{
|
||||
|
||||
@Override
|
||||
public String extract(OAuthRequest request)
|
||||
{
|
||||
String baseString = super.extract(request);
|
||||
return baseString.replace("%7E", "~");
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,18 @@ package org.scribe.extractors;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
/**
|
||||
* Simple command object that extracts a {@link Token} from a String
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public interface AccessTokenExtractor
|
||||
{
|
||||
/**
|
||||
* Extracts the access token from the contents of an Http Response
|
||||
*
|
||||
* @param response the contents of the response
|
||||
* @return OAuth access token
|
||||
*/
|
||||
public Token extract(String response);
|
||||
}
|
||||
@@ -2,7 +2,20 @@ package org.scribe.extractors;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
/**
|
||||
* Simple command object that extracts a base string from a {@link OAuthRequest}
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public interface BaseStringExtractor
|
||||
{
|
||||
/**
|
||||
* Extracts an url-encoded base string from the {@link OAuthRequest}.
|
||||
*
|
||||
* See <a href="http://oauth.net/core/1.0/#anchor14">the oauth spec</a> for more info on this.
|
||||
*
|
||||
* @param request the OAuthRequest
|
||||
* @return the url-encoded base string
|
||||
*/
|
||||
String extract(OAuthRequest request);
|
||||
}
|
||||
@@ -6,11 +6,20 @@ import org.scribe.exceptions.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.utils.*;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link BaseStringExtractor}. Conforms to OAuth 1.0a
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*
|
||||
*/
|
||||
public class BaseStringExtractorImpl implements BaseStringExtractor
|
||||
{
|
||||
|
||||
private static final String AMPERSAND_SEPARATED_STRING = "%s&%s&%s";
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String extract(OAuthRequest request)
|
||||
{
|
||||
checkPreconditions(request);
|
||||
@@ -23,11 +32,31 @@ public class BaseStringExtractorImpl implements BaseStringExtractor
|
||||
private String getSortedAndEncodedParams(OAuthRequest request)
|
||||
{
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.putAll(request.getQueryStringParams());
|
||||
params.putAll(request.getBodyParams());
|
||||
params.putAll(request.getOauthParameters());
|
||||
Map<String, String> tmp = null;
|
||||
//params.putAll(request.getQueryStringParams());
|
||||
tmp = request.getQueryStringParams();
|
||||
for (String key:tmp.keySet()){
|
||||
params.put(
|
||||
URLUtils.percentEncode(key),
|
||||
URLUtils.percentEncode(tmp.get(key))
|
||||
);
|
||||
}
|
||||
tmp = request.getBodyParams();
|
||||
for (String key:tmp.keySet()){
|
||||
params.put(
|
||||
URLUtils.percentEncode(key),
|
||||
URLUtils.percentEncode(tmp.get(key))
|
||||
);
|
||||
}
|
||||
tmp = request.getOauthParameters();
|
||||
for (String key:tmp.keySet()){
|
||||
params.put(
|
||||
URLUtils.percentEncode(key),
|
||||
URLUtils.percentEncode(tmp.get(key))
|
||||
);
|
||||
}
|
||||
params = MapUtils.sort(params);
|
||||
return URLUtils.percentEncode(URLUtils.formURLEncodeMap(params));
|
||||
return URLUtils.percentEncode(URLUtils.concatSortedPercentEncodedParams(params));
|
||||
}
|
||||
|
||||
private void checkPreconditions(OAuthRequest request)
|
||||
|
||||
@@ -2,7 +2,18 @@ package org.scribe.extractors;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
/**
|
||||
* Simple command object that generates an OAuth Authorization header to include in the request.
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public interface HeaderExtractor
|
||||
{
|
||||
/**
|
||||
* Generates an OAuth 'Authorization' Http header to include in requests as the signature.
|
||||
*
|
||||
* @param request the OAuthRequest to inspect and generate the header
|
||||
* @return the Http header value
|
||||
*/
|
||||
String extract(OAuthRequest request);
|
||||
}
|
||||
@@ -6,22 +6,35 @@ import org.scribe.exceptions.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.utils.*;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link HeaderExtractor}. Conforms to OAuth 1.0a
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*
|
||||
*/
|
||||
public class HeaderExtractorImpl implements HeaderExtractor
|
||||
{
|
||||
|
||||
private static final String PARAM_SEPARATOR = ", ";
|
||||
private static final String PREAMBLE = "OAuth ";
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String extract(OAuthRequest request)
|
||||
{
|
||||
checkPreconditions(request);
|
||||
Map<String, String> parameters = request.getOauthParameters();
|
||||
StringBuffer header = new StringBuffer();
|
||||
StringBuffer header = new StringBuffer(parameters.size() * 20);
|
||||
header.append(PREAMBLE);
|
||||
for (String key : parameters.keySet())
|
||||
{
|
||||
addToHeader(header, key, parameters.get(key));
|
||||
if(header.length() > PREAMBLE.length())
|
||||
{
|
||||
header.append(PARAM_SEPARATOR);
|
||||
}
|
||||
header.append(String.format("%s=\"%s\"", key, URLUtils.percentEncode(parameters.get(key))));
|
||||
}
|
||||
return removeTrail(header);
|
||||
return header.toString();
|
||||
}
|
||||
|
||||
private void checkPreconditions(OAuthRequest request)
|
||||
@@ -34,13 +47,4 @@ public class HeaderExtractorImpl implements HeaderExtractor
|
||||
}
|
||||
}
|
||||
|
||||
private void addToHeader(StringBuffer header, String name, String value)
|
||||
{
|
||||
header.append(String.format("%s=\"%s\", ", name, URLUtils.percentEncode(value)));
|
||||
}
|
||||
|
||||
private String removeTrail(StringBuffer header)
|
||||
{
|
||||
return header.toString().substring(0, header.length() - 2);
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,18 @@ package org.scribe.extractors;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
/**
|
||||
* Simple command object that extracts a {@link Token} from a String
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public interface RequestTokenExtractor
|
||||
{
|
||||
|
||||
/**
|
||||
* Extracts the request token from the contents of an Http Response
|
||||
*
|
||||
* @param response the contents of the response
|
||||
* @return OAuth access token
|
||||
*/
|
||||
public Token extract(String response);
|
||||
}
|
||||
@@ -6,24 +6,33 @@ import org.scribe.exceptions.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.utils.*;
|
||||
|
||||
/**
|
||||
* Default implementation of {@RequestTokenExtractor} and {@AccessTokenExtractor}. Conforms to OAuth 1.0a
|
||||
*
|
||||
* The process for extracting access and request tokens is similar so this class can do both things.
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class TokenExtractorImpl implements RequestTokenExtractor, AccessTokenExtractor
|
||||
{
|
||||
|
||||
private static final String TOKEN_REGEX = "oauth_token=(\\S*)&oauth_token_secret=(\\S*?)(&(.*))?";
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Token extract(String response)
|
||||
{
|
||||
Preconditions.checkEmptyString(response, "Cant extract a token from null object or an empty string.");
|
||||
Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string");
|
||||
|
||||
Matcher matcher = Pattern.compile(TOKEN_REGEX).matcher(response);
|
||||
if (matcher.matches())
|
||||
{
|
||||
String token = URLUtils.percentDecode(matcher.group(1));
|
||||
String secret = URLUtils.percentDecode(matcher.group(2));
|
||||
String token = URLUtils.urlDecodeWrapper(matcher.group(1));
|
||||
String secret = URLUtils.urlDecodeWrapper(matcher.group(2));
|
||||
return new Token(token, secret);
|
||||
} else
|
||||
{
|
||||
throw new OAuthException("Could not find request token or secret in response: " + response, null);
|
||||
throw new OAuthException("Response body is incorrect. Can't extract a token from this: '" + response + "'", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,27 @@
|
||||
package org.scribe.model;
|
||||
|
||||
/**
|
||||
* Parameter object that groups OAuth config values
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class OAuthConfig
|
||||
{
|
||||
private String apiKey;
|
||||
private String apiSecret;
|
||||
private String callback;
|
||||
private String requestTokenEndpoint;
|
||||
private String accessTokenEndpoint;
|
||||
private Verb requestTokenVerb;
|
||||
private Verb accessTokenVerb;
|
||||
|
||||
public OAuthConfig(String key, String secret)
|
||||
{
|
||||
this(key,secret,null);
|
||||
}
|
||||
|
||||
public OAuthConfig(String key, String secret, String callback)
|
||||
{
|
||||
this.apiKey = key;
|
||||
this.apiSecret = secret;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public String getApiKey()
|
||||
{
|
||||
@@ -39,45 +52,4 @@ public class OAuthConfig
|
||||
{
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return requestTokenEndpoint;
|
||||
}
|
||||
|
||||
public void setRequestTokenEndpoint(String requestTokenEndpoint)
|
||||
{
|
||||
this.requestTokenEndpoint = requestTokenEndpoint;
|
||||
}
|
||||
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return accessTokenEndpoint;
|
||||
}
|
||||
|
||||
public void setAccessTokenEndpoint(String accessTokenEndpoint)
|
||||
{
|
||||
this.accessTokenEndpoint = accessTokenEndpoint;
|
||||
}
|
||||
|
||||
public Verb getRequestTokenVerb()
|
||||
{
|
||||
return requestTokenVerb != null ? requestTokenVerb : Verb.GET;
|
||||
}
|
||||
|
||||
public void setRequestTokenVerb(Verb requestTokenVerb)
|
||||
{
|
||||
this.requestTokenVerb = requestTokenVerb;
|
||||
}
|
||||
|
||||
public Verb getAccessTokenVerb()
|
||||
{
|
||||
return accessTokenVerb != null ? accessTokenVerb : Verb.GET;
|
||||
}
|
||||
|
||||
public void setAccessTokenVerb(Verb accessTokenVerb)
|
||||
{
|
||||
this.accessTokenVerb = accessTokenVerb;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package org.scribe.model;
|
||||
* This class contains OAuth constants, used project-wide
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*
|
||||
*/
|
||||
public class OAuthConstants
|
||||
{
|
||||
@@ -38,4 +37,8 @@ public class OAuthConstants
|
||||
public static final String VERIFIER = "oauth_verifier";
|
||||
public static final String HEADER = "Authorization";
|
||||
public static final Token EMPTY_TOKEN = new Token("", "");
|
||||
public static final String SCOPE = "scope";
|
||||
|
||||
//OAuth 2.0
|
||||
public static final String ACCESS_TOKEN = "access_token";
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.scribe.model;
|
||||
|
||||
public class OAuthParams
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,19 +1,41 @@
|
||||
package org.scribe.model;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The representation of an OAuth HttpRequest.
|
||||
*
|
||||
* Adds OAuth-related functionality to the {@link Request}
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class OAuthRequest extends Request
|
||||
{
|
||||
|
||||
private static final String OAUTH_PREFIX = "oauth_";
|
||||
private Map<String, String> oauthParameters;
|
||||
|
||||
public OAuthRequest(Verb verb, String url)
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* @param verb Http verb/method
|
||||
* @param url resource URL
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public OAuthRequest(Verb verb, String url) throws MalformedURLException
|
||||
{
|
||||
super(verb, url);
|
||||
this.oauthParameters = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an OAuth parameter.
|
||||
*
|
||||
* @param key name of the parameter
|
||||
* @param value value of the parameter
|
||||
*
|
||||
* @throws IllegalArgumentException if the parameter is not an OAuth parameter
|
||||
*/
|
||||
public void addOAuthParameter(String key, String value)
|
||||
{
|
||||
oauthParameters.put(checkKey(key), value);
|
||||
@@ -21,15 +43,21 @@ public class OAuthRequest extends Request
|
||||
|
||||
private String checkKey(String key)
|
||||
{
|
||||
if (!key.startsWith(OAUTH_PREFIX))
|
||||
{
|
||||
throw new IllegalArgumentException(String.format("OAuth parameters must start with '%s'", OAUTH_PREFIX));
|
||||
} else
|
||||
if (key.startsWith(OAUTH_PREFIX) || key.equals(OAuthConstants.SCOPE))
|
||||
{
|
||||
return key;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException(String.format("OAuth parameters must either be '%s' or start with '%s'", OAuthConstants.SCOPE, OAUTH_PREFIX));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Map} containing the key-value pair of parameters.
|
||||
*
|
||||
* @return parameters as map
|
||||
*/
|
||||
public Map<String, String> getOauthParameters()
|
||||
{
|
||||
return oauthParameters;
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.scribe.model;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.scribe.exceptions.*;
|
||||
import org.scribe.utils.*;
|
||||
@@ -14,15 +15,14 @@ import org.scribe.utils.*;
|
||||
*/
|
||||
class Request
|
||||
{
|
||||
|
||||
private static final String CONTENT_LENGTH = "Content-Length";
|
||||
|
||||
private String url;
|
||||
private URL url;
|
||||
private Verb verb;
|
||||
private Map<String, String> querystringParams;
|
||||
private Map<String, String> bodyParams;
|
||||
private Map<String, String> headers;
|
||||
private String payload = null;
|
||||
private Integer timeout = null;
|
||||
private HttpURLConnection connection;
|
||||
|
||||
/**
|
||||
@@ -30,21 +30,15 @@ class Request
|
||||
*
|
||||
* @param verb Http Verb (GET, POST, etc)
|
||||
* @param url url with optional querystring parameters.
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public Request(Verb verb, String url)
|
||||
public Request(Verb verb, String url) throws MalformedURLException
|
||||
{
|
||||
this.verb = verb;
|
||||
this.url = url;
|
||||
this.url = new URL(url);
|
||||
this.querystringParams = new HashMap<String, String>();
|
||||
this.bodyParams = new HashMap<String, String>();
|
||||
this.headers = new HashMap<String, String>();
|
||||
try
|
||||
{
|
||||
connection = (HttpURLConnection) new URL(url).openConnection();
|
||||
if(timeout != null) connection.setConnectTimeout(timeout);
|
||||
} catch (IOException ioe)
|
||||
{
|
||||
throw new OAuthException("Could not open connection to: " + url, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,6 +52,7 @@ class Request
|
||||
{
|
||||
try
|
||||
{
|
||||
createConnection();
|
||||
return doSend();
|
||||
} catch (IOException ioe)
|
||||
{
|
||||
@@ -65,6 +60,15 @@ class Request
|
||||
}
|
||||
}
|
||||
|
||||
private void createConnection() throws IOException
|
||||
{
|
||||
String effectiveUrl = URLUtils.appendParametersToQueryString(url.toString(), querystringParams);
|
||||
if (connection == null)
|
||||
{
|
||||
connection = (HttpURLConnection) new URL(effectiveUrl).openConnection();
|
||||
}
|
||||
}
|
||||
|
||||
Response doSend() throws IOException
|
||||
{
|
||||
connection.setRequestMethod(this.verb.name());
|
||||
@@ -92,8 +96,8 @@ class Request
|
||||
/**
|
||||
* Add an HTTP Header to the Request
|
||||
*
|
||||
* @param name
|
||||
* @param value
|
||||
* @param key the header name
|
||||
* @param value the header value
|
||||
*/
|
||||
public void addHeader(String key, String value)
|
||||
{
|
||||
@@ -103,14 +107,25 @@ class Request
|
||||
/**
|
||||
* Add a body Parameter (for POST/ PUT Requests)
|
||||
*
|
||||
* @param name
|
||||
* @param value
|
||||
* @param key the parameter name
|
||||
* @param value the parameter value
|
||||
*/
|
||||
public void addBodyParameter(String key, String value)
|
||||
{
|
||||
this.bodyParams.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a QueryString parameter
|
||||
*
|
||||
* @param key the parameter name
|
||||
* @param value the parameter value
|
||||
*/
|
||||
public void addQuerystringParameter(String key, String value)
|
||||
{
|
||||
this.querystringParams.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add body payload.
|
||||
*
|
||||
@@ -119,7 +134,7 @@ class Request
|
||||
*
|
||||
* Note: The contents are not part of the OAuth signature
|
||||
*
|
||||
* @param payload
|
||||
* @param payload the body of the request
|
||||
*/
|
||||
public void addPayload(String payload)
|
||||
{
|
||||
@@ -133,23 +148,22 @@ class Request
|
||||
*/
|
||||
public Map<String, String> getQueryStringParams()
|
||||
{
|
||||
try
|
||||
{
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
String query = new URL(url).getQuery();
|
||||
String query = url.getQuery();
|
||||
if (query != null)
|
||||
{
|
||||
for (String param : query.split("&"))
|
||||
{
|
||||
String pair[] = param.split("=");
|
||||
params.put(pair[0], pair[1]);
|
||||
String valuePart = "";
|
||||
if (pair.length > 1) {
|
||||
valuePart = URLUtils.urlDecodeWrapper(pair[1]);
|
||||
}
|
||||
params.put(URLUtils.urlDecodeWrapper(pair[0]),valuePart );
|
||||
}
|
||||
}
|
||||
return params;
|
||||
} catch (MalformedURLException mue)
|
||||
{
|
||||
throw new OAuthException("Malformed URL", mue);
|
||||
}
|
||||
params.putAll(querystringParams);
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,7 +183,7 @@ class Request
|
||||
*/
|
||||
public String getUrl()
|
||||
{
|
||||
return url;
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,7 +193,7 @@ class Request
|
||||
*/
|
||||
public String getSanitizedUrl()
|
||||
{
|
||||
return url.replaceAll("\\?.*", "").replace("\\:\\d{4}", "");
|
||||
return URLUtils.convertUrlToBaseStringURI(url);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,13 +227,27 @@ class Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the connection timeout in milliseconds for the underlying {@link HttpURLConnection}
|
||||
* Sets the connect timeout for the underlying {@link HttpURLConnection}
|
||||
*
|
||||
* @param timeout in milliseconds
|
||||
* @param duration duration of the timeout
|
||||
*
|
||||
* @param unit unit of time (milliseconds, seconds, etc)
|
||||
*/
|
||||
public void setTimeout(int timeout)
|
||||
public void setConnectTimeout(int duration, TimeUnit unit)
|
||||
{
|
||||
this.timeout = timeout;
|
||||
this.connection.setConnectTimeout((int) unit.toMillis(duration));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the read timeout for the underlying {@link HttpURLConnection}
|
||||
*
|
||||
* @param duration duration of the timeout
|
||||
*
|
||||
* @param unit unit of time (milliseconds, seconds, etc)
|
||||
*/
|
||||
public void setReadTimeout(int duration, TimeUnit unit)
|
||||
{
|
||||
this.connection.setReadTimeout((int) unit.toMillis(duration));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -13,7 +13,6 @@ import org.scribe.utils.*;
|
||||
*/
|
||||
public class Response
|
||||
{
|
||||
|
||||
private static final String EMPTY = "";
|
||||
|
||||
private int code;
|
||||
@@ -52,11 +51,6 @@ public class Response
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the code is in the successful or redirect range.
|
||||
*
|
||||
* @return true if successful
|
||||
*/
|
||||
private boolean wasSuccessful()
|
||||
{
|
||||
return getCode() >= 200 && getCode() < 400;
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
package org.scribe.model;
|
||||
|
||||
public class Token
|
||||
{
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents an OAuth token (either request or access token) and its secret
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class Token implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 715000866082812683L;
|
||||
|
||||
private final String token;
|
||||
private final String secret;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param token token value
|
||||
* @param secret token secret
|
||||
*/
|
||||
public Token(String token, String secret)
|
||||
{
|
||||
this.token = token;
|
||||
|
||||
@@ -1,12 +1,25 @@
|
||||
package org.scribe.model;
|
||||
|
||||
/**
|
||||
* Represents an OAuth verifier code.
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class Verifier
|
||||
{
|
||||
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* @param value verifier value
|
||||
*/
|
||||
public Verifier(String value)
|
||||
{
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +1,89 @@
|
||||
package org.scribe.oauth;
|
||||
|
||||
import org.scribe.extractors.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.services.*;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.scribe.builder.api.*;
|
||||
import org.scribe.exceptions.OAuthException;
|
||||
import org.scribe.model.*;
|
||||
|
||||
/**
|
||||
* OAuth 1.0a implementation of {@link OAuthService}
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class OAuth10aServiceImpl implements OAuthService
|
||||
{
|
||||
|
||||
private static final String NO_SCOPE = null;
|
||||
private static final String VERSION = "1.0";
|
||||
|
||||
private OAuthConfig config;
|
||||
private SignatureService signatureService;
|
||||
private TimestampService timestampService;
|
||||
private BaseStringExtractor baseStringExtractor;
|
||||
private HeaderExtractor headerExtractor;
|
||||
private RequestTokenExtractor rtExtractor;
|
||||
private AccessTokenExtractor atExtractor;
|
||||
private DefaultApi10a api;
|
||||
private String scope;
|
||||
|
||||
public OAuth10aServiceImpl(SignatureService signatureService, TimestampService timestampService, BaseStringExtractor baseStringExtractor,
|
||||
HeaderExtractor headerExtractor, RequestTokenExtractor rtExtractor, AccessTokenExtractor atExtractor, OAuthConfig config)
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param api OAuth1.0a api information
|
||||
* @param config OAuth 1.0a configuration param object
|
||||
*/
|
||||
public OAuth10aServiceImpl(DefaultApi10a api, OAuthConfig config)
|
||||
{
|
||||
this.signatureService = signatureService;
|
||||
this.timestampService = timestampService;
|
||||
this.baseStringExtractor = baseStringExtractor;
|
||||
this.headerExtractor = headerExtractor;
|
||||
this.rtExtractor = rtExtractor;
|
||||
this.atExtractor = atExtractor;
|
||||
this.api = api;
|
||||
this.config = config;
|
||||
this.scope = NO_SCOPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Token getRequestToken()
|
||||
{
|
||||
OAuthRequest request = new OAuthRequest(config.getRequestTokenVerb(), config.getRequestTokenEndpoint());
|
||||
OAuthRequest request = null;;
|
||||
try {
|
||||
request = new OAuthRequest(api.getRequestTokenVerb(), api.getRequestTokenEndpoint());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new OAuthException("Problems while creating connection", e);
|
||||
}
|
||||
addOAuthParams(request, OAuthConstants.EMPTY_TOKEN);
|
||||
addOAuthHeader(request);
|
||||
Response response = request.send();
|
||||
return rtExtractor.extract(response.getBody());
|
||||
return api.getRequestTokenExtractor().extract(response.getBody());
|
||||
}
|
||||
|
||||
private void addOAuthParams(OAuthRequest request, Token token)
|
||||
{
|
||||
request.addOAuthParameter(OAuthConstants.TIMESTAMP, timestampService.getTimestampInSeconds());
|
||||
request.addOAuthParameter(OAuthConstants.NONCE, timestampService.getNonce());
|
||||
request.addOAuthParameter(OAuthConstants.TIMESTAMP, api.getTimestampService().getTimestampInSeconds());
|
||||
request.addOAuthParameter(OAuthConstants.NONCE, api.getTimestampService().getNonce());
|
||||
request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, config.getApiKey());
|
||||
request.addOAuthParameter(OAuthConstants.SIGN_METHOD, signatureService.getSignatureMethod());
|
||||
request.addOAuthParameter(OAuthConstants.SIGN_METHOD, api.getSignatureService().getSignatureMethod());
|
||||
request.addOAuthParameter(OAuthConstants.VERSION, getVersion());
|
||||
request.addOAuthParameter(OAuthConstants.CALLBACK, config.getCallback());
|
||||
if(scope != NO_SCOPE) request.addOAuthParameter(OAuthConstants.SCOPE, scope);
|
||||
request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, token));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Token getAccessToken(Token requestToken, Verifier verifier)
|
||||
{
|
||||
OAuthRequest request = new OAuthRequest(config.getAccessTokenVerb(), config.getAccessTokenEndpoint());
|
||||
OAuthRequest request = null;
|
||||
try {
|
||||
request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new OAuthException("Problems while creating connection", e);
|
||||
}
|
||||
request.addOAuthParameter(OAuthConstants.TOKEN, requestToken.getToken());
|
||||
request.addOAuthParameter(OAuthConstants.VERIFIER, verifier.getValue());
|
||||
addOAuthParams(request, requestToken);
|
||||
addOAuthHeader(request);
|
||||
Response response = request.send();
|
||||
return atExtractor.extract(response.getBody());
|
||||
return api.getAccessTokenExtractor().extract(response.getBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void signRequest(Token token, OAuthRequest request)
|
||||
{
|
||||
request.addOAuthParameter(OAuthConstants.TOKEN, token.getToken());
|
||||
@@ -67,20 +91,39 @@ public class OAuth10aServiceImpl implements OAuthService
|
||||
addOAuthHeader(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getVersion()
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addScope(String scope)
|
||||
{
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return api.getAuthorizationUrl(requestToken);
|
||||
}
|
||||
|
||||
private String getSignature(OAuthRequest request, Token token)
|
||||
{
|
||||
String baseString = baseStringExtractor.extract(request);
|
||||
return signatureService.getSignature(baseString, config.getApiSecret(), token.getSecret());
|
||||
String baseString = api.getBaseStringExtractor().extract(request);
|
||||
return api.getSignatureService().getSignature(baseString, config.getApiSecret(), token.getSecret());
|
||||
}
|
||||
|
||||
private void addOAuthHeader(OAuthRequest request)
|
||||
{
|
||||
String oauthHeader = headerExtractor.extract(request);
|
||||
String oauthHeader = api.getHeaderExtractor().extract(request);
|
||||
request.addHeader(OAuthConstants.HEADER, oauthHeader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.scribe.oauth;
|
||||
|
||||
import org.scribe.builder.api.*;
|
||||
import org.scribe.model.*;
|
||||
|
||||
public class OAuth20ServiceImpl implements OAuthService
|
||||
{
|
||||
private static final String VERSION = "2.0";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addScope(String scope)
|
||||
{
|
||||
throw new UnsupportedOperationException("OAuth 2 does not use scopes");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Token getAccessToken(Token requestToken, Verifier verifier)
|
||||
{
|
||||
throw new UnsupportedOperationException("Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Token getRequestToken()
|
||||
{
|
||||
throw new UnsupportedOperationException("Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getVersion()
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void signRequest(Token accessToken, OAuthRequest request)
|
||||
{
|
||||
request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return api.getAuthorizationUrl(config);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,13 +2,59 @@ package org.scribe.oauth;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
/**
|
||||
* The main Scribe object.
|
||||
*
|
||||
* A facade responsible for the retrieval of request and access tokens and for the signing of HTTP requests.
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public interface OAuthService
|
||||
{
|
||||
/**
|
||||
* Retrieve the request token.
|
||||
*
|
||||
* @return request token
|
||||
*/
|
||||
public Token getRequestToken();
|
||||
|
||||
/**
|
||||
* Retrieve the access token
|
||||
*
|
||||
* @param requestToken request token (obtained previously)
|
||||
* @param verifier verifier code
|
||||
* @return access token
|
||||
*/
|
||||
public Token getAccessToken(Token requestToken, Verifier verifier);
|
||||
|
||||
/**
|
||||
* Signs am OAuth request
|
||||
*
|
||||
* @param accessToken access token (obtained previously)
|
||||
* @param request request to sign
|
||||
*/
|
||||
public void signRequest(Token accessToken, OAuthRequest request);
|
||||
|
||||
/**
|
||||
* Returns the OAuth version of the service.
|
||||
*
|
||||
* @return oauth version as string
|
||||
*/
|
||||
public String getVersion();
|
||||
|
||||
/**
|
||||
* Adds the 'scope' parameter. This is **not** a default OAuth parameter and the setting is optional.
|
||||
*
|
||||
* @param scope OAuth Api scope (optional)
|
||||
*/
|
||||
public void addScope(String scope);
|
||||
|
||||
/**
|
||||
* Returns the URL where you should redirect your users to authenticate
|
||||
* your application.
|
||||
*
|
||||
* @param requestToken the request token you need to authorize
|
||||
* @return the URL where you should redirect your users
|
||||
*/
|
||||
public String getAuthorizationUrl(Token requestToken);
|
||||
}
|
||||
@@ -7,22 +7,30 @@ import org.apache.commons.codec.binary.*;
|
||||
import org.scribe.exceptions.*;
|
||||
import org.scribe.utils.*;
|
||||
|
||||
/**
|
||||
* HMAC-SHA1 implementation of {@SignatureService}
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*
|
||||
*/
|
||||
public class HMACSha1SignatureService implements SignatureService
|
||||
{
|
||||
|
||||
private static final String EMPTY_STRING = "";
|
||||
private static final String CARRIAGE_RETURN = "\r\n";
|
||||
private static final String UTF8 = "UTF-8";
|
||||
private static final String HMAC_SHA1 = "HmacSHA1";
|
||||
private static final String METHOD = "HMAC-SHA1";
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getSignature(String baseString, String apiSecret, String tokenSecret)
|
||||
{
|
||||
try
|
||||
{
|
||||
Preconditions.checkEmptyString(baseString, "Base string cant be null or empty string");
|
||||
Preconditions.checkEmptyString(apiSecret, "Api secret cant be null or empty string");
|
||||
return doSign(baseString, apiSecret + '&' + tokenSecret);
|
||||
return doSign(baseString, URLUtils.percentEncode(apiSecret) + '&' + URLUtils.percentEncode(tokenSecret));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -39,6 +47,9 @@ public class HMACSha1SignatureService implements SignatureService
|
||||
return new String(Base64.encodeBase64(bytes)).replace(CARRIAGE_RETURN, EMPTY_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getSignatureMethod()
|
||||
{
|
||||
return METHOD;
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
package org.scribe.services;
|
||||
|
||||
/**
|
||||
* Signs a base string, returning the OAuth signature
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*
|
||||
*/
|
||||
public interface SignatureService
|
||||
{
|
||||
/**
|
||||
* Returns the signature
|
||||
*
|
||||
* @param baseString url-encoded string to sign
|
||||
* @param apiSecret api secret for your app
|
||||
* @param tokenSecret token secret (empty string for the request token step)
|
||||
*
|
||||
* @return signature
|
||||
*/
|
||||
public String getSignature(String baseString, String apiSecret, String tokenSecret);
|
||||
|
||||
/**
|
||||
* Returns the signature method/algorithm
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getSignatureMethod();
|
||||
}
|
||||
@@ -1,9 +1,25 @@
|
||||
package org.scribe.services;
|
||||
|
||||
/**
|
||||
* Unix epoch timestamp generator.
|
||||
*
|
||||
* This class is useful for stubbing in tests.
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public interface TimestampService
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the unix epoch timestamp in seconds
|
||||
*
|
||||
* @return timestamp
|
||||
*/
|
||||
public String getTimestampInSeconds();
|
||||
|
||||
/**
|
||||
* Returns a nonce (unique value for each request)
|
||||
*
|
||||
* @return nonce
|
||||
*/
|
||||
public String getNonce();
|
||||
}
|
||||
@@ -2,22 +2,35 @@ package org.scribe.services;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Implementation of {@link TimestampService} using plain java classes.
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class TimestampServiceImpl implements TimestampService
|
||||
{
|
||||
|
||||
private Timer timer;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public TimestampServiceImpl()
|
||||
{
|
||||
timer = new Timer();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getNonce()
|
||||
{
|
||||
Long ts = getTs();
|
||||
return String.valueOf(ts + timer.getRandomInteger());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getTimestampInSeconds()
|
||||
{
|
||||
return String.valueOf(getTs());
|
||||
@@ -33,14 +46,19 @@ public class TimestampServiceImpl implements TimestampService
|
||||
this.timer = timer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class that uses {@link System} for generating the timestamps.
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
static class Timer
|
||||
{
|
||||
public Long getMilis()
|
||||
Long getMilis()
|
||||
{
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public Integer getRandomInteger()
|
||||
Integer getRandomInteger()
|
||||
{
|
||||
return new Random().nextInt();
|
||||
}
|
||||
|
||||
@@ -2,9 +2,19 @@ package org.scribe.utils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Utils for {@link Map} manipulation
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class MapUtils
|
||||
{
|
||||
|
||||
/**
|
||||
* Sorts a Map
|
||||
*
|
||||
* @param map unsorted map
|
||||
* @return sorted map
|
||||
*/
|
||||
public static final Map<String, String> sort(Map<String, String> map)
|
||||
{
|
||||
Preconditions.checkNotNull(map, "Cannot sort a null object.");
|
||||
|
||||
@@ -1,27 +1,63 @@
|
||||
package org.scribe.utils;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.scribe.model.OAuthConstants;
|
||||
|
||||
/**
|
||||
* Utils for checking preconditions and invariants
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class Preconditions
|
||||
{
|
||||
private static final String DEFAULT_MESSAGE = "Received an invalid parameter";
|
||||
private static final Pattern URL_PATTERN = Pattern.compile("[a-zA-Z_-]+://\\S+");
|
||||
|
||||
/**
|
||||
* Checks that an object is not null.
|
||||
*
|
||||
* @param object any object
|
||||
* @param errorMsg error message
|
||||
*
|
||||
* @throws IllegalArgumentException if the object is null
|
||||
*/
|
||||
public static void checkNotNull(Object object, String errorMsg)
|
||||
{
|
||||
check(object != null, errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a string is not null or empty
|
||||
*
|
||||
* @param string any string
|
||||
* @param errorMsg error message
|
||||
*
|
||||
* @throws IllegalArgumentException if the string is null or empty
|
||||
*/
|
||||
public static void checkEmptyString(String string, String errorMsg)
|
||||
{
|
||||
check(string != null && !string.trim().equals(""), errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a URL is valid
|
||||
*
|
||||
* @param url any string
|
||||
* @param errorMsg error message
|
||||
*/
|
||||
public static void checkValidUrl(String url, String errorMsg)
|
||||
{
|
||||
checkEmptyString(url, errorMsg);
|
||||
check(isUrl(url), errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a URL is a valid OAuth callback
|
||||
*
|
||||
* @param url any string
|
||||
* @param errorMsg error message
|
||||
*/
|
||||
public static void checkValidOAuthCallback(String url, String errorMsg)
|
||||
{
|
||||
checkEmptyString(url, errorMsg);
|
||||
@@ -31,9 +67,9 @@ public class Preconditions
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isUrl(String url)
|
||||
private static boolean isUrl(String url)
|
||||
{
|
||||
return url.startsWith("http://") || url.startsWith("https://");
|
||||
return URL_PATTERN.matcher(url).matches();
|
||||
}
|
||||
|
||||
private static void check(boolean requirements, String error)
|
||||
|
||||
@@ -2,9 +2,19 @@ package org.scribe.utils;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Utils to deal with Streams.
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class StreamUtils
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the stream contents as an UTF-8 encoded string
|
||||
*
|
||||
* @param is input stream
|
||||
* @return string contents
|
||||
*/
|
||||
public static String getStreamContents(InputStream is)
|
||||
{
|
||||
Preconditions.checkNotNull(is, "Cannot get String from a null object");
|
||||
@@ -26,7 +36,7 @@ public class StreamUtils
|
||||
return out.toString();
|
||||
} catch (IOException ioe)
|
||||
{
|
||||
throw new RuntimeException("Error while reading response body", ioe);
|
||||
throw new IllegalStateException("Error while reading response body", ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,42 @@ import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.scribe.exceptions.*;
|
||||
|
||||
/**
|
||||
* Utils to deal with URL and url-encodings
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
*/
|
||||
public class URLUtils
|
||||
{
|
||||
|
||||
private static final String EMPTY_STRING = "";
|
||||
private static final String UTF_8 = "UTF-8";
|
||||
private static final char PAIR_SEPARATOR = '=';
|
||||
private static final char PARAM_SEPARATOR = '&';
|
||||
private static final char QUERY_STRING_SEPARATOR = '?';
|
||||
private static final String HTTP_PROTOCOL = "http";
|
||||
private static final int HTTP_DEFAULT_PORT = 80;
|
||||
private static final String HTTPS_PROTOCOL = "https";
|
||||
private static final int HTTPS_DEFAULT_PORT = 443;
|
||||
|
||||
private static final String ERROR_MSG = String.format("Cannot find specified encoding: %s", UTF_8);
|
||||
|
||||
private static final Set<EncodingRule> ENCODING_RULES;
|
||||
|
||||
static
|
||||
{
|
||||
Set<EncodingRule> rules = new HashSet<EncodingRule>();
|
||||
rules.add(new EncodingRule("*","%2A"));
|
||||
rules.add(new EncodingRule("+","%20"));
|
||||
rules.add(new EncodingRule("%7E", "~"));
|
||||
ENCODING_RULES = Collections.unmodifiableSet(rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a map into a form-url-encoded string (key=value&key2&key3=value)
|
||||
*
|
||||
* @param map any map
|
||||
* @return form-url-encoded string
|
||||
*/
|
||||
public static String formURLEncodeMap(Map<String, String> map)
|
||||
{
|
||||
Preconditions.checkNotNull(map, "Cannot url-encode a null object");
|
||||
@@ -24,40 +48,151 @@ public class URLUtils
|
||||
|
||||
private static String doFormUrlEncode(Map<String, String> map)
|
||||
{
|
||||
StringBuffer encodedString = new StringBuffer();
|
||||
StringBuffer encodedString = new StringBuffer(map.size() * 20);
|
||||
for (String key : map.keySet())
|
||||
{
|
||||
encodedString.append(percentEncode(key)).append(PAIR_SEPARATOR).append(percentEncode(map.get(key))).append(PARAM_SEPARATOR);
|
||||
if(encodedString.length() > 0)
|
||||
{
|
||||
encodedString.append(PARAM_SEPARATOR);
|
||||
}
|
||||
encodedString.append(urlEncodeWrapper(key));
|
||||
if (map.get(key).length() > 0) {
|
||||
encodedString.append(PAIR_SEPARATOR).append(urlEncodeWrapper(map.get(key)));
|
||||
}
|
||||
}
|
||||
return removeTrailingSeparator(encodedString);
|
||||
}
|
||||
|
||||
private static String removeTrailingSeparator(StringBuffer buffer)
|
||||
{
|
||||
return buffer.toString().substring(0, buffer.length() - 1);
|
||||
return encodedString.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Percent encodes a string
|
||||
*
|
||||
* @param plain
|
||||
* @return percent encoded string
|
||||
*/
|
||||
public static String percentEncode(String string)
|
||||
{
|
||||
Preconditions.checkNotNull(string, "Cannot encode null string");
|
||||
try
|
||||
{
|
||||
return URLEncoder.encode(string, UTF_8);
|
||||
} catch (UnsupportedEncodingException uee)
|
||||
String encoded = URLEncoder.encode(string, UTF_8);
|
||||
for(EncodingRule rule : ENCODING_RULES)
|
||||
{
|
||||
encoded = rule.apply(encoded);
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
catch (UnsupportedEncodingException uee)
|
||||
{
|
||||
throw new OAuthException(ERROR_MSG, uee);
|
||||
throw new IllegalStateException(ERROR_MSG, uee);
|
||||
}
|
||||
}
|
||||
|
||||
public static String percentDecode(String string)
|
||||
/**
|
||||
* URL encodes a string
|
||||
*
|
||||
* @param plain
|
||||
* @return percent encoded string
|
||||
*/
|
||||
public static String urlEncodeWrapper(String string)
|
||||
{
|
||||
Preconditions.checkNotNull(string, "Cannot encode null string");
|
||||
try
|
||||
{
|
||||
return URLEncoder.encode(string, UTF_8);
|
||||
}
|
||||
catch (UnsupportedEncodingException uee)
|
||||
{
|
||||
throw new IllegalStateException(ERROR_MSG, uee);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URL decodes a string
|
||||
*
|
||||
* @param string percent encoded string
|
||||
* @return plain string
|
||||
*/
|
||||
public static String urlDecodeWrapper(String string)
|
||||
{
|
||||
Preconditions.checkNotNull(string, "Cannot decode null string");
|
||||
try
|
||||
{
|
||||
return URLDecoder.decode(string, UTF_8);
|
||||
} catch (UnsupportedEncodingException uee)
|
||||
}
|
||||
catch (UnsupportedEncodingException uee)
|
||||
{
|
||||
throw new OAuthException(ERROR_MSG, uee);
|
||||
throw new IllegalStateException(ERROR_MSG, uee);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append given parameters to the query string of the url
|
||||
*
|
||||
* @param url the url to append parameters to
|
||||
* @param params any map
|
||||
* @return new url with parameters on query string
|
||||
*/
|
||||
public static String appendParametersToQueryString(String url, Map<String, String> params)
|
||||
{
|
||||
Preconditions.checkNotNull(url, "Cannot append to null URL");
|
||||
String queryString = URLUtils.formURLEncodeMap(params);
|
||||
if (queryString.length() == 0) return url;
|
||||
|
||||
// Check if there are parameters in the url already and use '&' instead of '?'
|
||||
url += url.indexOf(QUERY_STRING_SEPARATOR) != -1 ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR;
|
||||
url += queryString;
|
||||
return url;
|
||||
}
|
||||
|
||||
private static final class EncodingRule
|
||||
{
|
||||
private final String ch;
|
||||
private final String toCh;
|
||||
|
||||
EncodingRule(String ch, String toCh)
|
||||
{
|
||||
this.ch = ch;
|
||||
this.toCh = toCh;
|
||||
}
|
||||
|
||||
String apply(String string) {
|
||||
return string.replace(ch, toCh);
|
||||
}
|
||||
}
|
||||
|
||||
public static String concatSortedPercentEncodedParams(Map<String, String> params) {
|
||||
StringBuilder target = new StringBuilder();
|
||||
for (String key:params.keySet()){
|
||||
target.append(key);
|
||||
target.append(PAIR_SEPARATOR);
|
||||
target.append(params.get(key));
|
||||
target.append(PARAM_SEPARATOR);
|
||||
}
|
||||
return target.deleteCharAt(target.length() - 1).toString();
|
||||
}
|
||||
|
||||
public static String convertUrlToBaseStringURI(URL url){
|
||||
URI uri = null;
|
||||
try {
|
||||
uri = url.toURI();
|
||||
} catch (URISyntaxException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
String scheme = uri.getScheme().toLowerCase();
|
||||
String host = uri.getHost().toLowerCase();
|
||||
int port = uri.getPort();
|
||||
if (
|
||||
(scheme.equals(HTTP_PROTOCOL) && port == HTTP_DEFAULT_PORT)
|
||||
|| (scheme.equals(HTTPS_PROTOCOL) && port == HTTPS_DEFAULT_PORT)
|
||||
){
|
||||
port = -1;
|
||||
}
|
||||
URI baseUri = null;
|
||||
try {
|
||||
baseUri = new URI(scheme,null, host, port, uri.getPath(), null, null);
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return baseUri.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.scribe.builder;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.*;
|
||||
import org.scribe.builder.api.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.oauth.*;
|
||||
|
||||
public class ServiceBuilderTest
|
||||
{
|
||||
private ServiceBuilder builder;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
builder = new ServiceBuilder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnOOBasDefaultCallback()
|
||||
{
|
||||
builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").build();
|
||||
assertEquals(ApiMock.config.getApiKey(), "key");
|
||||
assertEquals(ApiMock.config.getApiSecret(), "secret");
|
||||
assertEquals(ApiMock.config.getCallback(), OAuthConstants.OUT_OF_BAND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAcceptValidCallbackUrl()
|
||||
{
|
||||
builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").callback("http://example.com").build();
|
||||
assertEquals(ApiMock.config.getApiKey(), "key");
|
||||
assertEquals(ApiMock.config.getApiSecret(), "secret");
|
||||
assertEquals(ApiMock.config.getCallback(), "http://example.com");
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void shouldNotAcceptAnInvalidUrlAsCallback()
|
||||
{
|
||||
builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").callback("example.com").build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAcceptAnScope()
|
||||
{
|
||||
builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").scope("rss-api").build();
|
||||
assertEquals(ApiMock.config.getApiKey(), "key");
|
||||
assertEquals(ApiMock.config.getApiSecret(), "secret");
|
||||
assertEquals(ApiMock.scope, "rss-api");
|
||||
}
|
||||
|
||||
public static class ApiMock implements Api
|
||||
{
|
||||
public static OAuthConfig config;
|
||||
public static String scope;
|
||||
|
||||
@Override
|
||||
public OAuthService createService(OAuthConfig config, String scope)
|
||||
{
|
||||
ApiMock.config = config;
|
||||
ApiMock.scope = scope;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.scribe.examples;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.*;
|
||||
|
||||
import org.scribe.builder.*;
|
||||
import org.scribe.builder.api.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.oauth.*;
|
||||
|
||||
public class FacebookExample
|
||||
{
|
||||
private static final String NETWORK_NAME = "Facebook";
|
||||
private static final String PROTECTED_RESOURCE_URL = "https://graph.facebook.com/me";
|
||||
private static final String NO_SECRET_NEEDED = "";
|
||||
private static final Token EMPTY_TOKEN = null;
|
||||
|
||||
public static void main(String[] args) throws MalformedURLException
|
||||
{
|
||||
// Replace these with your own api key and secret
|
||||
String apiKey = "your_api_key";
|
||||
String apiSecret = "your_api_secret";
|
||||
OAuthService service = new ServiceBuilder()
|
||||
.provider(FacebookApi.class)
|
||||
.apiKey(apiKey)
|
||||
.apiSecret(apiSecret)
|
||||
.callback("http://www.example.com/oauth_callback/")
|
||||
.build();
|
||||
Scanner in = new Scanner(System.in);
|
||||
|
||||
System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
|
||||
System.out.println();
|
||||
|
||||
// Obtain the Authorization URL
|
||||
System.out.println("Fetching the Authorization URL...");
|
||||
String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
|
||||
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 access token here");
|
||||
System.out.print(">>");
|
||||
Token accessToken = new Token(in.nextLine(), NO_SECRET_NEEDED);
|
||||
System.out.println();
|
||||
|
||||
// Now let's go and ask for a protected resource!
|
||||
System.out.println("Now we're going to access a protected resource...");
|
||||
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
|
||||
service.signRequest(accessToken, request);
|
||||
Response response = request.send();
|
||||
System.out.println("Got it! Lets see what we found...");
|
||||
System.out.println();
|
||||
System.out.println(response.getCode());
|
||||
System.out.println(response.getBody());
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.scribe.examples;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.scribe.builder.*;
|
||||
@@ -9,10 +10,9 @@ import org.scribe.oauth.*;
|
||||
|
||||
public class FoursquareExample
|
||||
{
|
||||
private static final String AUTHORIZE_URL = "http://foursquare.com/oauth/authorize?oauth_token=";
|
||||
private static final String PROTECTED_RESOURCE_URL = "http://api.foursquare.com/v1/user";
|
||||
|
||||
public static void main(String[] args)
|
||||
public static void main(String[] args) throws MalformedURLException
|
||||
{
|
||||
OAuthService service = new ServiceBuilder()
|
||||
.provider(FoursquareApi.class)
|
||||
@@ -31,7 +31,7 @@ public class FoursquareExample
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Now go and authorize Scribe here:");
|
||||
System.out.println(AUTHORIZE_URL + requestToken.getToken());
|
||||
System.out.println(service.getAuthorizationUrl(requestToken));
|
||||
System.out.println("And paste the verifier here");
|
||||
System.out.print(">>");
|
||||
Verifier verifier = new Verifier(in.nextLine());
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.scribe.examples;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.*;
|
||||
|
||||
import org.scribe.builder.*;
|
||||
import org.scribe.builder.api.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.oauth.*;
|
||||
|
||||
public class GoogleExample
|
||||
{
|
||||
private static final String NETWORK_NAME = "Google";
|
||||
private static final String AUTHORIZE_URL = "https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=";
|
||||
private static final String PROTECTED_RESOURCE_URL = "https://docs.google.com/feeds/default/private/full/";
|
||||
private static final String SCOPE = "https://docs.google.com/feeds/";
|
||||
|
||||
public static void main(String[] args) throws MalformedURLException
|
||||
{
|
||||
OAuthService service = new ServiceBuilder()
|
||||
.provider(GoogleApi.class)
|
||||
.apiKey("anonymous")
|
||||
.apiSecret("anonymous")
|
||||
.scope(SCOPE)
|
||||
.build();
|
||||
Scanner in = new Scanner(System.in);
|
||||
|
||||
System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
|
||||
System.out.println();
|
||||
|
||||
// Obtain the Request Token
|
||||
System.out.println("Fetching the Request Token...");
|
||||
Token requestToken = service.getRequestToken();
|
||||
System.out.println("Got the Request Token!");
|
||||
System.out.println("(if your curious it looks like this: " + requestToken + " )");
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Now go and authorize Scribe here:");
|
||||
System.out.println(AUTHORIZE_URL + requestToken.getToken());
|
||||
System.out.println("And paste the verifier here");
|
||||
System.out.print(">>");
|
||||
Verifier verifier = new Verifier(in.nextLine());
|
||||
System.out.println();
|
||||
|
||||
// Trade the Request Token and Verfier for the Access Token
|
||||
System.out.println("Trading the Request Token for an Access Token...");
|
||||
Token accessToken = service.getAccessToken(requestToken, verifier);
|
||||
System.out.println("Got the Access Token!");
|
||||
System.out.println("(if your curious it looks like this: " + accessToken + " )");
|
||||
System.out.println();
|
||||
|
||||
// Now let's go and ask for a protected resource!
|
||||
System.out.println("Now we're going to access a protected resource...");
|
||||
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
|
||||
service.signRequest(accessToken, request);
|
||||
request.addHeader("GData-Version", "3.0");
|
||||
Response response = request.send();
|
||||
System.out.println("Got it! Lets see what we found...");
|
||||
System.out.println();
|
||||
System.out.println(response.getCode());
|
||||
System.out.println(response.getBody());
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.scribe.examples;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.scribe.builder.*;
|
||||
@@ -9,18 +10,17 @@ import org.scribe.oauth.*;
|
||||
|
||||
public class LinkedInExample
|
||||
{
|
||||
private static final String AUTHORIZE_URL = "https://api.linkedin.com/uas/oauth/authorize?oauth_token=";
|
||||
private static final String PROTECTED_RESOURCE_URL = "http://api.linkedin.com/v1/people/~/connections:(id,last-name)";
|
||||
|
||||
public static void main(String[] args)
|
||||
public static void main(String[] args) throws MalformedURLException
|
||||
{
|
||||
OAuthService service = new ServiceBuilder()
|
||||
.provider(LinkedInApi.class)
|
||||
.apiKey("CiEgwWDkA5BFpNrc0RfGyVuSlOh4tig5kOTZ9q97qcXNrFl7zqk-Ts7DqRGaKDCV")
|
||||
.apiSecret("dhho4dfoCmiQXrkw4yslork5XWLFnPSuMR-8gscPVjY4jqFFHPYWJKgpFl4uLTM6")
|
||||
.build();
|
||||
|
||||
.provider(LinkedInApi.class)
|
||||
.apiKey("CiEgwWDkA5BFpNrc0RfGyVuSlOh4tig5kOTZ9q97qcXNrFl7zqk-Ts7DqRGaKDCV")
|
||||
.apiSecret("dhho4dfoCmiQXrkw4yslork5XWLFnPSuMR-8gscPVjY4jqFFHPYWJKgpFl4uLTM6")
|
||||
.build();
|
||||
Scanner in = new Scanner(System.in);
|
||||
|
||||
System.out.println("=== LinkedIn's OAuth Workflow ===");
|
||||
System.out.println();
|
||||
|
||||
@@ -31,7 +31,7 @@ public class LinkedInExample
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Now go and authorize Scribe here:");
|
||||
System.out.println(AUTHORIZE_URL + requestToken.getToken());
|
||||
System.out.println(service.getAuthorizationUrl(requestToken));
|
||||
System.out.println("And paste the verifier here");
|
||||
System.out.print(">>");
|
||||
Verifier verifier = new Verifier(in.nextLine());
|
||||
@@ -55,8 +55,6 @@ public class LinkedInExample
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
|
||||
|
||||
System.out.println(service.getRequestToken());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.scribe.examples;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.scribe.builder.*;
|
||||
@@ -9,10 +10,9 @@ import org.scribe.oauth.*;
|
||||
|
||||
public class TwitterExample
|
||||
{
|
||||
private static final String AUTHORIZE_URL = "https://twitter.com/oauth/authorize?oauth_token=";
|
||||
private static final String PROTECTED_RESOURCE_URL = "http://api.twitter.com/1/account/verify_credentials.xml";
|
||||
|
||||
public static void main(String[] args)
|
||||
public static void main(String[] args) throws MalformedURLException
|
||||
{
|
||||
OAuthService service = new ServiceBuilder()
|
||||
.provider(TwitterApi.class)
|
||||
@@ -31,7 +31,7 @@ public class TwitterExample
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Now go and authorize Scribe here:");
|
||||
System.out.println(AUTHORIZE_URL + requestToken.getToken());
|
||||
System.out.println(service.getAuthorizationUrl(requestToken));
|
||||
System.out.println("And paste the verifier here");
|
||||
System.out.print(">>");
|
||||
Verifier verifier = new Verifier(in.nextLine());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.scribe.examples;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.scribe.builder.*;
|
||||
@@ -9,20 +10,18 @@ import org.scribe.oauth.*;
|
||||
|
||||
public class YahooExample
|
||||
{
|
||||
private static final String NETWORK_NAME = "Yahoo";
|
||||
private static final String AUTHORIZE_URL = "https://api.login.yahoo.com/oauth/v2/request_auth?oauth_token=";
|
||||
private static final String PROTECTED_RESOURCE_URL = "http://social.yahooapis.com/v1/user/A6ROU63MXWDCW3Y5MGCYWVHDJI/profile/status?format=json";
|
||||
|
||||
public static void main(String[] args)
|
||||
public static void main(String[] args) throws MalformedURLException
|
||||
{
|
||||
OAuthService service = new ServiceBuilder()
|
||||
.provider(YahooApi.class)
|
||||
.apiKey("dj0yJmk9TXZDWVpNVVdGaVFmJmQ9WVdrOWMweHZXbkZLTkhVbWNHbzlNVEl5TWprd05qUTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wMw--")
|
||||
.apiSecret("262be559f92a2be20c4c039419018f2b48cdfce9")
|
||||
.build();
|
||||
.provider(YahooApi.class)
|
||||
.apiKey("dj0yJmk9TXZDWVpNVVdGaVFmJmQ9WVdrOWMweHZXbkZLTkhVbWNHbzlNVEl5TWprd05qUTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wMw--")
|
||||
.apiSecret("262be559f92a2be20c4c039419018f2b48cdfce9")
|
||||
.build();
|
||||
Scanner in = new Scanner(System.in);
|
||||
|
||||
System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
|
||||
System.out.println("=== Yahoo's OAuth Workflow ===");
|
||||
System.out.println();
|
||||
|
||||
// Obtain the Request Token
|
||||
@@ -32,7 +31,7 @@ public class YahooExample
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Now go and authorize Scribe here:");
|
||||
System.out.println(AUTHORIZE_URL + requestToken.getToken());
|
||||
System.out.println(service.getAuthorizationUrl(requestToken));
|
||||
System.out.println("And paste the verifier here");
|
||||
System.out.print(">>");
|
||||
Verifier verifier = new Verifier(in.nextLine());
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.scribe.extractors;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.junit.*;
|
||||
import org.scribe.exceptions.*;
|
||||
import org.scribe.model.*;
|
||||
@@ -12,21 +14,33 @@ public class BaseStringExtractorTest
|
||||
|
||||
private BaseStringExtractorImpl extractor;
|
||||
private OAuthRequest request;
|
||||
private OAuthRequest request2;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
public void setup() throws MalformedURLException
|
||||
{
|
||||
request = ObjectMother.createSampleOAuthRequest();
|
||||
request2 = ObjectMother.createSampleOAuthRequest2();
|
||||
extractor = new BaseStringExtractorImpl();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractBaseStringFromOAuthRequest()
|
||||
{
|
||||
String expected = "GET&http%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E*%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
|
||||
String expected = "GET&http%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
|
||||
String baseString = extractor.extract(request);
|
||||
assertEquals(expected, baseString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractBaseStringFromOAuthRequest2()
|
||||
{
|
||||
String expected = "GET&http%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
|
||||
String baseString = extractor.extract(request2);
|
||||
assertEquals(expected, baseString);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionIfRquestIsNull()
|
||||
@@ -36,9 +50,17 @@ public class BaseStringExtractorTest
|
||||
}
|
||||
|
||||
@Test(expected = OAuthParametersMissingException.class)
|
||||
public void shouldThrowExceptionIfRquestHasNoOAuthParameters()
|
||||
public void shouldThrowExceptionIfRquestHasNoOAuthParameters() throws MalformedURLException
|
||||
{
|
||||
OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com");
|
||||
extractor.extract(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldProperlyEncodeSpaces()
|
||||
{
|
||||
String expected = "GET&http%3A%2F%2Fexample.com&body%3Dthis%2520param%2520has%2520whitespace%26oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
|
||||
request.addBodyParameter("body", "this param has whitespace");
|
||||
assertEquals(expected, extractor.extract(request));
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package org.scribe.extractors;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.junit.*;
|
||||
import org.scribe.exceptions.*;
|
||||
import org.scribe.model.*;
|
||||
@@ -14,7 +16,7 @@ public class HeaderExtractorTest
|
||||
private OAuthRequest request;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
public void setup() throws MalformedURLException
|
||||
{
|
||||
request = ObjectMother.createSampleOAuthRequest();
|
||||
extractor = new HeaderExtractorImpl();
|
||||
@@ -24,7 +26,7 @@ public class HeaderExtractorTest
|
||||
public void shouldExtractStandardHeader()
|
||||
{
|
||||
String expected = "OAuth oauth_callback=\"http%3A%2F%2Fexample%2Fcallback\", " + "oauth_signature=\"OAuth-Signature\", "
|
||||
+ "oauth_consumer_key=\"AS%23%24%5E*%40%26\", " + "oauth_timestamp=\"123456\"";
|
||||
+ "oauth_consumer_key=\"AS%23%24%5E%2A%40%26\", " + "oauth_timestamp=\"123456\"";
|
||||
String header = extractor.extract(request);
|
||||
assertEquals(expected, header);
|
||||
}
|
||||
@@ -37,7 +39,7 @@ public class HeaderExtractorTest
|
||||
}
|
||||
|
||||
@Test(expected = OAuthParametersMissingException.class)
|
||||
public void shouldExceptionIfRequestHasNoOAuthParams()
|
||||
public void shouldExceptionIfRequestHasNoOAuthParams() throws MalformedURLException
|
||||
{
|
||||
OAuthRequest emptyRequest = new OAuthRequest(Verb.GET, "http://example.com");
|
||||
extractor.extract(emptyRequest);
|
||||
|
||||
@@ -10,22 +10,17 @@ public class OAuthConfigTest
|
||||
@Test
|
||||
public void shouldReturnDefaultValuesIfNotSet()
|
||||
{
|
||||
OAuthConfig config = new OAuthConfig();
|
||||
assertEquals(Verb.GET, config.getAccessTokenVerb());
|
||||
assertEquals(Verb.GET, config.getRequestTokenVerb());
|
||||
OAuthConfig config = new OAuthConfig("key", "secret");
|
||||
assertEquals(OAuthConstants.OUT_OF_BAND, config.getCallback());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldOverrideDefaultsIfSet()
|
||||
{
|
||||
OAuthConfig config = new OAuthConfig();
|
||||
config.setCallback("http://callback");
|
||||
config.setAccessTokenVerb(Verb.POST);
|
||||
config.setRequestTokenVerb(Verb.POST);
|
||||
OAuthConfig config = new OAuthConfig("key", "secret", "http://callback");
|
||||
assertEquals("http://callback", config.getCallback());
|
||||
assertEquals(Verb.POST, config.getAccessTokenVerb());
|
||||
assertEquals(Verb.POST, config.getRequestTokenVerb());
|
||||
assertEquals("key", config.getApiKey());
|
||||
assertEquals("secret", config.getApiSecret());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package org.scribe.model;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
public class OAuthRequestTest
|
||||
@@ -10,7 +12,7 @@ public class OAuthRequestTest
|
||||
private OAuthRequest request;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
public void setup() throws MalformedURLException
|
||||
{
|
||||
request = new OAuthRequest(Verb.GET, "http://example.com");
|
||||
}
|
||||
@@ -21,8 +23,9 @@ public class OAuthRequestTest
|
||||
request.addOAuthParameter(OAuthConstants.TOKEN, "token");
|
||||
request.addOAuthParameter(OAuthConstants.NONCE, "nonce");
|
||||
request.addOAuthParameter(OAuthConstants.TIMESTAMP, "ts");
|
||||
request.addOAuthParameter(OAuthConstants.SCOPE, "feeds");
|
||||
|
||||
assertEquals(3, request.getOauthParameters().size());
|
||||
assertEquals(4, request.getOauthParameters().size());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.scribe.model;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
public class RequestTest
|
||||
@@ -17,7 +19,7 @@ public class RequestTest
|
||||
connection = new ConnectionStub();
|
||||
postRequest = new Request(Verb.POST, "http://example.com");
|
||||
postRequest.setConnection(connection);
|
||||
getRequest = new Request(Verb.GET, "http://example.com?qsparam=value&other=value+with+spaces");
|
||||
getRequest = new Request(Verb.GET, "http://example.com?qsparam=value&other+param=value+with+spaces");
|
||||
getRequest.setConnection(connection);
|
||||
}
|
||||
|
||||
@@ -34,6 +36,8 @@ public class RequestTest
|
||||
assertEquals(2, getRequest.getQueryStringParams().size());
|
||||
assertEquals(0, postRequest.getQueryStringParams().size());
|
||||
assertTrue(getRequest.getQueryStringParams().containsKey("qsparam"));
|
||||
assertTrue(getRequest.getQueryStringParams().get("qsparam").equals("value"));
|
||||
assertTrue(getRequest.getQueryStringParams().get("other param").equals("value with spaces"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -65,4 +69,46 @@ public class RequestTest
|
||||
assertTrue(connection.getHeaders().containsKey("Content-Length"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAllowAddingQuerystringParametersAfterCreation() throws MalformedURLException
|
||||
{
|
||||
Request request = new Request(Verb.GET, "http://example.com?one=val");
|
||||
request.addQuerystringParameter("two", "other val");
|
||||
request.addQuerystringParameter("more", "params");
|
||||
assertEquals(3, request.getQueryStringParams().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sanatizeUrlTest() throws MalformedURLException
|
||||
{
|
||||
Request request = new Request(Verb.GET, "http://example.com?one=val");
|
||||
assertEquals("http://example.com", request.getSanitizedUrl());
|
||||
|
||||
request = new Request(Verb.GET, "http://EXAMPLE.com:80/?one=val");
|
||||
assertEquals("http://example.com/", request.getSanitizedUrl());
|
||||
|
||||
request = new Request(Verb.GET, "http://EXAMPLE.com:8080?one=val");
|
||||
assertEquals("http://example.com:8080", request.getSanitizedUrl());
|
||||
|
||||
request = new Request(Verb.GET, "http://EXAMPLE.com:8080?one=val");
|
||||
assertEquals("http://example.com:8080", request.getSanitizedUrl());
|
||||
|
||||
request = new Request(Verb.GET, "http://EXAMPLE.com:80/test/?one=val");
|
||||
assertEquals("http://example.com/test/", request.getSanitizedUrl());
|
||||
|
||||
request = new Request(Verb.GET, "http://EXAMPLE.com:8080/test/?one=val#Hello");
|
||||
assertEquals("http://example.com:8080/test/", request.getSanitizedUrl());
|
||||
|
||||
request = new Request(Verb.GET, "HTTP://EXAMPLE.com:8080/test/?one=val#Hello");
|
||||
assertEquals("http://example.com:8080/test/", request.getSanitizedUrl());
|
||||
|
||||
//From RFC5849 example p.20
|
||||
request = new Request(Verb.GET, "http://example.com:80/r%20v/X?id=123");
|
||||
assertEquals("http://example.com/r%20v/X", request.getSanitizedUrl());
|
||||
|
||||
//From RFC5849 example p.20
|
||||
request = new Request(Verb.GET, "https://www.example.com:8080/?q=1");
|
||||
assertEquals("https://www.example.com:8080/", request.getSanitizedUrl());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.scribe.model;
|
||||
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
public class VerifierTest
|
||||
{
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowErrorForNullString()
|
||||
{
|
||||
new Verifier(null);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package org.scribe.services;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.*;
|
||||
import org.scribe.exceptions.OAuthException;
|
||||
import org.scribe.exceptions.*;
|
||||
|
||||
public class HMACSha1SignatureServiceTest
|
||||
{
|
||||
@@ -29,7 +29,7 @@ public class HMACSha1SignatureServiceTest
|
||||
String apiSecret = "api secret";
|
||||
String tokenSecret = "token secret";
|
||||
String baseString = "base string";
|
||||
String signature = "cyxvUDZY/5cQBcBiKulaNgnhN/w=";
|
||||
String signature = "uGymw2KHOTWI699YEaoi5xyLT50=";
|
||||
assertEquals(signature, service.getSignature(baseString, apiSecret, tokenSecret));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package org.scribe.test.helpers;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
public class ObjectMother
|
||||
{
|
||||
|
||||
public static OAuthRequest createSampleOAuthRequest()
|
||||
public static OAuthRequest createSampleOAuthRequest() throws MalformedURLException
|
||||
{
|
||||
OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com");
|
||||
request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
|
||||
@@ -14,4 +16,14 @@ public class ObjectMother
|
||||
request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
|
||||
return request;
|
||||
}
|
||||
|
||||
public static OAuthRequest createSampleOAuthRequest2() throws MalformedURLException
|
||||
{
|
||||
OAuthRequest request = new OAuthRequest(Verb.GET, "http://EXAMPLE.com");
|
||||
request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
|
||||
request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&");
|
||||
request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback");
|
||||
request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
|
||||
return request;
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,17 @@ public class PreconditionsTest
|
||||
Preconditions.checkValidUrl("https://www.example.com", ERROR_MSG);
|
||||
}
|
||||
|
||||
public void shouldAllowNonStandarProtocolsForAndroid()
|
||||
{
|
||||
Preconditions.checkValidUrl("x-url-custom://www.example.com", ERROR_MSG);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldNotAllowStrangeProtocolNames()
|
||||
{
|
||||
Preconditions.checkValidUrl("$weird*://www.example.com", ERROR_MSG);
|
||||
}
|
||||
|
||||
public void shouldAllowOutOfBandAsValidCallbackValue()
|
||||
{
|
||||
Preconditions.checkValidOAuthCallback("oob", ERROR_MSG);
|
||||
|
||||
@@ -8,13 +8,6 @@ import org.junit.*;
|
||||
|
||||
public class URLUtilsTest
|
||||
{
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPercentEncodeMap()
|
||||
{
|
||||
@@ -39,7 +32,7 @@ public class URLUtilsTest
|
||||
public void shouldPercentEncodeString()
|
||||
{
|
||||
String toEncode = "this is a test &^";
|
||||
String expected = "this+is+a+test+%26%5E";
|
||||
String expected = "this%20is%20a%20test%20%26%5E";
|
||||
assertEquals(expected, URLUtils.percentEncode(toEncode));
|
||||
}
|
||||
|
||||
@@ -48,7 +41,24 @@ public class URLUtilsTest
|
||||
{
|
||||
String toDecode = "this+is+a+test+%26%5E";
|
||||
String expected = "this is a test &^";
|
||||
assertEquals(expected, URLUtils.percentDecode(toDecode));
|
||||
assertEquals(expected, URLUtils.urlDecodeWrapper(toDecode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncodeAllSpecialCharacters()
|
||||
{
|
||||
String plain = "!*'();:@&=+$,/?#[]";
|
||||
String encoded = "%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D";
|
||||
assertEquals(encoded, URLUtils.percentEncode(plain));
|
||||
assertEquals(plain, URLUtils.urlDecodeWrapper(encoded));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotEncodeReservedCharacters()
|
||||
{
|
||||
String plain = "abcde123456-._~";
|
||||
String encoded = plain;
|
||||
assertEquals(encoded, URLUtils.percentEncode(plain));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -69,7 +79,69 @@ public class URLUtilsTest
|
||||
public void shouldThrowExceptionIfStringToDecodeIsNull()
|
||||
{
|
||||
String toDecode = null;
|
||||
URLUtils.percentDecode(toDecode);
|
||||
URLUtils.urlDecodeWrapper(toDecode);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionWhenAppendingNullMapToQuerystring()
|
||||
{
|
||||
String url = "http://www.example.com";
|
||||
Map<String, String> nullMap = null;
|
||||
URLUtils.appendParametersToQueryString(url, nullMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAppendNothingToQuerystringIfGivenEmptyMap()
|
||||
{
|
||||
String url = "http://www.example.com";
|
||||
Map<String, String> emptyMap = new HashMap<String, String>();
|
||||
String newUrl = URLUtils.appendParametersToQueryString(url, emptyMap);
|
||||
Assert.assertEquals(url, newUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAppendParametersToSimpleUrl()
|
||||
{
|
||||
String url = "http://www.example.com";
|
||||
String expectedUrl = "http://www.example.com?param1=value1¶m2=value+with+spaces";
|
||||
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("param1", "value1");
|
||||
params.put("param2", "value with spaces");
|
||||
|
||||
url = URLUtils.appendParametersToQueryString(url, params);
|
||||
Assert.assertEquals(url, expectedUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAppendParametersToUrlWithQuerystring()
|
||||
{
|
||||
String url = "http://www.example.com?already=present";
|
||||
String expectedUrl = "http://www.example.com?already=present¶m1=value1¶m2=value+with+spaces";
|
||||
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("param1", "value1");
|
||||
params.put("param2", "value with spaces");
|
||||
|
||||
url = URLUtils.appendParametersToQueryString(url, params);
|
||||
Assert.assertEquals(url, expectedUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncodePlusSymbol()
|
||||
{
|
||||
String plain = "7aEP+jNAwvjc0mjhqg0nuXPf";
|
||||
String encoded = "7aEP%2BjNAwvjc0mjhqg0nuXPf";
|
||||
|
||||
Assert.assertEquals(encoded, URLUtils.percentEncode(plain));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDecodePlusSymbol()
|
||||
{
|
||||
String encoded = "oauth_verifier=7aEP%2BjNAwvjc0mjhqg0nuXPf";
|
||||
String expected = "oauth_verifier=7aEP+jNAwvjc0mjhqg0nuXPf";
|
||||
|
||||
Assert.assertEquals(expected, URLUtils.urlDecodeWrapper(encoded));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user