Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a63f935d2 | ||
|
|
61c0b4cc9f | ||
|
|
3f366589ea | ||
|
|
83b62f6079 | ||
|
|
b380b3af3d | ||
|
|
ce531cdc38 | ||
|
|
56561acdac | ||
|
|
05988a63cd | ||
|
|
611c6464f2 | ||
|
|
7fba153218 | ||
|
|
9070edd20a | ||
|
|
78fd342d92 | ||
|
|
7510111d28 | ||
|
|
852368e0a7 | ||
|
|
dbf00c9227 | ||
|
|
ce139bb28b | ||
|
|
40c8a27bb0 | ||
|
|
ae3a1b11c9 | ||
|
|
24babbae02 | ||
|
|
9f4569fbbc | ||
|
|
7e7d3ff7e0 | ||
|
|
dcd13835ba | ||
|
|
daf45d7078 | ||
|
|
8a7336b7d4 | ||
|
|
207df8a3d4 | ||
|
|
4f8315f7f7 | ||
|
|
e719c73d92 | ||
|
|
c6bff31353 | ||
|
|
27b1fc390b | ||
|
|
b917140078 | ||
|
|
9cdebd1ca6 | ||
|
|
2238c2da51 | ||
|
|
bf9a4bac68 | ||
|
|
0390ae7eb7 |
No files matched your search
@@ -5,6 +5,11 @@
|
||||
.project
|
||||
.settings
|
||||
|
||||
# IntelliJ Idea settings
|
||||
|
||||
.idea
|
||||
scribe.iml
|
||||
|
||||
# Binaries
|
||||
|
||||
target
|
||||
+9
-1
@@ -38,6 +38,8 @@ h3. Supports all major 1.0a and 2.0 OAuth APIs out-of-the-box
|
||||
|
||||
* Yammer
|
||||
|
||||
* Windows Live
|
||||
|
||||
* 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
|
||||
@@ -61,7 +63,7 @@ You can pull scribe from a maven repository, just add this to your __pom.xml__ f
|
||||
@<dependency>@
|
||||
@<groupId>org.scribe</groupId>@
|
||||
@<artifactId>scribe</artifactId>@
|
||||
@<version>1.2.1</version>@
|
||||
@<version>1.3.0</version>@
|
||||
@</dependency>@
|
||||
|
||||
h1. Getting started in less than 2 minutes
|
||||
@@ -70,6 +72,12 @@ Check the "Getting Started":http://wiki.github.com/fernandezpablo85/scribe-java/
|
||||
|
||||
h1. Please Read the "FAQ":http://wiki.github.com/fernandezpablo85/scribe-java/faq before creating an issue :)
|
||||
|
||||
h1. Questions?
|
||||
|
||||
Feel free to drop me an email, but there's already a "StackOvferflow":http://stackoverflow.com tag for "scribe":http://stackoverflow.com/questions/tagged/scribe you should use. I'm subscribed to it so I'll pick the question immediately.
|
||||
|
||||
Note that it really helps to run scribe on **debug** mode (since 1.3.0), to get additional info. To do this simply call the @.debug()@ method on the @ServiceBuilder@.
|
||||
|
||||
h1. About me
|
||||
|
||||
"LinkedIn profile":http://www.linkedin.com/in/fernandezpablo85
|
||||
|
||||
@@ -56,3 +56,18 @@
|
||||
* FEATURE: Added support for Vkontakte (thanks dotbg)
|
||||
* FEATURE: Added Sohu Weibo, Netease Weibo & Sina Weibo Apis (thanks Arthur Wang)
|
||||
* FEATURE: Added support for persistent Http Connections (thanks Craig Minton)
|
||||
|
||||
[1.2.2]
|
||||
* FIX: Added support for JDK 1.5. Issue #146 (thanks Sripathi Krishnan)
|
||||
* FIX: Invalid character constant error message. Issue #137 (thanks Scott Scoble)
|
||||
* FEATURE: Added a Api class to handle windows live authentication. Issue #135 (thanks Tomas Lin)
|
||||
* FEATURE: Added refresh token feature for Yahoo! API. Issue #134 (thanks Aaron Foltz)
|
||||
* FEATURE: Added support for Plurk API. Issue #130 (thanks Chia-Wei Li)
|
||||
* FIX: Request.setConnectTimeout() and setReadTimeout() throw NPE. Issue #123 (thanks thepizzle)
|
||||
|
||||
[1.2.3]
|
||||
* FEATURE: Added default Content-Type header
|
||||
* FEATURE: Sapo Api
|
||||
* FEATURE: Plurk Mobile Api
|
||||
* FEATURE: Kaixin and QWeibo Apis
|
||||
* FEATURE: SimpleGeo Api
|
||||
@@ -4,7 +4,7 @@
|
||||
<groupId>org.scribe</groupId>
|
||||
<artifactId>scribe</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.2.1</version>
|
||||
<version>1.3.0</version>
|
||||
<name>Scribe OAuth Library</name>
|
||||
<description>The best OAuth library out there</description>
|
||||
<url>http://github.com/fernandezpablo85/scribe-java</url>
|
||||
@@ -63,8 +63,8 @@
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.scribe.builder;
|
||||
|
||||
import java.io.*;
|
||||
import org.scribe.builder.api.*;
|
||||
import org.scribe.exceptions.*;
|
||||
import org.scribe.model.*;
|
||||
@@ -21,6 +22,7 @@ public class ServiceBuilder
|
||||
private Api api;
|
||||
private String scope;
|
||||
private SignatureType signatureType;
|
||||
private OutputStream debugStream;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
@@ -28,6 +30,8 @@ public class ServiceBuilder
|
||||
public ServiceBuilder()
|
||||
{
|
||||
this.callback = OAuthConstants.OUT_OF_BAND;
|
||||
this.signatureType = SignatureType.Header;
|
||||
this.debugStream = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,6 +140,19 @@ public class ServiceBuilder
|
||||
this.signatureType = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServiceBuilder debugStream(OutputStream stream)
|
||||
{
|
||||
Preconditions.checkNotNull(stream, "debug stream can't be null");
|
||||
this.debugStream = stream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServiceBuilder debug()
|
||||
{
|
||||
this.debugStream(System.out);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully configured {@link OAuthService}
|
||||
@@ -147,6 +164,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(new OAuthConfig(apiKey, apiSecret, callback, signatureType, scope));
|
||||
return api.createService(new OAuthConfig(apiKey, apiSecret, callback, signatureType, scope, debugStream));
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package org.scribe.builder.api;
|
||||
import org.scribe.model.*;
|
||||
|
||||
import org.scribe.utils.*;
|
||||
import static org.scribe.utils.URLUtils.*;
|
||||
|
||||
public class FacebookApi extends DefaultApi20
|
||||
{
|
||||
@@ -24,11 +23,11 @@ public class FacebookApi extends DefaultApi20
|
||||
// Append scope if present
|
||||
if(config.hasScope())
|
||||
{
|
||||
return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), formURLEncode(config.getCallback()), formURLEncode(config.getScope()));
|
||||
return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return String.format(AUTHORIZE_URL, config.getApiKey(), formURLEncode(config.getCallback()));
|
||||
return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public class Foursquare2Api extends DefaultApi20
|
||||
public String getAuthorizationUrl(OAuthConfig config)
|
||||
{
|
||||
Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Foursquare2 does not support OOB");
|
||||
return String.format(AUTHORIZATION_URL, config.getApiKey(), URLUtils.formURLEncode(config.getCallback()));
|
||||
return String.format(AUTHORIZATION_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
public class KaixinApi extends DefaultApi10a
|
||||
{
|
||||
private static final String REQUEST_TOKEN_URL = "http://api.kaixin001.com/oauth/request_token";
|
||||
private static final String ACCESS_TOKEN_URL = "http://api.kaixin001.com/oauth/access_token";
|
||||
private static final String AUTHORIZE_URL = "http://api.kaixin001.com/oauth/authorize?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return REQUEST_TOKEN_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return ACCESS_TOKEN_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZE_URL, requestToken.getToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Verb getRequestTokenVerb()
|
||||
{
|
||||
return Verb.GET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Verb getAccessTokenVerb()
|
||||
{
|
||||
return Verb.GET;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,9 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.extractors.*;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
import org.scribe.utils.*;
|
||||
|
||||
import static org.scribe.utils.URLUtils.*;
|
||||
|
||||
public class LiveApi extends DefaultApi20
|
||||
{
|
||||
|
||||
@@ -28,10 +24,11 @@ public class LiveApi extends DefaultApi20
|
||||
// Append scope if present
|
||||
if (config.hasScope())
|
||||
{
|
||||
return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), formURLEncode(config.getCallback()), formURLEncode(config.getScope()));
|
||||
} else
|
||||
return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return String.format(AUTHORIZE_URL, config.getApiKey(), formURLEncode(config.getCallback()));
|
||||
return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.scribe.model.Token;
|
||||
public class PlurkApi extends DefaultApi10a
|
||||
{
|
||||
private static final String REQUEST_TOKEN_URL = "http://www.plurk.com/OAuth/request_token";
|
||||
private static final String AUTHORIZE_URL = "http://www.plurk.com/OAuth/authorize?oauth_token=%s";
|
||||
private static final String AUTHORIZATION_URL = "http://www.plurk.com/OAuth/authorize?oauth_token=%s";
|
||||
private static final String ACCESS_TOKEN_URL = "http://www.plurk.com/OAuth/access_token";
|
||||
|
||||
@Override
|
||||
@@ -17,7 +17,7 @@ public class PlurkApi extends DefaultApi10a
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZE_URL, requestToken.getToken());
|
||||
return String.format(AUTHORIZATION_URL, requestToken.getToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -25,4 +25,15 @@ public class PlurkApi extends DefaultApi10a
|
||||
{
|
||||
return ACCESS_TOKEN_URL;
|
||||
}
|
||||
|
||||
public class Mobile extends PlurkApi
|
||||
{
|
||||
private static final String AUTHORIZATION_URL = "http://www.plurk.com/m/authorize?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZATION_URL, requestToken.getToken());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
public class QWeiboApi extends DefaultApi10a
|
||||
{
|
||||
private static final String REQUEST_TOKEN_URL = "https://open.t.qq.com/cgi-bin/request_token";
|
||||
private static final String ACCESS_TOKEN_URL = "https://open.t.qq.com/cgi-bin/access_token";
|
||||
private static final String AUTHORIZE_URL = "https://open.t.qq.com/cgi-bin/authorize?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return REQUEST_TOKEN_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return ACCESS_TOKEN_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZE_URL, requestToken.getToken());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.*;
|
||||
|
||||
public class SapoApi extends DefaultApi10a
|
||||
{
|
||||
private static final String AUTHORIZE_URL = "https://id.sapo.pt/oauth/authorize?oauth_token=%s";
|
||||
private static final String ACCESS_URL = "https://id.sapo.pt/oauth/access_token";
|
||||
private static final String REQUEST_URL = "https://id.sapo.pt/oauth/request_token";
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return ACCESS_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return REQUEST_URL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHORIZE_URL, requestToken.getToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Verb getRequestTokenVerb()
|
||||
{
|
||||
return Verb.GET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Verb getAccessTokenVerb()
|
||||
{
|
||||
return Verb.GET;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.model.Token;
|
||||
|
||||
/**
|
||||
* @author: Pablo Fernandez
|
||||
*/
|
||||
public class SimpleGeoApi extends DefaultApi10a
|
||||
{
|
||||
private static final String ENDPOINT = "these are not used since SimpleGeo uses 2 legged OAuth";
|
||||
|
||||
@Override
|
||||
public String getRequestTokenEndpoint()
|
||||
{
|
||||
return ENDPOINT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return ENDPOINT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return ENDPOINT;
|
||||
}
|
||||
}
|
||||
@@ -40,4 +40,27 @@ public class TwitterApi extends DefaultApi10a
|
||||
return "https://" + REQUEST_TOKEN_RESOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Twitter 'friendlier' authorization endpoint for OAuth.
|
||||
*
|
||||
* Uses SSL.
|
||||
*/
|
||||
public static class Authenticate extends SSL
|
||||
{
|
||||
private static final String AUTHENTICATE_URL = "https://api.twitter.com/oauth/authenticate?oauth_token=%s";
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(Token requestToken)
|
||||
{
|
||||
return String.format(AUTHENTICATE_URL, requestToken.getToken());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Just an alias to the default (SSL) authorization endpoint.
|
||||
*
|
||||
* Need to include this for symmetry with 'Authenticate' only.
|
||||
*/
|
||||
public static class Authorize extends SSL{}
|
||||
}
|
||||
@@ -25,11 +25,11 @@ public class VkontakteApi extends DefaultApi20
|
||||
Preconditions.checkValidUrl(config.getCallback(), "Valid url is required for a callback. Vkontakte does not support OOB");
|
||||
if(config.hasScope())// Appending scope if present
|
||||
{
|
||||
return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), URLUtils.formURLEncode(config.getCallback()),URLUtils.formURLEncode(config.getScope()));
|
||||
return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return String.format(AUTHORIZE_URL, config.getApiKey(), URLUtils.formURLEncode(config.getCallback()));
|
||||
return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.scribe.extractors;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.scribe.exceptions.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.utils.*;
|
||||
@@ -23,20 +21,19 @@ public class BaseStringExtractorImpl implements BaseStringExtractor
|
||||
public String extract(OAuthRequest request)
|
||||
{
|
||||
checkPreconditions(request);
|
||||
String verb = URLUtils.percentEncode(request.getVerb().name());
|
||||
String url = URLUtils.percentEncode(request.getSanitizedUrl());
|
||||
String verb = OAuthEncoder.encode(request.getVerb().name());
|
||||
String url = OAuthEncoder.encode(request.getSanitizedUrl());
|
||||
String params = getSortedAndEncodedParams(request);
|
||||
return String.format(AMPERSAND_SEPARATED_STRING, verb, url, params);
|
||||
}
|
||||
|
||||
private String getSortedAndEncodedParams(OAuthRequest request)
|
||||
{
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
MapUtils.decodeAndAppendEntries(request.getQueryStringParams(), params);
|
||||
MapUtils.decodeAndAppendEntries(request.getBodyParams(), params);
|
||||
MapUtils.decodeAndAppendEntries(request.getOauthParameters(), params);
|
||||
params = MapUtils.sort(params);
|
||||
return URLUtils.percentEncode(URLUtils.concatSortedPercentEncodedParams(params));
|
||||
ParameterList params = new ParameterList();
|
||||
params.addAll(request.getQueryStringParams());
|
||||
params.addAll(request.getBodyParams());
|
||||
params.addAll(new ParameterList(request.getOauthParameters()));
|
||||
return params.sort().asOauthBaseString();
|
||||
}
|
||||
|
||||
private void checkPreconditions(OAuthRequest request)
|
||||
|
||||
@@ -32,7 +32,7 @@ public class HeaderExtractorImpl implements HeaderExtractor
|
||||
{
|
||||
header.append(PARAM_SEPARATOR);
|
||||
}
|
||||
header.append(String.format("%s=\"%s\"", key, URLUtils.percentEncode(parameters.get(key))));
|
||||
header.append(String.format("%s=\"%s\"", key, OAuthEncoder.encode(parameters.get(key))));
|
||||
}
|
||||
return header.toString();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.scribe.utils.*;
|
||||
|
||||
public class JsonTokenExtractor implements AccessTokenExtractor
|
||||
{
|
||||
private Pattern accessTokenPattern = Pattern.compile("\"access_token\":\"(\\S*?)\"");
|
||||
private Pattern accessTokenPattern = Pattern.compile("\"access_token\":\\s*\"(\\S*?)\"");
|
||||
|
||||
@Override
|
||||
public Token extract(String response)
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.scribe.utils.*;
|
||||
*/
|
||||
public class TokenExtractor20Impl implements AccessTokenExtractor
|
||||
{
|
||||
private static final String TOKEN_REGEX = "access_token=(\\S*?)(&(\\S*))?";
|
||||
private static final String TOKEN_REGEX = "access_token=([^&]+)";
|
||||
private static final String EMPTY_SECRET = "";
|
||||
|
||||
/**
|
||||
@@ -23,9 +23,9 @@ public class TokenExtractor20Impl implements AccessTokenExtractor
|
||||
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())
|
||||
if (matcher.find())
|
||||
{
|
||||
String token = URLUtils.formURLDecode(matcher.group(1));
|
||||
String token = OAuthEncoder.decode(matcher.group(1));
|
||||
return new Token(token, EMPTY_SECRET, response);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -34,7 +34,7 @@ public class TokenExtractorImpl implements RequestTokenExtractor, AccessTokenExt
|
||||
Matcher matcher = p.matcher(response);
|
||||
if (matcher.find() && matcher.groupCount() >= 1)
|
||||
{
|
||||
return URLUtils.formURLDecode(matcher.group(1));
|
||||
return OAuthEncoder.decode(matcher.group(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.scribe.model;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Parameter object that groups OAuth config values
|
||||
*
|
||||
@@ -12,19 +14,21 @@ public class OAuthConfig
|
||||
private final String callback;
|
||||
private final SignatureType signatureType;
|
||||
private final String scope;
|
||||
private final OutputStream debugStream;
|
||||
|
||||
public OAuthConfig(String key, String secret)
|
||||
{
|
||||
this(key, secret, null, null, null);
|
||||
this(key, secret, null, null, null, null);
|
||||
}
|
||||
|
||||
public OAuthConfig(String key, String secret, String callback, SignatureType type, String scope)
|
||||
public OAuthConfig(String key, String secret, String callback, SignatureType type, String scope, OutputStream stream)
|
||||
{
|
||||
this.apiKey = key;
|
||||
this.apiSecret = secret;
|
||||
this.callback = callback != null ? callback : OAuthConstants.OUT_OF_BAND;
|
||||
this.signatureType = (type != null) ? type : SignatureType.Header;
|
||||
this.callback = callback;
|
||||
this.signatureType = type;
|
||||
this.scope = scope;
|
||||
this.debugStream = stream;
|
||||
}
|
||||
|
||||
public String getApiKey()
|
||||
@@ -56,4 +60,20 @@ public class OAuthConfig
|
||||
{
|
||||
return scope != null;
|
||||
}
|
||||
}
|
||||
|
||||
public void log(String message)
|
||||
{
|
||||
if (debugStream != null)
|
||||
{
|
||||
message = message + "\n";
|
||||
try
|
||||
{
|
||||
debugStream.write(message.getBytes("UTF8"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.scribe.model;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import org.scribe.exceptions.OAuthException;
|
||||
import org.scribe.utils.OAuthEncoder;
|
||||
|
||||
/**
|
||||
* @author: Pablo Fernandez
|
||||
*/
|
||||
public class Parameter implements Comparable<Parameter>
|
||||
{
|
||||
private static final String UTF = "UTF8";
|
||||
|
||||
private final String key;
|
||||
private final String value;
|
||||
|
||||
public Parameter(String key, String value)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String asUrlEncodedPair()
|
||||
{
|
||||
return OAuthEncoder.encode(key).concat("=").concat(OAuthEncoder.encode(value));
|
||||
}
|
||||
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
if(other == null) return false;
|
||||
if(other == this) return true;
|
||||
if(!(other instanceof Parameter)) return false;
|
||||
|
||||
Parameter otherParam = (Parameter) other;
|
||||
return otherParam.key.equals(key) && otherParam.value.equals(value);
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return key.hashCode() + value.hashCode();
|
||||
}
|
||||
|
||||
public int compareTo(Parameter parameter)
|
||||
{
|
||||
int keyDiff = key.compareTo(parameter.key);
|
||||
|
||||
return keyDiff != 0 ? keyDiff : value.compareTo(parameter.value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package org.scribe.model;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.scribe.utils.OAuthEncoder;
|
||||
import org.scribe.utils.Preconditions;
|
||||
|
||||
/**
|
||||
* @author: Pablo Fernandez
|
||||
*/
|
||||
public class ParameterList
|
||||
{
|
||||
private static final char QUERY_STRING_SEPARATOR = '?';
|
||||
private static final String PARAM_SEPARATOR = "&";
|
||||
private static final String PAIR_SEPARATOR = "=";
|
||||
private static final String EMPTY_STRING = "";
|
||||
|
||||
private final List<Parameter> params;
|
||||
|
||||
public ParameterList()
|
||||
{
|
||||
params = new ArrayList<Parameter>();
|
||||
}
|
||||
|
||||
ParameterList(List<Parameter> params)
|
||||
{
|
||||
this.params = new ArrayList<Parameter>(params);
|
||||
}
|
||||
|
||||
public ParameterList(Map<String, String> map)
|
||||
{
|
||||
this();
|
||||
for(Map.Entry<String, String> entry : map.entrySet())
|
||||
{
|
||||
params.add(new Parameter(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
public void add(String key, String value)
|
||||
{
|
||||
params.add(new Parameter(key, value));
|
||||
}
|
||||
|
||||
public String appendTo(String url)
|
||||
{
|
||||
Preconditions.checkNotNull(url, "Cannot append to null URL");
|
||||
String queryString = asFormUrlEncodedString();
|
||||
if (queryString.equals(EMPTY_STRING))
|
||||
{
|
||||
return url;
|
||||
}
|
||||
else
|
||||
{
|
||||
url += url.indexOf(QUERY_STRING_SEPARATOR) != -1 ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR;
|
||||
url += queryString;
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
public String asOauthBaseString()
|
||||
{
|
||||
try
|
||||
{
|
||||
return URLEncoder.encode(asFormUrlEncodedString(), "UTF8");
|
||||
}
|
||||
catch (UnsupportedEncodingException uee)
|
||||
{
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
public String asFormUrlEncodedString()
|
||||
{
|
||||
if (params.size() == 0) return EMPTY_STRING;
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for(Parameter p : params)
|
||||
{
|
||||
builder.append('&').append(p.asUrlEncodedPair());
|
||||
}
|
||||
return builder.toString().substring(1);
|
||||
}
|
||||
|
||||
public void addAll(ParameterList other)
|
||||
{
|
||||
params.addAll(other.params);
|
||||
}
|
||||
|
||||
public void addQuerystring(String queryString)
|
||||
{
|
||||
if (queryString != null && queryString.length() > 0)
|
||||
{
|
||||
for (String param : queryString.split(PARAM_SEPARATOR))
|
||||
{
|
||||
String pair[] = param.split(PAIR_SEPARATOR);
|
||||
String key = OAuthEncoder.decode(pair[0]);
|
||||
String value = pair.length > 1 ? OAuthEncoder.decode(pair[1]) : EMPTY_STRING;
|
||||
params.add(new Parameter(key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(Parameter param)
|
||||
{
|
||||
return params.contains(param);
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return params.size();
|
||||
}
|
||||
|
||||
public ParameterList sort()
|
||||
{
|
||||
ParameterList sorted = new ParameterList(params);
|
||||
Collections.sort(sorted.params);
|
||||
return sorted;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.scribe.exceptions.*;
|
||||
import org.scribe.utils.*;
|
||||
|
||||
/**
|
||||
* Represents an HTTP Request object
|
||||
@@ -17,11 +16,13 @@ import org.scribe.utils.*;
|
||||
class Request
|
||||
{
|
||||
private static final String CONTENT_LENGTH = "Content-Length";
|
||||
private static final String CONTENT_TYPE = "Content-Type";
|
||||
public static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded";
|
||||
|
||||
private String url;
|
||||
private Verb verb;
|
||||
private Map<String, String> querystringParams;
|
||||
private Map<String, String> bodyParams;
|
||||
private ParameterList querystringParams;
|
||||
private ParameterList bodyParams;
|
||||
private Map<String, String> headers;
|
||||
private String payload = null;
|
||||
private HttpURLConnection connection;
|
||||
@@ -41,8 +42,8 @@ class Request
|
||||
{
|
||||
this.verb = verb;
|
||||
this.url = url;
|
||||
this.querystringParams = new HashMap<String, String>();
|
||||
this.bodyParams = new HashMap<String, String>();
|
||||
this.querystringParams = new ParameterList();
|
||||
this.bodyParams = new ParameterList();
|
||||
this.headers = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
@@ -59,22 +60,37 @@ class Request
|
||||
{
|
||||
createConnection();
|
||||
return doSend();
|
||||
} catch (IOException ioe)
|
||||
}
|
||||
catch (UnknownHostException uhe)
|
||||
{
|
||||
throw new OAuthException("Problems while creating connection", ioe);
|
||||
throw new OAuthException("Could not reach the desired host. Check your network connection.", uhe);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new OAuthException("Problems while creating connection.", ioe);
|
||||
}
|
||||
}
|
||||
|
||||
private void createConnection() throws IOException
|
||||
{
|
||||
String effectiveUrl = URLUtils.appendParametersToQueryString(url, querystringParams);
|
||||
String completeUrl = getCompleteUrl();
|
||||
if (connection == null)
|
||||
{
|
||||
System.setProperty("http.keepAlive", connectionKeepAlive ? "true" : "false");
|
||||
connection = (HttpURLConnection) new URL(effectiveUrl).openConnection();
|
||||
connection = (HttpURLConnection) new URL(completeUrl).openConnection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the complete url (host + resource + encoded querystring parameters).
|
||||
*
|
||||
* @return the complete url.
|
||||
*/
|
||||
public String getCompleteUrl()
|
||||
{
|
||||
return querystringParams.appendTo(url);
|
||||
}
|
||||
|
||||
Response doSend() throws IOException
|
||||
{
|
||||
connection.setRequestMethod(this.verb.name());
|
||||
@@ -103,6 +119,12 @@ class Request
|
||||
void addBody(HttpURLConnection conn, byte[] content) throws IOException
|
||||
{
|
||||
conn.setRequestProperty(CONTENT_LENGTH, String.valueOf(content.length));
|
||||
|
||||
// Set default content type if none is set.
|
||||
if (conn.getRequestProperty(CONTENT_TYPE) == null)
|
||||
{
|
||||
conn.setRequestProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
|
||||
}
|
||||
conn.setDoOutput(true);
|
||||
conn.getOutputStream().write(content);
|
||||
}
|
||||
@@ -126,7 +148,7 @@ class Request
|
||||
*/
|
||||
public void addBodyParameter(String key, String value)
|
||||
{
|
||||
this.bodyParams.put(key, value);
|
||||
this.bodyParams.add(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,7 +159,7 @@ class Request
|
||||
*/
|
||||
public void addQuerystringParameter(String key, String value)
|
||||
{
|
||||
this.querystringParams.put(key, value);
|
||||
this.querystringParams.add(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,20 +188,20 @@ class Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a {@link Map} of the query string parameters.
|
||||
* Get a {@link ParameterList} with the query string parameters.
|
||||
*
|
||||
* @return a map containing the query string parameters
|
||||
* @throws OAuthException if the URL is not valid
|
||||
* @return a {@link ParameterList} containing the query string parameters.
|
||||
* @throws OAuthException if the request URL is not valid.
|
||||
*/
|
||||
public Map<String, String> getQueryStringParams()
|
||||
public ParameterList getQueryStringParams()
|
||||
{
|
||||
try
|
||||
{
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
ParameterList result = new ParameterList();
|
||||
String queryString = new URL(url).getQuery();
|
||||
params.putAll(URLUtils.queryStringToMap(queryString));
|
||||
params.putAll(this.querystringParams);
|
||||
return params;
|
||||
result.addQuerystring(queryString);
|
||||
result.addAll(querystringParams);
|
||||
return result;
|
||||
}
|
||||
catch (MalformedURLException mue)
|
||||
{
|
||||
@@ -188,11 +210,11 @@ class Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@link Map} of the body parameters.
|
||||
* Obtains a {@link ParameterList} of the body parameters.
|
||||
*
|
||||
* @return a map containing the body parameters.
|
||||
* @return a {@link ParameterList}containing the body parameters.
|
||||
*/
|
||||
public Map<String, String> getBodyParams()
|
||||
public ParameterList getBodyParams()
|
||||
{
|
||||
return bodyParams;
|
||||
}
|
||||
@@ -238,7 +260,7 @@ class Request
|
||||
byte[] getByteBodyContents()
|
||||
{
|
||||
if (bytePayload != null) return bytePayload;
|
||||
String body = (payload != null) ? payload : URLUtils.formURLEncodeMap(bodyParams);
|
||||
String body = (payload != null) ? payload : bodyParams.asFormUrlEncodedString();
|
||||
try
|
||||
{
|
||||
return body.getBytes(getCharset());
|
||||
@@ -314,7 +336,7 @@ class Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets wether the underlying Http Connection is persistent or not.
|
||||
* Sets whether the underlying Http Connection is persistent or not.
|
||||
*
|
||||
* @see http://download.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html
|
||||
* @param connectionKeepAlive
|
||||
|
||||
@@ -27,11 +27,12 @@ public class Response
|
||||
connection.connect();
|
||||
code = connection.getResponseCode();
|
||||
headers = parseHeaders(connection);
|
||||
stream = wasSuccessful() ? connection.getInputStream() : connection.getErrorStream();
|
||||
} catch (UnknownHostException e)
|
||||
stream = isSuccessful() ? connection.getInputStream() : connection.getErrorStream();
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
code = 404;
|
||||
body = EMPTY;
|
||||
body = Response.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +52,7 @@ public class Response
|
||||
return headers;
|
||||
}
|
||||
|
||||
private boolean wasSuccessful()
|
||||
public boolean isSuccessful()
|
||||
{
|
||||
return getCode() >= 200 && getCode() < 400;
|
||||
}
|
||||
@@ -100,10 +101,9 @@ public class Response
|
||||
/**
|
||||
* Obtains a single HTTP Header value, or null if undefined
|
||||
*
|
||||
* @param header
|
||||
* name
|
||||
* @param name the header name.
|
||||
*
|
||||
* @return header value or null
|
||||
* @return header value or null.
|
||||
*/
|
||||
public String getHeader(String name)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.*;
|
||||
|
||||
import org.scribe.builder.api.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.utils.*;
|
||||
|
||||
/**
|
||||
* OAuth 1.0a implementation of {@link OAuthService}
|
||||
@@ -34,12 +35,21 @@ public class OAuth10aServiceImpl implements OAuthService
|
||||
*/
|
||||
public Token getRequestToken()
|
||||
{
|
||||
config.log("obtaining request token from " + api.getRequestTokenEndpoint());
|
||||
OAuthRequest request = new OAuthRequest(api.getRequestTokenVerb(), api.getRequestTokenEndpoint());
|
||||
|
||||
config.log("setting oauth_callback to " + config.getCallback());
|
||||
request.addOAuthParameter(OAuthConstants.CALLBACK, config.getCallback());
|
||||
addOAuthParams(request, OAuthConstants.EMPTY_TOKEN);
|
||||
addSignature(request);
|
||||
appendSignature(request);
|
||||
|
||||
config.log("sending request...");
|
||||
Response response = request.send();
|
||||
return api.getRequestTokenExtractor().extract(response.getBody());
|
||||
String body = response.getBody();
|
||||
|
||||
config.log("response status code: " + response.getCode());
|
||||
config.log("response body: " + body);
|
||||
return api.getRequestTokenExtractor().extract(body);
|
||||
}
|
||||
|
||||
private void addOAuthParams(OAuthRequest request, Token token)
|
||||
@@ -51,6 +61,8 @@ public class OAuth10aServiceImpl implements OAuthService
|
||||
request.addOAuthParameter(OAuthConstants.VERSION, getVersion());
|
||||
if(config.hasScope()) request.addOAuthParameter(OAuthConstants.SCOPE, config.getScope());
|
||||
request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, token));
|
||||
|
||||
config.log("appended additional OAuth parameters: " + MapUtils.toString(request.getOauthParameters()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,11 +70,14 @@ public class OAuth10aServiceImpl implements OAuthService
|
||||
*/
|
||||
public Token getAccessToken(Token requestToken, Verifier verifier)
|
||||
{
|
||||
config.log("obtaining access token from " + api.getAccessTokenEndpoint());
|
||||
OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
|
||||
request.addOAuthParameter(OAuthConstants.TOKEN, requestToken.getToken());
|
||||
request.addOAuthParameter(OAuthConstants.VERIFIER, verifier.getValue());
|
||||
|
||||
config.log("setting token to: " + requestToken + " and verifier to: " + verifier);
|
||||
addOAuthParams(request, requestToken);
|
||||
addSignature(request);
|
||||
appendSignature(request);
|
||||
Response response = request.send();
|
||||
return api.getAccessTokenExtractor().extract(response.getBody());
|
||||
}
|
||||
@@ -72,9 +87,12 @@ public class OAuth10aServiceImpl implements OAuthService
|
||||
*/
|
||||
public void signRequest(Token token, OAuthRequest request)
|
||||
{
|
||||
config.log("signing request: " + request.getCompleteUrl());
|
||||
request.addOAuthParameter(OAuthConstants.TOKEN, token.getToken());
|
||||
|
||||
config.log("setting token to: " + token);
|
||||
addOAuthParams(request, token);
|
||||
addSignature(request);
|
||||
appendSignature(request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,19 +113,28 @@ public class OAuth10aServiceImpl implements OAuthService
|
||||
|
||||
private String getSignature(OAuthRequest request, Token token)
|
||||
{
|
||||
config.log("generating signature...");
|
||||
String baseString = api.getBaseStringExtractor().extract(request);
|
||||
return api.getSignatureService().getSignature(baseString, config.getApiSecret(), token.getSecret());
|
||||
String signature = api.getSignatureService().getSignature(baseString, config.getApiSecret(), token.getSecret());
|
||||
|
||||
config.log("base string is: " + baseString);
|
||||
config.log("signature is: " + signature);
|
||||
return signature;
|
||||
}
|
||||
|
||||
private void addSignature(OAuthRequest request)
|
||||
private void appendSignature(OAuthRequest request)
|
||||
{
|
||||
switch (config.getSignatureType())
|
||||
{
|
||||
case Header:
|
||||
config.log("using Http Header signature");
|
||||
|
||||
String oauthHeader = api.getHeaderExtractor().extract(request);
|
||||
request.addHeader(OAuthConstants.HEADER, oauthHeader);
|
||||
break;
|
||||
case QueryString:
|
||||
config.log("using Querystring signature");
|
||||
|
||||
for (Map.Entry<String, String> entry : request.getOauthParameters().entrySet())
|
||||
{
|
||||
request.addQuerystringParameter(entry.getKey(), entry.getValue());
|
||||
|
||||
@@ -30,7 +30,7 @@ public class HMACSha1SignatureService implements SignatureService
|
||||
{
|
||||
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, URLUtils.percentEncode(apiSecret) + '&' + URLUtils.percentEncode(tokenSecret));
|
||||
return doSign(baseString, OAuthEncoder.encode(apiSecret) + '&' + OAuthEncoder.encode(tokenSecret));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ public class PlaintextSignatureService implements SignatureService
|
||||
try
|
||||
{
|
||||
Preconditions.checkEmptyString(apiSecret, "Api secret cant be null or empty string");
|
||||
return URLUtils.percentEncode(apiSecret) + '&' + URLUtils.percentEncode(tokenSecret);
|
||||
return OAuthEncoder.encode(apiSecret) + '&' + OAuthEncoder.encode(tokenSecret);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -1,51 +1,22 @@
|
||||
package org.scribe.utils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Utils for {@link Map} manipulation
|
||||
*
|
||||
* @author Pablo Fernandez
|
||||
* @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)
|
||||
public static <K,V> String toString(Map<K,V> map)
|
||||
{
|
||||
Preconditions.checkNotNull(map, "Cannot sort a null object.");
|
||||
if (map == null) return "";
|
||||
if (map.isEmpty()) return "{}";
|
||||
|
||||
Map<String, String> sorted = new LinkedHashMap<String, String>();
|
||||
for (String key : getSortedKeys(map))
|
||||
StringBuilder result = new StringBuilder();
|
||||
for(Map.Entry<K,V> entry : map.entrySet())
|
||||
{
|
||||
sorted.put(key, map.get(key));
|
||||
}
|
||||
return sorted;
|
||||
}
|
||||
|
||||
private static List<String> getSortedKeys(Map<String, String> map)
|
||||
{
|
||||
List<String> keys = new ArrayList<String>(map.keySet());
|
||||
Collections.sort(keys);
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form-urlDecodes and appends all keys from the source {@link Map} to the
|
||||
* target {@link Map}
|
||||
*
|
||||
* @param source Map from where the keys get copied and decoded
|
||||
* @param target Map where the decoded keys are copied to
|
||||
*/
|
||||
public static void decodeAndAppendEntries(Map<String, String> source, Map<String, String> target)
|
||||
{
|
||||
for (String key: source.keySet())
|
||||
{
|
||||
target.put(URLUtils.percentEncode(key), URLUtils.percentEncode(source.get(key)));
|
||||
result.append(String.format(", %s -> %s ", entry.getKey().toString(), entry.getValue().toString()));
|
||||
}
|
||||
return "{" + result.substring(1) + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.scribe.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
import org.scribe.exceptions.*;
|
||||
|
||||
/**
|
||||
* @author: Pablo Fernandez
|
||||
*/
|
||||
public class OAuthEncoder
|
||||
{
|
||||
private static String CHARSET = "UTF-8";
|
||||
private static final Map<String, String> ENCODING_RULES;
|
||||
|
||||
static
|
||||
{
|
||||
Map<String, String> rules = new HashMap<String, String>();
|
||||
rules.put("*", "%2A");
|
||||
rules.put("+", "%20");
|
||||
rules.put("%7E", "~");
|
||||
ENCODING_RULES = Collections.unmodifiableMap(rules);
|
||||
}
|
||||
|
||||
public static String encode(String plain)
|
||||
{
|
||||
Preconditions.checkNotNull(plain, "Cannot encode null object");
|
||||
String encoded = "";
|
||||
try
|
||||
{
|
||||
encoded = URLEncoder.encode(plain, CHARSET);
|
||||
}
|
||||
catch (UnsupportedEncodingException uee)
|
||||
{
|
||||
throw new OAuthException("Charset not found while encoding string: " + CHARSET, uee);
|
||||
}
|
||||
for(Map.Entry<String, String> rule : ENCODING_RULES.entrySet())
|
||||
{
|
||||
encoded = applyRule(encoded, rule.getKey(), rule.getValue());
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
private static String applyRule(String encoded, String toReplace, String replacement)
|
||||
{
|
||||
return encoded.replaceAll(Pattern.quote(toReplace), replacement);
|
||||
}
|
||||
|
||||
public static String decode(String encoded)
|
||||
{
|
||||
Preconditions.checkNotNull(encoded, "Cannot decode null object");
|
||||
try
|
||||
{
|
||||
return URLDecoder.decode(encoded, CHARSET);
|
||||
}
|
||||
catch(UnsupportedEncodingException uee)
|
||||
{
|
||||
throw new OAuthException("Charset not found while decoding string: " + CHARSET, uee);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
package org.scribe.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 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 String PAIR_SEPARATOR = "=";
|
||||
private static final String PARAM_SEPARATOR = "&";
|
||||
private static final char QUERY_STRING_SEPARATOR = '?';
|
||||
|
||||
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-urlencoded string
|
||||
*
|
||||
* @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");
|
||||
return (map.size() <= 0) ? EMPTY_STRING : doFormUrlEncode(map);
|
||||
}
|
||||
|
||||
private static String doFormUrlEncode(Map<String, String> map)
|
||||
{
|
||||
StringBuffer encodedString = new StringBuffer(map.size() * 20);
|
||||
for (String key : map.keySet())
|
||||
{
|
||||
encodedString.append(PARAM_SEPARATOR).append(formURLEncode(key));
|
||||
if(map.get(key) != null)
|
||||
{
|
||||
encodedString.append(PAIR_SEPARATOR).append(formURLEncode(map.get(key)));
|
||||
}
|
||||
}
|
||||
return encodedString.toString().substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Percent encodes a string
|
||||
*
|
||||
* @param string plain string
|
||||
* @return percent encoded string
|
||||
*/
|
||||
public static String percentEncode(String string)
|
||||
{
|
||||
String encoded = formURLEncode(string);
|
||||
for (EncodingRule rule : ENCODING_RULES)
|
||||
{
|
||||
encoded = rule.apply(encoded);
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a string into application/x-www-form-urlencoded format
|
||||
*
|
||||
* @param plain
|
||||
* @return form-urlencoded string
|
||||
*/
|
||||
public static String formURLEncode(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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a application/x-www-form-urlencoded string
|
||||
*
|
||||
* @param string form-urlencoded string
|
||||
* @return plain string
|
||||
*/
|
||||
public static String formURLDecode(String string)
|
||||
{
|
||||
Preconditions.checkNotNull(string, "Cannot decode null string");
|
||||
try
|
||||
{
|
||||
return URLDecoder.decode(string, UTF_8);
|
||||
}
|
||||
catch (UnsupportedEncodingException 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.equals(EMPTY_STRING))
|
||||
{
|
||||
return url;
|
||||
}
|
||||
else
|
||||
{
|
||||
url += url.indexOf(QUERY_STRING_SEPARATOR) != -1 ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR;
|
||||
url += queryString;
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Concats a key-value map into a querystring-like String
|
||||
*
|
||||
* @param params key-value map
|
||||
* @return querystring-like String
|
||||
*/
|
||||
// TODO Move to MapUtils
|
||||
public static String concatSortedPercentEncodedParams(Map<String, String> params)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (String key : params.keySet())
|
||||
{
|
||||
result.append(key).append(PAIR_SEPARATOR);
|
||||
result.append(params.get(key)).append(PARAM_SEPARATOR);
|
||||
}
|
||||
return result.toString().substring(0, result.length() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and form-urldecodes a querystring-like string into a map
|
||||
*
|
||||
* @param queryString querystring-like String
|
||||
* @return a map with the form-urldecoded parameters
|
||||
*/
|
||||
// TODO Move to MapUtils
|
||||
public static Map<String, String> queryStringToMap(String queryString)
|
||||
{
|
||||
Map<String, String> result = new HashMap<String, String>();
|
||||
if (queryString != null && queryString.length() > 0)
|
||||
{
|
||||
for (String param : queryString.split(PARAM_SEPARATOR))
|
||||
{
|
||||
String pair[] = param.split(PAIR_SEPARATOR);
|
||||
String key = formURLDecode(pair[0]);
|
||||
String value = pair.length > 1 ? formURLDecode(pair[1]) : EMPTY_STRING;
|
||||
result.put(key, value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,8 +63,7 @@ public class ServiceBuilderTest
|
||||
public static class ApiMock implements Api
|
||||
{
|
||||
public static OAuthConfig config;
|
||||
|
||||
@Override
|
||||
|
||||
public OAuthService createService(OAuthConfig config)
|
||||
{
|
||||
ApiMock.config = config;
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.scribe.oauth.*;
|
||||
|
||||
public class TwitterExample
|
||||
{
|
||||
private static final String PROTECTED_RESOURCE_URL = "http://api.twitter.com/1/account/verify_credentials.xml";
|
||||
private static final String PROTECTED_RESOURCE_URL = "https://api.twitter.com/1/statuses/update.json";
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
@@ -45,7 +45,8 @@ public class TwitterExample
|
||||
|
||||
// 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);
|
||||
OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL);
|
||||
request.addBodyParameter("status", "this is sparta! *");
|
||||
service.signRequest(accessToken, request);
|
||||
Response response = request.send();
|
||||
System.out.println("Got it! Lets see what we found...");
|
||||
|
||||
@@ -41,7 +41,7 @@ public class BaseStringExtractorTest
|
||||
OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com");
|
||||
extractor.extract(request);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldProperlyEncodeSpaces()
|
||||
{
|
||||
|
||||
@@ -35,6 +35,15 @@ public class TokenExtractor20Test
|
||||
assertEquals("", extracted.getSecret());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractTokenFromResponseWithManyParameters()
|
||||
{
|
||||
String response = "access_token=foo1234&other_stuff=yeah_we_have_this_too&number=42";
|
||||
Token extracted = extractor.extract(response);
|
||||
assertEquals("foo1234", extracted.getToken());
|
||||
assertEquals("", extracted.getSecret());
|
||||
}
|
||||
|
||||
@Test(expected = OAuthException.class)
|
||||
public void shouldThrowExceptionIfTokenIsAbsent()
|
||||
{
|
||||
|
||||
@@ -22,6 +22,12 @@ public class ConnectionStub extends HttpURLConnection
|
||||
headers.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestProperty(String s)
|
||||
{
|
||||
return headers.get(s);
|
||||
}
|
||||
|
||||
public Map<String, String> getHeaders()
|
||||
{
|
||||
return headers;
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.scribe.model;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
public class OAuthConfigTest
|
||||
{
|
||||
|
||||
@Test
|
||||
public void shouldReturnDefaultValuesIfNotSet()
|
||||
{
|
||||
OAuthConfig config = new OAuthConfig("key", "secret");
|
||||
assertEquals(OAuthConstants.OUT_OF_BAND, config.getCallback());
|
||||
assertEquals(SignatureType.Header, config.getSignatureType());
|
||||
assertFalse(config.hasScope());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldOverrideDefaultsIfSet()
|
||||
{
|
||||
OAuthConfig config = new OAuthConfig("key", "secret", "http://callback", SignatureType.Header, "scope");
|
||||
assertEquals("http://callback", config.getCallback());
|
||||
assertEquals("key", config.getApiKey());
|
||||
assertEquals("secret", config.getApiSecret());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package org.scribe.model;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
|
||||
/**
|
||||
* @author: Pablo Fernandez
|
||||
*/
|
||||
public class ParameterListTest
|
||||
{
|
||||
private ParameterList params;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
this.params = new ParameterList();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionWhenAppendingNullMapToQuerystring()
|
||||
{
|
||||
String url = null;
|
||||
params.appendTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAppendNothingToQuerystringIfGivenEmptyMap()
|
||||
{
|
||||
String url = "http://www.example.com";
|
||||
Assert.assertEquals(url, params.appendTo(url));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAppendParametersToSimpleUrl()
|
||||
{
|
||||
String url = "http://www.example.com";
|
||||
String expectedUrl = "http://www.example.com?param1=value1¶m2=value%20with%20spaces";
|
||||
|
||||
params.add("param1", "value1");
|
||||
params.add("param2", "value with spaces");
|
||||
|
||||
url = params.appendTo(url);
|
||||
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%20with%20spaces";
|
||||
|
||||
params.add("param1", "value1");
|
||||
params.add("param2", "value with spaces");
|
||||
|
||||
url = params.appendTo(url);
|
||||
Assert.assertEquals(url, expectedUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldProperlySortParameters()
|
||||
{
|
||||
params.add("param1", "v1");
|
||||
params.add("param6", "v2");
|
||||
params.add("a_param", "v3");
|
||||
params.add("param2", "v4");
|
||||
Assert.assertEquals("a_param=v3¶m1=v1¶m2=v4¶m6=v2", params.sort().asFormUrlEncodedString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldProperlySortParametersWithTheSameName()
|
||||
{
|
||||
params.add("param1", "v1");
|
||||
params.add("param6", "v2");
|
||||
params.add("a_param", "v3");
|
||||
params.add("param1", "v4");
|
||||
Assert.assertEquals("a_param=v3¶m1=v1¶m1=v4¶m6=v2", params.sort().asFormUrlEncodedString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotModifyTheOriginalParameterList()
|
||||
{
|
||||
params.add("param1", "v1");
|
||||
params.add("param6", "v2");
|
||||
|
||||
assertNotSame(params, params.sort());
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import org.junit.*;
|
||||
|
||||
public class RequestTest
|
||||
{
|
||||
|
||||
private Request getRequest;
|
||||
private Request postRequest;
|
||||
private ConnectionStub connection;
|
||||
@@ -35,8 +34,7 @@ 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().contains(new Parameter("qsparam", "value")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -52,7 +50,7 @@ public class RequestTest
|
||||
@Test
|
||||
public void shouldSetBodyParamsAndAddContentLength()
|
||||
{
|
||||
assertEquals("param=value¶m+with+spaces=value+with+spaces", postRequest.getBodyContents());
|
||||
assertEquals("param=value¶m%20with%20spaces=value%20with%20spaces", postRequest.getBodyContents());
|
||||
postRequest.send();
|
||||
assertTrue(connection.getHeaders().containsKey("Content-Length"));
|
||||
}
|
||||
@@ -75,9 +73,56 @@ public class RequestTest
|
||||
assertEquals(3, request.getQueryStringParams().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnTheCompleteUrl()
|
||||
{
|
||||
Request request = new Request(Verb.GET, "http://example.com?one=val");
|
||||
request.addQuerystringParameter("two", "other val");
|
||||
request.addQuerystringParameter("more", "params");
|
||||
assertEquals("http://example.com?one=val&two=other%20val&more=params", request.getCompleteUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandleQueryStringSpaceEncodingProperly()
|
||||
{
|
||||
assertTrue(getRequest.getQueryStringParams().get("other param").equals("value with spaces"));
|
||||
assertTrue(getRequest.getQueryStringParams().contains(new Parameter("other param","value with spaces")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAutomaticallyAddContentTypeForPostRequestsWithBytePayload()
|
||||
{
|
||||
postRequest.addPayload("PAYLOAD".getBytes());
|
||||
postRequest.send();
|
||||
assertEquals(Request.DEFAULT_CONTENT_TYPE, connection.getHeaders().get("Content-Type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAutomaticallyAddContentTypeForPostRequestsWithStringPayload()
|
||||
{
|
||||
postRequest.addPayload("PAYLOAD");
|
||||
postRequest.send();
|
||||
assertEquals(Request.DEFAULT_CONTENT_TYPE, connection.getHeaders().get("Content-Type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAutomaticallyAddContentTypeForPostRequestsWithBodyParameters()
|
||||
{
|
||||
postRequest.send();
|
||||
assertEquals(Request.DEFAULT_CONTENT_TYPE, connection.getHeaders().get("Content-Type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeAbleToOverrideItsContentType()
|
||||
{
|
||||
postRequest.addHeader("Content-Type", "my-content-type");
|
||||
postRequest.send();
|
||||
assertEquals("my-content-type", connection.getHeaders().get("Content-Type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotAddContentTypeForGetRequests()
|
||||
{
|
||||
getRequest.send();
|
||||
assertFalse(connection.getHeaders().containsKey("Content-Type"));
|
||||
}
|
||||
}
|
||||
@@ -1,53 +1,35 @@
|
||||
package org.scribe.utils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
/**
|
||||
* @author: Pablo Fernandez
|
||||
*/
|
||||
public class MapUtilsTest
|
||||
{
|
||||
|
||||
private Map<String, String> unsorted;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
@Test
|
||||
public void shouldPrettyPrintMap()
|
||||
{
|
||||
unsorted = new LinkedHashMap<String, String>();
|
||||
unsorted.put("d", "fourth");
|
||||
unsorted.put("a", "first");
|
||||
unsorted.put("c", "third");
|
||||
unsorted.put("b", "second");
|
||||
Map<Integer, String> map = new HashMap<Integer, String>();
|
||||
map.put(1, "one");
|
||||
map.put(2, "two");
|
||||
map.put(3, "three");
|
||||
map.put(4, "four");
|
||||
Assert.assertEquals("{ 1 -> one , 2 -> two , 3 -> three , 4 -> four }", MapUtils.toString(map));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSortMap()
|
||||
public void shouldHandleEmptyMap()
|
||||
{
|
||||
Map<String, String> sorted = MapUtils.sort(unsorted);
|
||||
List<String> values = new ArrayList<String>(sorted.values());
|
||||
assertEquals("first", values.get(0));
|
||||
assertEquals("second", values.get(1));
|
||||
assertEquals("third", values.get(2));
|
||||
assertEquals("fourth", values.get(3));
|
||||
Map<Integer, String> map = new HashMap<Integer, String>();
|
||||
Assert.assertEquals("{}", MapUtils.toString(map));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotModifyTheOriginalMap()
|
||||
public void shouldHandleNullInputs()
|
||||
{
|
||||
Map<String, String> sorted = MapUtils.sort(unsorted);
|
||||
assertNotSame(sorted, unsorted);
|
||||
|
||||
List<String> values = new ArrayList<String>(unsorted.values());
|
||||
assertEquals("fourth", values.get(0));
|
||||
assertEquals("first", values.get(1));
|
||||
assertEquals("third", values.get(2));
|
||||
assertEquals("second", values.get(3));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionForNullMap()
|
||||
{
|
||||
MapUtils.sort(null);
|
||||
Assert.assertEquals("", MapUtils.toString(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.scribe.utils;
|
||||
|
||||
import org.junit.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author: Pablo Fernandez
|
||||
*/
|
||||
public class OAuthEncoderTest
|
||||
{
|
||||
@Test
|
||||
public void shouldPercentEncodeString()
|
||||
{
|
||||
String plain = "this is a test &^";
|
||||
String encoded = "this%20is%20a%20test%20%26%5E";
|
||||
assertEquals(encoded, OAuthEncoder.encode(plain));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFormURLDecodeString()
|
||||
{
|
||||
String encoded = "this+is+a+test+%26%5E";
|
||||
String plain = "this is a test &^";
|
||||
assertEquals(plain, OAuthEncoder.decode(encoded));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPercentEncodeAllSpecialCharacters()
|
||||
{
|
||||
String plain = "!*'();:@&=+$,/?#[]";
|
||||
String encoded = "%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D";
|
||||
assertEquals(encoded, OAuthEncoder.encode(plain));
|
||||
assertEquals(plain, OAuthEncoder.decode(encoded));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotPercentEncodeReservedCharacters()
|
||||
{
|
||||
String plain = "abcde123456-._~";
|
||||
String encoded = plain;
|
||||
assertEquals(encoded, OAuthEncoder.encode(plain));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionIfStringToEncodeIsNull()
|
||||
{
|
||||
String toEncode = null;
|
||||
OAuthEncoder.encode(toEncode);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionIfStringToDecodeIsNull()
|
||||
{
|
||||
String toDecode = null;
|
||||
OAuthEncoder.decode(toDecode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPercentEncodeCorrectlyTwitterCodingExamples()
|
||||
{
|
||||
// These tests are part of the Twitter dev examples here -> https://dev.twitter.com/docs/auth/percent-encoding-parameters
|
||||
String sources[] = {"Ladies + Gentlemen", "An encoded string!", "Dogs, Cats & Mice"};
|
||||
String encoded[] = {"Ladies%20%2B%20Gentlemen", "An%20encoded%20string%21", "Dogs%2C%20Cats%20%26%20Mice"};
|
||||
|
||||
for(int i = 0; i < sources.length; i++)
|
||||
{
|
||||
Assert.assertEquals(encoded[i], OAuthEncoder.encode(sources[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
package org.scribe.utils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
public class URLUtilsTest
|
||||
{
|
||||
@Test
|
||||
public void shouldPercentEncodeMap()
|
||||
{
|
||||
Map<String, String> params = new LinkedHashMap<String, String>();
|
||||
params.put("key", "value");
|
||||
params.put("key with spaces", "value with spaces");
|
||||
params.put("&symbols!", "#!");
|
||||
|
||||
String expected = "key=value&key+with+spaces=value+with+spaces&%26symbols%21=%23%21";
|
||||
assertEquals(expected, URLUtils.formURLEncodeMap(params));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnEmptyStringForEmptyMap()
|
||||
{
|
||||
Map<String, String> params = new LinkedHashMap<String, String>();
|
||||
String expected = "";
|
||||
assertEquals(expected, URLUtils.formURLEncodeMap(params));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFormURLEncodeMapWithMissingValues()
|
||||
{
|
||||
Map<String, String> params = new LinkedHashMap<String, String>();
|
||||
params.put("key", "value");
|
||||
params.put("key with spaces", null);
|
||||
|
||||
String expected = "key=value&key+with+spaces";
|
||||
assertEquals(expected, URLUtils.formURLEncodeMap(params));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPercentEncodeString()
|
||||
{
|
||||
String toEncode = "this is a test &^";
|
||||
String expected = "this%20is%20a%20test%20%26%5E";
|
||||
assertEquals(expected, URLUtils.percentEncode(toEncode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFormURLEncodeString()
|
||||
{
|
||||
String toEncode = "this is a test &^";
|
||||
String expected = "this+is+a+test+%26%5E";
|
||||
assertEquals(expected, URLUtils.formURLEncode(toEncode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFormURLDecodeString()
|
||||
{
|
||||
String toDecode = "this+is+a+test+%26%5E";
|
||||
String expected = "this is a test &^";
|
||||
assertEquals(expected, URLUtils.formURLDecode(toDecode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPercentEncodeAllSpecialCharacters()
|
||||
{
|
||||
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.formURLDecode(encoded));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotPercentEncodeReservedCharacters()
|
||||
{
|
||||
String plain = "abcde123456-._~";
|
||||
String encoded = plain;
|
||||
assertEquals(encoded, URLUtils.percentEncode(plain));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionIfMapIsNull()
|
||||
{
|
||||
Map<String, String> nullMap = null;
|
||||
URLUtils.formURLEncodeMap(nullMap);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionIfStringToEncodeIsNull()
|
||||
{
|
||||
String toEncode = null;
|
||||
URLUtils.percentEncode(toEncode);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionIfStringToDecodeIsNull()
|
||||
{
|
||||
String toDecode = null;
|
||||
URLUtils.formURLDecode(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 shouldPercentEncodePlusSymbol()
|
||||
{
|
||||
String plain = "7aEP+jNAwvjc0mjhqg0nuXPf";
|
||||
String encoded = "7aEP%2BjNAwvjc0mjhqg0nuXPf";
|
||||
|
||||
Assert.assertEquals(encoded, URLUtils.percentEncode(plain));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldURLDecodePlusSymbol()
|
||||
{
|
||||
String encoded = "oauth_verifier=7aEP%2BjNAwvjc0mjhqg0nuXPf";
|
||||
String expected = "oauth_verifier=7aEP+jNAwvjc0mjhqg0nuXPf";
|
||||
|
||||
Assert.assertEquals(expected, URLUtils.formURLDecode(encoded));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user