Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
b2147de2e5 |
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.
|
||||||
@@ -48,6 +48,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.
|
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
|
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!
|
Check the "Getting Started":http://wiki.github.com/fernandezpablo85/scribe-java/getting-started page and start rocking!
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
[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
|
||||||
@@ -4,8 +4,38 @@
|
|||||||
<groupId>org.scribe</groupId>
|
<groupId>org.scribe</groupId>
|
||||||
<artifactId>scribe</artifactId>
|
<artifactId>scribe</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>1.0.1</version>
|
<version>1.0.7</version>
|
||||||
<name>OAuth Library</name>
|
<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>
|
||||||
|
</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>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -18,6 +48,7 @@
|
|||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.8.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -30,6 +61,19 @@
|
|||||||
<target>1.6</target>
|
<target>1.6</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</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>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
@@ -20,7 +20,11 @@ public class ServiceBuilder
|
|||||||
private String apiSecret;
|
private String apiSecret;
|
||||||
private String callback;
|
private String callback;
|
||||||
private Api api;
|
private Api api;
|
||||||
|
private String scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*/
|
||||||
public ServiceBuilder()
|
public ServiceBuilder()
|
||||||
{
|
{
|
||||||
this.callback = OAuthConstants.OUT_OF_BAND;
|
this.callback = OAuthConstants.OUT_OF_BAND;
|
||||||
@@ -92,6 +96,19 @@ public class ServiceBuilder
|
|||||||
return this;
|
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}
|
* Returns the fully configured {@link OAuthService}
|
||||||
*
|
*
|
||||||
@@ -102,6 +119,6 @@ public class ServiceBuilder
|
|||||||
Preconditions.checkNotNull(api, "You must specify a valid api through the provider() method");
|
Preconditions.checkNotNull(api, "You must specify a valid api through the provider() method");
|
||||||
Preconditions.checkEmptyString(apiKey, "You must provide an api key");
|
Preconditions.checkEmptyString(apiKey, "You must provide an api key");
|
||||||
Preconditions.checkEmptyString(apiSecret, "You must provide an api secret");
|
Preconditions.checkEmptyString(apiSecret, "You must provide an api secret");
|
||||||
return api.createService(apiKey, apiSecret, callback);
|
return api.createService(apiKey, apiSecret, callback, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,8 +16,9 @@ public interface Api
|
|||||||
* @param apiKey your application api key
|
* @param apiKey your application api key
|
||||||
* @param apiSecret your application api secret
|
* @param apiSecret your application api secret
|
||||||
* @param callback the callback url (or 'oob' for out of band OAuth)
|
* @param callback the callback url (or 'oob' for out of band OAuth)
|
||||||
|
* @param scope the OAuth scope
|
||||||
*
|
*
|
||||||
* @return fully configured {@link OAuthService}
|
* @return fully configured {@link OAuthService}
|
||||||
*/
|
*/
|
||||||
OAuthService createService(String apiKey, String apiSecret, String callback);
|
OAuthService createService(String apiKey, String apiSecret, String callback, String scope);
|
||||||
}
|
}
|
||||||
@@ -5,53 +5,89 @@ import org.scribe.model.*;
|
|||||||
import org.scribe.oauth.*;
|
import org.scribe.oauth.*;
|
||||||
import org.scribe.services.*;
|
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.
|
||||||
|
* If your Api adheres to the 1.0a protocol correctly, you just need to extend
|
||||||
|
* this class and define the getters for your endpoints.
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*
|
||||||
|
*/
|
||||||
public abstract class DefaultApi10a implements Api
|
public abstract class DefaultApi10a implements Api
|
||||||
{
|
{
|
||||||
public AccessTokenExtractor getAccessTokenExtractor()
|
|
||||||
|
protected AccessTokenExtractor getAccessTokenExtractor()
|
||||||
{
|
{
|
||||||
return new TokenExtractorImpl();
|
return new TokenExtractorImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseStringExtractor getBaseStringExtractor()
|
protected BaseStringExtractor getBaseStringExtractor()
|
||||||
{
|
{
|
||||||
return new BaseStringExtractorImpl();
|
return new BaseStringExtractorImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public HeaderExtractor getHeaderExtractor()
|
protected HeaderExtractor getHeaderExtractor()
|
||||||
{
|
{
|
||||||
return new HeaderExtractorImpl();
|
return new HeaderExtractorImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RequestTokenExtractor getRequestTokenExtractor()
|
protected RequestTokenExtractor getRequestTokenExtractor()
|
||||||
{
|
{
|
||||||
return new TokenExtractorImpl();
|
return new TokenExtractorImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignatureService getSignatureService()
|
protected SignatureService getSignatureService()
|
||||||
{
|
{
|
||||||
return new HMACSha1SignatureService();
|
return new HMACSha1SignatureService();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimestampService getTimestampService()
|
protected TimestampService getTimestampService()
|
||||||
{
|
{
|
||||||
return new TimestampServiceImpl();
|
return new TimestampServiceImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Verb getAccessTokenVerb()
|
protected Verb getAccessTokenVerb()
|
||||||
{
|
{
|
||||||
return Verb.POST;
|
return Verb.POST;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Verb getRequestTokenVerb()
|
protected Verb getRequestTokenVerb()
|
||||||
{
|
{
|
||||||
return Verb.POST;
|
return Verb.POST;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract String getRequestTokenEndpoint();
|
/**
|
||||||
public abstract String getAccessTokenEndpoint();
|
* Returns the URL that receives the request token requests.
|
||||||
|
*
|
||||||
|
* @return request token URL
|
||||||
|
*/
|
||||||
|
protected abstract String getRequestTokenEndpoint();
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public OAuthService createService(String apiKey, String apiSecret, String callback)
|
* Returns the URL that receives the access token requests.
|
||||||
|
*
|
||||||
|
* @return access token URL
|
||||||
|
*/
|
||||||
|
protected abstract String getAccessTokenEndpoint();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(String apiKey, String apiSecret, String callback, String scope)
|
||||||
|
{
|
||||||
|
OAuthService service = createService(apiKey, apiSecret, callback);
|
||||||
|
service.addScope(scope);
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OAuthService createService(String apiKey, String apiSecret, String callback)
|
||||||
{
|
{
|
||||||
return new OAuth10aServiceImpl( getSignatureService(),
|
return new OAuth10aServiceImpl( getSignatureService(),
|
||||||
getTimestampService(),
|
getTimestampService(),
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.scribe.builder.api;
|
||||||
|
|
||||||
|
public class EvernoteApi extends DefaultApi10a
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRequestTokenEndpoint()
|
||||||
|
{
|
||||||
|
return "https://www.evernote.com/oauth";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAccessTokenEndpoint()
|
||||||
|
{
|
||||||
|
return "https://www.evernote.com/oauth";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,13 +3,13 @@ package org.scribe.builder.api;
|
|||||||
public class FoursquareApi extends DefaultApi10a
|
public class FoursquareApi extends DefaultApi10a
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public String getAccessTokenEndpoint()
|
protected String getAccessTokenEndpoint()
|
||||||
{
|
{
|
||||||
return "http://foursquare.com/oauth/access_token";
|
return "http://foursquare.com/oauth/access_token";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRequestTokenEndpoint()
|
protected String getRequestTokenEndpoint()
|
||||||
{
|
{
|
||||||
return "http://foursquare.com/oauth/request_token";
|
return "http://foursquare.com/oauth/request_token";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package org.scribe.builder.api;
|
|||||||
public class GoogleApi extends DefaultApi10a
|
public class GoogleApi extends DefaultApi10a
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public String getAccessTokenEndpoint()
|
protected String getAccessTokenEndpoint()
|
||||||
{
|
|
||||||
return "https://www.google.com/accounts/OAuthGetRequestToken";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRequestTokenEndpoint()
|
|
||||||
{
|
{
|
||||||
return "https://www.google.com/accounts/OAuthGetAccessToken";
|
return "https://www.google.com/accounts/OAuthGetAccessToken";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getRequestTokenEndpoint()
|
||||||
|
{
|
||||||
|
return "https://www.google.com/accounts/OAuthGetRequestToken";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,19 +7,19 @@ public class LinkedInApi extends DefaultApi10a
|
|||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAccessTokenEndpoint()
|
protected String getAccessTokenEndpoint()
|
||||||
{
|
{
|
||||||
return "https://api.linkedin.com/uas/oauth/accessToken";
|
return "https://api.linkedin.com/uas/oauth/accessToken";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRequestTokenEndpoint()
|
protected String getRequestTokenEndpoint()
|
||||||
{
|
{
|
||||||
return "https://api.linkedin.com/uas/oauth/requestToken";
|
return "https://api.linkedin.com/uas/oauth/requestToken";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseStringExtractor getBaseStringExtractor()
|
protected BaseStringExtractor getBaseStringExtractor()
|
||||||
{
|
{
|
||||||
return new LinkedInBaseStringExtractorImpl();
|
return new LinkedInBaseStringExtractorImpl();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ package org.scribe.builder.api;
|
|||||||
public class TwitterApi extends DefaultApi10a
|
public class TwitterApi extends DefaultApi10a
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public String getAccessTokenEndpoint()
|
protected String getAccessTokenEndpoint()
|
||||||
{
|
{
|
||||||
return "http://twitter.com/oauth/access_token";
|
return "http://twitter.com/oauth/access_token";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRequestTokenEndpoint()
|
protected String getRequestTokenEndpoint()
|
||||||
{
|
{
|
||||||
return "http://twitter.com/oauth/request_token";
|
return "http://twitter.com/oauth/request_token";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.scribe.builder.api;
|
||||||
|
|
||||||
|
public class VimeoApi extends DefaultApi10a
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected String getAccessTokenEndpoint()
|
||||||
|
{
|
||||||
|
return "http://vimeo.com/oauth/access_token";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getRequestTokenEndpoint()
|
||||||
|
{
|
||||||
|
return "http://vimeo.com/oauth/request_token";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,13 +3,13 @@ package org.scribe.builder.api;
|
|||||||
public class YahooApi extends DefaultApi10a
|
public class YahooApi extends DefaultApi10a
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public String getAccessTokenEndpoint()
|
protected String getAccessTokenEndpoint()
|
||||||
{
|
{
|
||||||
return "https://api.login.yahoo.com/oauth/v2/get_token";
|
return "https://api.login.yahoo.com/oauth/v2/get_token";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRequestTokenEndpoint()
|
protected String getRequestTokenEndpoint()
|
||||||
{
|
{
|
||||||
return "https://api.login.yahoo.com/oauth/v2/get_request_token";
|
return "https://api.login.yahoo.com/oauth/v2/get_request_token";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.scribe.builder.api;
|
||||||
|
|
||||||
|
public class YammerApi extends DefaultApi10a
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRequestTokenEndpoint()
|
||||||
|
{
|
||||||
|
return "https://www.yammer.com/oauth/request_token";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAccessTokenEndpoint()
|
||||||
|
{
|
||||||
|
return "https://www.yammer.com/oauth/access_token";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,18 +1,33 @@
|
|||||||
package org.scribe.exceptions;
|
package org.scribe.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default scribe exception.
|
||||||
|
* Represents a problem in the OAuth signing process
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class OAuthException extends RuntimeException
|
public class OAuthException extends RuntimeException
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
* @param message message explaining what went wrong
|
||||||
|
* @param e original exception
|
||||||
|
*/
|
||||||
public OAuthException(String message, Exception e)
|
public OAuthException(String message, Exception e)
|
||||||
{
|
{
|
||||||
super(message, 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)
|
public OAuthException(String message)
|
||||||
{
|
{
|
||||||
super(message, null);
|
super(message, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,11 @@ package org.scribe.exceptions;
|
|||||||
|
|
||||||
import org.scribe.model.*;
|
import org.scribe.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialized exception that represents a missing OAuth parameter.
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class OAuthParametersMissingException extends OAuthException
|
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. "
|
private static final String MSG = "Could not find oauth parameters in request: %s. "
|
||||||
+ "OAuth parameters must be specified with the addOAuthParameter() method";
|
+ "OAuth parameters must be specified with the addOAuthParameter() method";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*
|
||||||
|
* @param request OAuthRequest that caused the error
|
||||||
|
*/
|
||||||
public OAuthParametersMissingException(OAuthRequest request)
|
public OAuthParametersMissingException(OAuthRequest request)
|
||||||
{
|
{
|
||||||
super(String.format(MSG, request));
|
super(String.format(MSG, request));
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
package org.scribe.exceptions;
|
package org.scribe.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialized exception that represents a problem in the signature
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class OAuthSignatureException extends OAuthException
|
public class OAuthSignatureException extends OAuthException
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 1L;
|
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)
|
public OAuthSignatureException(String stringToSign, Exception e)
|
||||||
{
|
{
|
||||||
super("Error while signing string: " + stringToSign, e);
|
super("Error while signing string: " + stringToSign, e);
|
||||||
|
|||||||
@@ -3,9 +3,17 @@ package org.scribe.extensions.linkedin;
|
|||||||
import org.scribe.extractors.*;
|
import org.scribe.extractors.*;
|
||||||
import org.scribe.model.*;
|
import org.scribe.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LinkedIn's specific extractor that does not encode the tilde character.
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class LinkedInBaseStringExtractorImpl extends BaseStringExtractorImpl
|
public class LinkedInBaseStringExtractorImpl extends BaseStringExtractorImpl
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String extract(OAuthRequest request)
|
public String extract(OAuthRequest request)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,18 @@ package org.scribe.extractors;
|
|||||||
|
|
||||||
import org.scribe.model.*;
|
import org.scribe.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple command object that extracts a {@link Token} from a String
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public interface AccessTokenExtractor
|
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);
|
public Token extract(String response);
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,20 @@ package org.scribe.extractors;
|
|||||||
|
|
||||||
import org.scribe.model.*;
|
import org.scribe.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple command object that extracts a base string from a {@link OAuthRequest}
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public interface BaseStringExtractor
|
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);
|
String extract(OAuthRequest request);
|
||||||
}
|
}
|
||||||
@@ -6,11 +6,20 @@ import org.scribe.exceptions.*;
|
|||||||
import org.scribe.model.*;
|
import org.scribe.model.*;
|
||||||
import org.scribe.utils.*;
|
import org.scribe.utils.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link BaseStringExtractor}. Conforms to OAuth 1.0a
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class BaseStringExtractorImpl implements BaseStringExtractor
|
public class BaseStringExtractorImpl implements BaseStringExtractor
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final String AMPERSAND_SEPARATED_STRING = "%s&%s&%s";
|
private static final String AMPERSAND_SEPARATED_STRING = "%s&%s&%s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String extract(OAuthRequest request)
|
public String extract(OAuthRequest request)
|
||||||
{
|
{
|
||||||
checkPreconditions(request);
|
checkPreconditions(request);
|
||||||
|
|||||||
@@ -2,7 +2,18 @@ package org.scribe.extractors;
|
|||||||
|
|
||||||
import org.scribe.model.*;
|
import org.scribe.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple command object that generates an OAuth Authorization header to include in the request.
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public interface HeaderExtractor
|
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);
|
String extract(OAuthRequest request);
|
||||||
}
|
}
|
||||||
@@ -6,22 +6,35 @@ import org.scribe.exceptions.*;
|
|||||||
import org.scribe.model.*;
|
import org.scribe.model.*;
|
||||||
import org.scribe.utils.*;
|
import org.scribe.utils.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link HeaderExtractor}. Conforms to OAuth 1.0a
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class HeaderExtractorImpl implements HeaderExtractor
|
public class HeaderExtractorImpl implements HeaderExtractor
|
||||||
{
|
{
|
||||||
|
private static final String PARAM_SEPARATOR = ", ";
|
||||||
private static final String PREAMBLE = "OAuth ";
|
private static final String PREAMBLE = "OAuth ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String extract(OAuthRequest request)
|
public String extract(OAuthRequest request)
|
||||||
{
|
{
|
||||||
checkPreconditions(request);
|
checkPreconditions(request);
|
||||||
Map<String, String> parameters = request.getOauthParameters();
|
Map<String, String> parameters = request.getOauthParameters();
|
||||||
StringBuffer header = new StringBuffer();
|
StringBuffer header = new StringBuffer(parameters.size() * 20);
|
||||||
header.append(PREAMBLE);
|
header.append(PREAMBLE);
|
||||||
for (String key : parameters.keySet())
|
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)
|
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.*;
|
import org.scribe.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple command object that extracts a {@link Token} from a String
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public interface RequestTokenExtractor
|
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);
|
public Token extract(String response);
|
||||||
}
|
}
|
||||||
@@ -6,11 +6,20 @@ import org.scribe.exceptions.*;
|
|||||||
import org.scribe.model.*;
|
import org.scribe.model.*;
|
||||||
import org.scribe.utils.*;
|
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
|
public class TokenExtractorImpl implements RequestTokenExtractor, AccessTokenExtractor
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final String TOKEN_REGEX = "oauth_token=(\\S*)&oauth_token_secret=(\\S*?)(&(.*))?";
|
private static final String TOKEN_REGEX = "oauth_token=(\\S*)&oauth_token_secret=(\\S*?)(&(.*))?";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public Token extract(String response)
|
public Token extract(String response)
|
||||||
{
|
{
|
||||||
Preconditions.checkEmptyString(response, "Cant extract a token from null object or an empty string.");
|
Preconditions.checkEmptyString(response, "Cant extract a token from null object or an empty string.");
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package org.scribe.model;
|
package org.scribe.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter object that groups OAuth config values
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class OAuthConfig
|
public class OAuthConfig
|
||||||
{
|
{
|
||||||
private String apiKey;
|
private String apiKey;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.scribe.model;
|
|||||||
* This class contains OAuth constants, used project-wide
|
* This class contains OAuth constants, used project-wide
|
||||||
*
|
*
|
||||||
* @author Pablo Fernandez
|
* @author Pablo Fernandez
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class OAuthConstants
|
public class OAuthConstants
|
||||||
{
|
{
|
||||||
@@ -38,4 +37,5 @@ public class OAuthConstants
|
|||||||
public static final String VERIFIER = "oauth_verifier";
|
public static final String VERIFIER = "oauth_verifier";
|
||||||
public static final String HEADER = "Authorization";
|
public static final String HEADER = "Authorization";
|
||||||
public static final Token EMPTY_TOKEN = new Token("", "");
|
public static final Token EMPTY_TOKEN = new Token("", "");
|
||||||
|
public static final String SCOPE = "scope";
|
||||||
}
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package org.scribe.model;
|
|
||||||
|
|
||||||
public class OAuthParams
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -2,18 +2,38 @@ package org.scribe.model;
|
|||||||
|
|
||||||
import java.util.*;
|
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
|
public class OAuthRequest extends Request
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final String OAUTH_PREFIX = "oauth_";
|
private static final String OAUTH_PREFIX = "oauth_";
|
||||||
private Map<String, String> oauthParameters;
|
private Map<String, String> oauthParameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*
|
||||||
|
* @param verb Http verb/method
|
||||||
|
* @param url resource URL
|
||||||
|
*/
|
||||||
public OAuthRequest(Verb verb, String url)
|
public OAuthRequest(Verb verb, String url)
|
||||||
{
|
{
|
||||||
super(verb, url);
|
super(verb, url);
|
||||||
this.oauthParameters = new HashMap<String, String>();
|
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)
|
public void addOAuthParameter(String key, String value)
|
||||||
{
|
{
|
||||||
oauthParameters.put(checkKey(key), value);
|
oauthParameters.put(checkKey(key), value);
|
||||||
@@ -21,15 +41,21 @@ public class OAuthRequest extends Request
|
|||||||
|
|
||||||
private String checkKey(String key)
|
private String checkKey(String key)
|
||||||
{
|
{
|
||||||
if (!key.startsWith(OAUTH_PREFIX))
|
if (key.startsWith(OAUTH_PREFIX) || key.equals(OAuthConstants.SCOPE))
|
||||||
{
|
|
||||||
throw new IllegalArgumentException(String.format("OAuth parameters must start with '%s'", OAUTH_PREFIX));
|
|
||||||
} else
|
|
||||||
{
|
{
|
||||||
return key;
|
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()
|
public Map<String, String> getOauthParameters()
|
||||||
{
|
{
|
||||||
return oauthParameters;
|
return oauthParameters;
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import org.scribe.utils.*;
|
|||||||
*/
|
*/
|
||||||
class Request
|
class Request
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final String CONTENT_LENGTH = "Content-Length";
|
private static final String CONTENT_LENGTH = "Content-Length";
|
||||||
|
|
||||||
private String url;
|
private String url;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import org.scribe.utils.*;
|
|||||||
*/
|
*/
|
||||||
public class Response
|
public class Response
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final String EMPTY = "";
|
private static final String EMPTY = "";
|
||||||
|
|
||||||
private int code;
|
private int code;
|
||||||
@@ -52,11 +51,6 @@ public class Response
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the code is in the successful or redirect range.
|
|
||||||
*
|
|
||||||
* @return true if successful
|
|
||||||
*/
|
|
||||||
private boolean wasSuccessful()
|
private boolean wasSuccessful()
|
||||||
{
|
{
|
||||||
return getCode() >= 200 && getCode() < 400;
|
return getCode() >= 200 && getCode() < 400;
|
||||||
|
|||||||
@@ -1,11 +1,21 @@
|
|||||||
package org.scribe.model;
|
package org.scribe.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an OAuth token (either request or access token) and its secret
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class Token
|
public class Token
|
||||||
{
|
{
|
||||||
|
|
||||||
private final String token;
|
private final String token;
|
||||||
private final String secret;
|
private final String secret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*
|
||||||
|
* @param token token value
|
||||||
|
* @param secret token secret
|
||||||
|
*/
|
||||||
public Token(String token, String secret)
|
public Token(String token, String secret)
|
||||||
{
|
{
|
||||||
this.token = token;
|
this.token = token;
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
package org.scribe.model;
|
package org.scribe.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an OAuth verifier code.
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class Verifier
|
public class Verifier
|
||||||
{
|
{
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*
|
||||||
|
* @param value verifier value
|
||||||
|
*/
|
||||||
public Verifier(String value)
|
public Verifier(String value)
|
||||||
{
|
{
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|||||||
@@ -4,9 +4,14 @@ import org.scribe.extractors.*;
|
|||||||
import org.scribe.model.*;
|
import org.scribe.model.*;
|
||||||
import org.scribe.services.*;
|
import org.scribe.services.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth 1.0a implementation of {@link OAuthService}
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class OAuth10aServiceImpl implements OAuthService
|
public class OAuth10aServiceImpl implements OAuthService
|
||||||
{
|
{
|
||||||
|
private static final String NO_SCOPE = null;
|
||||||
private static final String VERSION = "1.0";
|
private static final String VERSION = "1.0";
|
||||||
|
|
||||||
private OAuthConfig config;
|
private OAuthConfig config;
|
||||||
@@ -16,7 +21,19 @@ public class OAuth10aServiceImpl implements OAuthService
|
|||||||
private HeaderExtractor headerExtractor;
|
private HeaderExtractor headerExtractor;
|
||||||
private RequestTokenExtractor rtExtractor;
|
private RequestTokenExtractor rtExtractor;
|
||||||
private AccessTokenExtractor atExtractor;
|
private AccessTokenExtractor atExtractor;
|
||||||
|
private String scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*
|
||||||
|
* @param signatureService OAuth 1.0a signature service
|
||||||
|
* @param timestampService OAuth 1.0a timestamp service
|
||||||
|
* @param baseStringExtractor OAuth 1.0a base string extractor
|
||||||
|
* @param headerExtractor OAuth 1.0a http header extractor
|
||||||
|
* @param rtExtractor OAuth 1.0a request token extractor
|
||||||
|
* @param atExtractor OAuth 1.0a access token extractor
|
||||||
|
* @param config OAuth 1.0a configuration param object
|
||||||
|
*/
|
||||||
public OAuth10aServiceImpl(SignatureService signatureService, TimestampService timestampService, BaseStringExtractor baseStringExtractor,
|
public OAuth10aServiceImpl(SignatureService signatureService, TimestampService timestampService, BaseStringExtractor baseStringExtractor,
|
||||||
HeaderExtractor headerExtractor, RequestTokenExtractor rtExtractor, AccessTokenExtractor atExtractor, OAuthConfig config)
|
HeaderExtractor headerExtractor, RequestTokenExtractor rtExtractor, AccessTokenExtractor atExtractor, OAuthConfig config)
|
||||||
{
|
{
|
||||||
@@ -27,8 +44,12 @@ public class OAuth10aServiceImpl implements OAuthService
|
|||||||
this.rtExtractor = rtExtractor;
|
this.rtExtractor = rtExtractor;
|
||||||
this.atExtractor = atExtractor;
|
this.atExtractor = atExtractor;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.scope = NO_SCOPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public Token getRequestToken()
|
public Token getRequestToken()
|
||||||
{
|
{
|
||||||
OAuthRequest request = new OAuthRequest(config.getRequestTokenVerb(), config.getRequestTokenEndpoint());
|
OAuthRequest request = new OAuthRequest(config.getRequestTokenVerb(), config.getRequestTokenEndpoint());
|
||||||
@@ -46,9 +67,13 @@ public class OAuth10aServiceImpl implements OAuthService
|
|||||||
request.addOAuthParameter(OAuthConstants.SIGN_METHOD, signatureService.getSignatureMethod());
|
request.addOAuthParameter(OAuthConstants.SIGN_METHOD, signatureService.getSignatureMethod());
|
||||||
request.addOAuthParameter(OAuthConstants.VERSION, getVersion());
|
request.addOAuthParameter(OAuthConstants.VERSION, getVersion());
|
||||||
request.addOAuthParameter(OAuthConstants.CALLBACK, config.getCallback());
|
request.addOAuthParameter(OAuthConstants.CALLBACK, config.getCallback());
|
||||||
|
if(scope != NO_SCOPE) request.addOAuthParameter(OAuthConstants.SCOPE, scope);
|
||||||
request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, token));
|
request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, token));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public Token getAccessToken(Token requestToken, Verifier verifier)
|
public Token getAccessToken(Token requestToken, Verifier verifier)
|
||||||
{
|
{
|
||||||
OAuthRequest request = new OAuthRequest(config.getAccessTokenVerb(), config.getAccessTokenEndpoint());
|
OAuthRequest request = new OAuthRequest(config.getAccessTokenVerb(), config.getAccessTokenEndpoint());
|
||||||
@@ -60,6 +85,9 @@ public class OAuth10aServiceImpl implements OAuthService
|
|||||||
return atExtractor.extract(response.getBody());
|
return atExtractor.extract(response.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public void signRequest(Token token, OAuthRequest request)
|
public void signRequest(Token token, OAuthRequest request)
|
||||||
{
|
{
|
||||||
request.addOAuthParameter(OAuthConstants.TOKEN, token.getToken());
|
request.addOAuthParameter(OAuthConstants.TOKEN, token.getToken());
|
||||||
@@ -67,11 +95,22 @@ public class OAuth10aServiceImpl implements OAuthService
|
|||||||
addOAuthHeader(request);
|
addOAuthHeader(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String getVersion()
|
public String getVersion()
|
||||||
{
|
{
|
||||||
return VERSION;
|
return VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void addScope(String scope)
|
||||||
|
{
|
||||||
|
this.scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
private String getSignature(OAuthRequest request, Token token)
|
private String getSignature(OAuthRequest request, Token token)
|
||||||
{
|
{
|
||||||
String baseString = baseStringExtractor.extract(request);
|
String baseString = baseStringExtractor.extract(request);
|
||||||
|
|||||||
@@ -2,13 +2,50 @@ package org.scribe.oauth;
|
|||||||
|
|
||||||
import org.scribe.model.*;
|
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
|
public interface OAuthService
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Retrieve the request token.
|
||||||
|
*
|
||||||
|
* @return request token
|
||||||
|
*/
|
||||||
public Token getRequestToken();
|
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);
|
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);
|
public void signRequest(Token accessToken, OAuthRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the OAuth version of the service.
|
||||||
|
*
|
||||||
|
* @return oauth version as string
|
||||||
|
*/
|
||||||
public String getVersion();
|
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);
|
||||||
}
|
}
|
||||||
@@ -7,15 +7,23 @@ import org.apache.commons.codec.binary.*;
|
|||||||
import org.scribe.exceptions.*;
|
import org.scribe.exceptions.*;
|
||||||
import org.scribe.utils.*;
|
import org.scribe.utils.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HMAC-SHA1 implementation of {@SignatureService}
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class HMACSha1SignatureService implements SignatureService
|
public class HMACSha1SignatureService implements SignatureService
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final String EMPTY_STRING = "";
|
private static final String EMPTY_STRING = "";
|
||||||
private static final String CARRIAGE_RETURN = "\r\n";
|
private static final String CARRIAGE_RETURN = "\r\n";
|
||||||
private static final String UTF8 = "UTF-8";
|
private static final String UTF8 = "UTF-8";
|
||||||
private static final String HMAC_SHA1 = "HmacSHA1";
|
private static final String HMAC_SHA1 = "HmacSHA1";
|
||||||
private static final String METHOD = "HMAC-SHA1";
|
private static final String METHOD = "HMAC-SHA1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String getSignature(String baseString, String apiSecret, String tokenSecret)
|
public String getSignature(String baseString, String apiSecret, String tokenSecret)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -39,6 +47,9 @@ public class HMACSha1SignatureService implements SignatureService
|
|||||||
return new String(Base64.encodeBase64(bytes)).replace(CARRIAGE_RETURN, EMPTY_STRING);
|
return new String(Base64.encodeBase64(bytes)).replace(CARRIAGE_RETURN, EMPTY_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String getSignatureMethod()
|
public String getSignatureMethod()
|
||||||
{
|
{
|
||||||
return METHOD;
|
return METHOD;
|
||||||
|
|||||||
@@ -1,8 +1,28 @@
|
|||||||
package org.scribe.services;
|
package org.scribe.services;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs a base string, returning the OAuth signature
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*
|
||||||
|
*/
|
||||||
public interface SignatureService
|
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);
|
public String getSignature(String baseString, String apiSecret, String tokenSecret);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the signature method/algorithm
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public String getSignatureMethod();
|
public String getSignatureMethod();
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,25 @@
|
|||||||
package org.scribe.services;
|
package org.scribe.services;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unix epoch timestamp generator.
|
||||||
|
*
|
||||||
|
* This class is useful for stubbing in tests.
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public interface TimestampService
|
public interface TimestampService
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Returns the unix epoch timestamp in seconds
|
||||||
|
*
|
||||||
|
* @return timestamp
|
||||||
|
*/
|
||||||
public String getTimestampInSeconds();
|
public String getTimestampInSeconds();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a nonce (unique value for each request)
|
||||||
|
*
|
||||||
|
* @return nonce
|
||||||
|
*/
|
||||||
public String getNonce();
|
public String getNonce();
|
||||||
}
|
}
|
||||||
@@ -2,22 +2,35 @@ package org.scribe.services;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link TimestampService} using plain java classes.
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class TimestampServiceImpl implements TimestampService
|
public class TimestampServiceImpl implements TimestampService
|
||||||
{
|
{
|
||||||
|
|
||||||
private Timer timer;
|
private Timer timer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
public TimestampServiceImpl()
|
public TimestampServiceImpl()
|
||||||
{
|
{
|
||||||
timer = new Timer();
|
timer = new Timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String getNonce()
|
public String getNonce()
|
||||||
{
|
{
|
||||||
Long ts = getTs();
|
Long ts = getTs();
|
||||||
return String.valueOf(ts + timer.getRandomInteger());
|
return String.valueOf(ts + timer.getRandomInteger());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public String getTimestampInSeconds()
|
public String getTimestampInSeconds()
|
||||||
{
|
{
|
||||||
return String.valueOf(getTs());
|
return String.valueOf(getTs());
|
||||||
@@ -33,14 +46,19 @@ public class TimestampServiceImpl implements TimestampService
|
|||||||
this.timer = timer;
|
this.timer = timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inner class that uses {@link System} for generating the timestamps.
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
static class Timer
|
static class Timer
|
||||||
{
|
{
|
||||||
public Long getMilis()
|
Long getMilis()
|
||||||
{
|
{
|
||||||
return System.currentTimeMillis();
|
return System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getRandomInteger()
|
Integer getRandomInteger()
|
||||||
{
|
{
|
||||||
return new Random().nextInt();
|
return new Random().nextInt();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,19 @@ package org.scribe.utils;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utils for {@link Map} manipulation
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class MapUtils
|
public class MapUtils
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Sorts a Map
|
||||||
|
*
|
||||||
|
* @param map unsorted map
|
||||||
|
* @return sorted map
|
||||||
|
*/
|
||||||
public static final Map<String, String> sort(Map<String, String> map)
|
public static final Map<String, String> sort(Map<String, String> map)
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull(map, "Cannot sort a null object.");
|
Preconditions.checkNotNull(map, "Cannot sort a null object.");
|
||||||
|
|||||||
@@ -1,27 +1,63 @@
|
|||||||
package org.scribe.utils;
|
package org.scribe.utils;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.scribe.model.OAuthConstants;
|
import org.scribe.model.OAuthConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utils for checking preconditions and invariants
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class Preconditions
|
public class Preconditions
|
||||||
{
|
{
|
||||||
private static final String DEFAULT_MESSAGE = "Received an invalid parameter";
|
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)
|
public static void checkNotNull(Object object, String errorMsg)
|
||||||
{
|
{
|
||||||
check(object != null, 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)
|
public static void checkEmptyString(String string, String errorMsg)
|
||||||
{
|
{
|
||||||
check(string != null && !string.trim().equals(""), 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)
|
public static void checkValidUrl(String url, String errorMsg)
|
||||||
{
|
{
|
||||||
checkEmptyString(url, errorMsg);
|
checkEmptyString(url, errorMsg);
|
||||||
check(isUrl(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)
|
public static void checkValidOAuthCallback(String url, String errorMsg)
|
||||||
{
|
{
|
||||||
checkEmptyString(url, errorMsg);
|
checkEmptyString(url, errorMsg);
|
||||||
@@ -31,14 +67,14 @@ 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)
|
private static void check(boolean requirements, String error)
|
||||||
{
|
{
|
||||||
String message = (error == null || error.trim().isEmpty()) ? DEFAULT_MESSAGE : error;
|
String message = (error == null || error.trim().length() <= 0) ? DEFAULT_MESSAGE : error;
|
||||||
if (!requirements)
|
if (!requirements)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException(message);
|
throw new IllegalArgumentException(message);
|
||||||
|
|||||||
@@ -2,9 +2,19 @@ package org.scribe.utils;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utils to deal with Streams.
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class StreamUtils
|
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)
|
public static String getStreamContents(InputStream is)
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull(is, "Cannot get String from a null object");
|
Preconditions.checkNotNull(is, "Cannot get String from a null object");
|
||||||
|
|||||||
@@ -6,9 +6,13 @@ import java.util.*;
|
|||||||
|
|
||||||
import org.scribe.exceptions.*;
|
import org.scribe.exceptions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utils to deal with URL and url-encodings
|
||||||
|
*
|
||||||
|
* @author Pablo Fernandez
|
||||||
|
*/
|
||||||
public class URLUtils
|
public class URLUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final String EMPTY_STRING = "";
|
private static final String EMPTY_STRING = "";
|
||||||
private static final String UTF_8 = "UTF-8";
|
private static final String UTF_8 = "UTF-8";
|
||||||
private static final char PAIR_SEPARATOR = '=';
|
private static final char PAIR_SEPARATOR = '=';
|
||||||
@@ -16,6 +20,12 @@ public class URLUtils
|
|||||||
|
|
||||||
private static final String ERROR_MSG = String.format("Cannot find specified encoding: %s", UTF_8);
|
private static final String ERROR_MSG = String.format("Cannot find specified encoding: %s", UTF_8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns a map into a form-url-encoded string (key=value&key2=value2)
|
||||||
|
*
|
||||||
|
* @param map any map
|
||||||
|
* @return form-url-encoded string
|
||||||
|
*/
|
||||||
public static String formURLEncodeMap(Map<String, String> map)
|
public static String formURLEncodeMap(Map<String, String> map)
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull(map, "Cannot url-encode a null object");
|
Preconditions.checkNotNull(map, "Cannot url-encode a null object");
|
||||||
@@ -24,31 +34,43 @@ public class URLUtils
|
|||||||
|
|
||||||
private static String doFormUrlEncode(Map<String, String> map)
|
private static String doFormUrlEncode(Map<String, String> map)
|
||||||
{
|
{
|
||||||
StringBuffer encodedString = new StringBuffer();
|
StringBuffer encodedString = new StringBuffer(map.size() * 20);
|
||||||
for (String key : map.keySet())
|
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(percentEncode(key)).append(PAIR_SEPARATOR).append(percentEncode(map.get(key)));
|
||||||
}
|
}
|
||||||
return removeTrailingSeparator(encodedString);
|
return encodedString.toString();
|
||||||
}
|
|
||||||
|
|
||||||
private static String removeTrailingSeparator(StringBuffer buffer)
|
|
||||||
{
|
|
||||||
return buffer.toString().substring(0, buffer.length() - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Percent encodes a string
|
||||||
|
*
|
||||||
|
* @param plain
|
||||||
|
* @return percent encoded string
|
||||||
|
*/
|
||||||
public static String percentEncode(String string)
|
public static String percentEncode(String string)
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull(string, "Cannot encode null string");
|
Preconditions.checkNotNull(string, "Cannot encode null string");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return URLEncoder.encode(string, UTF_8);
|
return URLEncoder.encode(string, UTF_8).replaceAll("\\+", "%20");
|
||||||
} catch (UnsupportedEncodingException uee)
|
}
|
||||||
|
catch (UnsupportedEncodingException uee)
|
||||||
{
|
{
|
||||||
throw new OAuthException(ERROR_MSG, uee);
|
throw new OAuthException(ERROR_MSG, uee);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Percent decodes a string
|
||||||
|
*
|
||||||
|
* @param string percent encoded string
|
||||||
|
* @return plain string
|
||||||
|
*/
|
||||||
public static String percentDecode(String string)
|
public static String percentDecode(String string)
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull(string, "Cannot decode null string");
|
Preconditions.checkNotNull(string, "Cannot decode null string");
|
||||||
|
|||||||
@@ -41,4 +41,12 @@ public class BaseStringExtractorTest
|
|||||||
OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com");
|
OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com");
|
||||||
extractor.extract(request);
|
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*%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
|
||||||
|
request.addBodyParameter("body", "this param has whitespace");
|
||||||
|
assertEquals(expected, extractor.extract(request));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ public class RequestTest
|
|||||||
postRequest.addBodyParameter("param", "value");
|
postRequest.addBodyParameter("param", "value");
|
||||||
postRequest.addBodyParameter("param two", "value with spaces");
|
postRequest.addBodyParameter("param two", "value with spaces");
|
||||||
postRequest.send();
|
postRequest.send();
|
||||||
assertEquals("param+two=value+with+spaces¶m=value", postRequest.getBodyContents());
|
assertEquals("param%20two=value%20with%20spaces¶m=value", postRequest.getBodyContents());
|
||||||
assertTrue(connection.getHeaders().containsKey("Content-Length"));
|
assertTrue(connection.getHeaders().containsKey("Content-Length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,17 @@ public class PreconditionsTest
|
|||||||
Preconditions.checkValidUrl("https://www.example.com", ERROR_MSG);
|
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()
|
public void shouldAllowOutOfBandAsValidCallbackValue()
|
||||||
{
|
{
|
||||||
Preconditions.checkValidOAuthCallback("oob", ERROR_MSG);
|
Preconditions.checkValidOAuthCallback("oob", ERROR_MSG);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class URLUtilsTest
|
|||||||
params.put("key with spaces", "value with spaces");
|
params.put("key with spaces", "value with spaces");
|
||||||
params.put("&symbols!", "#!");
|
params.put("&symbols!", "#!");
|
||||||
|
|
||||||
String expected = "key=value&key+with+spaces=value+with+spaces&%26symbols%21=%23%21";
|
String expected = "key=value&key%20with%20spaces=value%20with%20spaces&%26symbols%21=%23%21";
|
||||||
assertEquals(expected, URLUtils.formURLEncodeMap(params));
|
assertEquals(expected, URLUtils.formURLEncodeMap(params));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ public class URLUtilsTest
|
|||||||
public void shouldPercentEncodeString()
|
public void shouldPercentEncodeString()
|
||||||
{
|
{
|
||||||
String toEncode = "this is a test &^";
|
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));
|
assertEquals(expected, URLUtils.percentEncode(toEncode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user