first step towards ParameterList refactoring

This commit is contained in:
Pablo Fernandez committed 2011-12-14 13:31:12 -03:00
1 parent 56561acdac
commit ce531cdc38
11 files changed
+318 -123

No files matched your search

@@ -31,12 +31,12 @@ public class BaseStringExtractorImpl implements BaseStringExtractor
private String getSortedAndEncodedParams(OAuthRequest request) private String getSortedAndEncodedParams(OAuthRequest request)
{ {
Map<String, String> params = new HashMap<String, String>(); ParameterList params = new ParameterList();
MapUtils.decodeAndAppendEntries(request.getQueryStringParams(), params); params.addAll(request.getQueryStringParams());
MapUtils.decodeAndAppendEntries(request.getBodyParams(), params); params.addAll(request.getBodyParams());
MapUtils.decodeAndAppendEntries(request.getOauthParameters(), params); params.addAll(new ParameterList(request.getOauthParameters()));
params = MapUtils.sort(params); params.sort();
return URLUtils.percentEncode(MapUtils.concatSortedPercentEncodedParams(params)); return params.asOauthBaseString();
} }
private void checkPreconditions(OAuthRequest request) private void checkPreconditions(OAuthRequest request)
@@ -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,117 @@
package org.scribe.model;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.scribe.utils.Preconditions;
import org.scribe.utils.URLUtils;
/**
* @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>();
}
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 = URLUtils.formURLDecode(pair[0]);
String value = pair.length > 1 ? URLUtils.formURLDecode(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 void sort()
{
Collections.sort(params);
}
}
+20 -21
View File
@@ -7,7 +7,6 @@ import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.scribe.exceptions.*; import org.scribe.exceptions.*;
import org.scribe.utils.*;
/** /**
* Represents an HTTP Request object * Represents an HTTP Request object
@@ -22,8 +21,8 @@ class Request
private String url; private String url;
private Verb verb; private Verb verb;
private Map<String, String> querystringParams; private ParameterList querystringParams;
private Map<String, String> bodyParams; private ParameterList bodyParams;
private Map<String, String> headers; private Map<String, String> headers;
private String payload = null; private String payload = null;
private HttpURLConnection connection; private HttpURLConnection connection;
@@ -43,8 +42,8 @@ class Request
{ {
this.verb = verb; this.verb = verb;
this.url = url; this.url = url;
this.querystringParams = new HashMap<String, String>(); this.querystringParams = new ParameterList();
this.bodyParams = new HashMap<String, String>(); this.bodyParams = new ParameterList();
this.headers = new HashMap<String, String>(); this.headers = new HashMap<String, String>();
} }
@@ -74,7 +73,7 @@ class Request
private void createConnection() throws IOException private void createConnection() throws IOException
{ {
String effectiveUrl = URLUtils.appendParametersToQueryString(url, querystringParams); String effectiveUrl = querystringParams.appendTo(url);
if (connection == null) if (connection == null)
{ {
System.setProperty("http.keepAlive", connectionKeepAlive ? "true" : "false"); System.setProperty("http.keepAlive", connectionKeepAlive ? "true" : "false");
@@ -139,7 +138,7 @@ class Request
*/ */
public void addBodyParameter(String key, String value) public void addBodyParameter(String key, String value)
{ {
this.bodyParams.put(key, value); this.bodyParams.add(key, value);
} }
/** /**
@@ -150,7 +149,7 @@ class Request
*/ */
public void addQuerystringParameter(String key, String value) public void addQuerystringParameter(String key, String value)
{ {
this.querystringParams.put(key, value); this.querystringParams.add(key, value);
} }
/** /**
@@ -179,20 +178,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 * @return a {@link ParameterList} containing the query string parameters.
* @throws OAuthException if the URL is not valid * @throws OAuthException if the request URL is not valid.
*/ */
public Map<String, String> getQueryStringParams() public ParameterList getQueryStringParams()
{ {
try try
{ {
Map<String, String> params = new HashMap<String, String>(); ParameterList result = new ParameterList();
String queryString = new URL(url).getQuery(); String queryString = new URL(url).getQuery();
params.putAll(MapUtils.queryStringToMap(queryString)); result.addQuerystring(queryString);
params.putAll(this.querystringParams); result.addAll(querystringParams);
return params; return result;
} }
catch (MalformedURLException mue) catch (MalformedURLException mue)
{ {
@@ -201,11 +200,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; return bodyParams;
} }
@@ -251,7 +250,7 @@ class Request
byte[] getByteBodyContents() byte[] getByteBodyContents()
{ {
if (bytePayload != null) return bytePayload; if (bytePayload != null) return bytePayload;
String body = (payload != null) ? payload : URLUtils.formURLEncodeMap(bodyParams); String body = (payload != null) ? payload : bodyParams.asFormUrlEncodedString();
try try
{ {
return body.getBytes(getCharset()); return body.getBytes(getCharset());
@@ -327,7 +326,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 * @see http://download.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html
* @param connectionKeepAlive * @param connectionKeepAlive
@@ -69,26 +69,4 @@ public class MapUtils
} }
return result.toString().substring(0, result.length() - 1); 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
*/
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 = URLUtils.formURLDecode(pair[0]);
String value = pair.length > 1 ? URLUtils.formURLDecode(pair[1]) : EMPTY_STRING;
result.put(key, value);
}
}
return result;
}
} }
@@ -0,0 +1,57 @@
package org.scribe.utils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import org.scribe.exceptions.OAuthException;
/**
* @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");
return encoded;
}
}
@@ -110,29 +110,6 @@ public class URLUtils
} }
} }
/**
* 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;
}
}
private static final class EncodingRule private static final class EncodingRule
{ {
private final String ch; private final String ch;
@@ -9,7 +9,7 @@ import org.scribe.oauth.*;
public class TwitterExample 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) public static void main(String[] args)
{ {
@@ -45,7 +45,8 @@ public class TwitterExample
// Now let's go and ask for a protected resource! // Now let's go and ask for a protected resource!
System.out.println("Now we're going to access 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); service.signRequest(accessToken, request);
Response response = request.send(); Response response = request.send();
System.out.println("Got it! Lets see what we found..."); System.out.println("Got it! Lets see what we found...");
@@ -0,0 +1,62 @@
package org.scribe.model;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.scribe.utils.URLUtils;
/**
* @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&param2=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&param1=value1&param2=value%20with%20spaces";
params.add("param1", "value1");
params.add("param2", "value with spaces");
url = params.appendTo(url);
Assert.assertEquals(url, expectedUrl);
}
}
@@ -34,8 +34,7 @@ public class RequestTest
{ {
assertEquals(2, getRequest.getQueryStringParams().size()); assertEquals(2, getRequest.getQueryStringParams().size());
assertEquals(0, postRequest.getQueryStringParams().size()); assertEquals(0, postRequest.getQueryStringParams().size());
assertTrue(getRequest.getQueryStringParams().containsKey("qsparam")); assertTrue(getRequest.getQueryStringParams().contains(new Parameter("qsparam", "value")));
assertTrue(getRequest.getQueryStringParams().get("qsparam").equals("value"));
} }
@Test @Test
@@ -51,7 +50,7 @@ public class RequestTest
@Test @Test
public void shouldSetBodyParamsAndAddContentLength() public void shouldSetBodyParamsAndAddContentLength()
{ {
assertEquals("param=value&param+with+spaces=value+with+spaces", postRequest.getBodyContents()); assertEquals("param=value&param%20with%20spaces=value%20with%20spaces", postRequest.getBodyContents());
postRequest.send(); postRequest.send();
assertTrue(connection.getHeaders().containsKey("Content-Length")); assertTrue(connection.getHeaders().containsKey("Content-Length"));
} }
@@ -77,7 +76,7 @@ public class RequestTest
@Test @Test
public void shouldHandleQueryStringSpaceEncodingProperly() 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 @Test
@@ -101,51 +101,6 @@ public class URLUtilsTest
URLUtils.formURLDecode(toDecode); 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&param2=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&param1=value1&param2=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 @Test
public void shouldPercentEncodePlusSymbol() public void shouldPercentEncodePlusSymbol()
{ {