You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by br...@apache.org on 2009/05/24 20:01:43 UTC
svn commit: r778203 - in /incubator/pivot/trunk:
tutorials/src/pivot/tutorials/stocktracker/ web/ web/src/pivot/web/
web/test/pivot/web/ web/test/pivot/web/test/
Author: brindy
Date: Sun May 24 18:01:42 2009
New Revision: 778203
URL: http://svn.apache.org/viewvc?rev=778203&view=rev
Log:
PIVOT-125
ArgumentsDictionary, RequestPropertiesDictionary and ResponsePropertiesDictionary have been replaced with QueryDictionary which is now returned from the respective getters. Each getter has been deprecated in favour of more appropriately named getters; getParameters, getRequestHeaders and getResponseHeaders respectively.
Added:
incubator/pivot/trunk/web/test/pivot/web/QueryDictionaryTest.java
Modified:
incubator/pivot/trunk/tutorials/src/pivot/tutorials/stocktracker/StockTracker.java
incubator/pivot/trunk/web/.classpath
incubator/pivot/trunk/web/src/pivot/web/BasicAuthentication.java
incubator/pivot/trunk/web/src/pivot/web/PostQuery.java
incubator/pivot/trunk/web/src/pivot/web/Query.java
incubator/pivot/trunk/web/test/pivot/web/test/WebQueryTestClient.java
Modified: incubator/pivot/trunk/tutorials/src/pivot/tutorials/stocktracker/StockTracker.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/src/pivot/tutorials/stocktracker/StockTracker.java?rev=778203&r1=778202&r2=778203&view=diff
==============================================================================
--- incubator/pivot/trunk/tutorials/src/pivot/tutorials/stocktracker/StockTracker.java (original)
+++ incubator/pivot/trunk/tutorials/src/pivot/tutorials/stocktracker/StockTracker.java Sun May 24 18:01:42 2009
@@ -212,8 +212,8 @@
// c1 - change percentage
// v - volume
String symbolsArgument = symbolsArgumentBuilder.toString();
- getQuery.getArguments().put("s", symbolsArgument);
- getQuery.getArguments().put("f", "snl1ohgc1v");
+ getQuery.getParameters().put("s", symbolsArgument);
+ getQuery.getParameters().put("f", "snl1ohgc1v");
CSVSerializer quoteSerializer = new CSVSerializer();
quoteSerializer.getKeys().add("symbol");
Modified: incubator/pivot/trunk/web/.classpath
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/web/.classpath?rev=778203&r1=778202&r2=778203&view=diff
==============================================================================
--- incubator/pivot/trunk/web/.classpath (original)
+++ incubator/pivot/trunk/web/.classpath Sun May 24 18:01:42 2009
@@ -5,5 +5,6 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/core"/>
<classpathentry kind="lib" path="lib/servlet-api.jar"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
<classpathentry kind="output" path="bin"/>
</classpath>
Modified: incubator/pivot/trunk/web/src/pivot/web/BasicAuthentication.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/web/src/pivot/web/BasicAuthentication.java?rev=778203&r1=778202&r2=778203&view=diff
==============================================================================
--- incubator/pivot/trunk/web/src/pivot/web/BasicAuthentication.java (original)
+++ incubator/pivot/trunk/web/src/pivot/web/BasicAuthentication.java Sun May 24 18:01:42 2009
@@ -44,6 +44,6 @@
String credentials = username + ":" + password;
String encodedCredentials = Base64.encode(credentials.getBytes());
- query.getRequestProperties().put("Authorization", "Basic " + encodedCredentials);
+ query.getRequestHeaders().put("Authorization", "Basic " + encodedCredentials);
}
}
Modified: incubator/pivot/trunk/web/src/pivot/web/PostQuery.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/web/src/pivot/web/PostQuery.java?rev=778203&r1=778202&r2=778203&view=diff
==============================================================================
--- incubator/pivot/trunk/web/src/pivot/web/PostQuery.java (original)
+++ incubator/pivot/trunk/web/src/pivot/web/PostQuery.java Sun May 24 18:01:42 2009
@@ -74,7 +74,7 @@
execute(METHOD, value);
- String location = getResponseProperties().get("Location");
+ String location = getResponseHeaders().get("Location");
if (location != null) {
try {
valueLocation = new URL(getLocation(), location);
Modified: incubator/pivot/trunk/web/src/pivot/web/Query.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/web/src/pivot/web/Query.java?rev=778203&r1=778202&r2=778203&view=diff
==============================================================================
--- incubator/pivot/trunk/web/src/pivot/web/Query.java (original)
+++ incubator/pivot/trunk/web/src/pivot/web/Query.java Sun May 24 18:01:42 2009
@@ -28,6 +28,7 @@
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
+import pivot.collections.ArrayList;
import pivot.collections.Dictionary;
import pivot.collections.HashMap;
import pivot.io.IOTask;
@@ -38,8 +39,8 @@
import pivot.util.concurrent.SynchronizedListenerList;
/**
- * Abstract base class for web queries. A web query is an asynchronous
- * operation that executes one of the following HTTP methods:
+ * Abstract base class for web queries. A web query is an asynchronous operation
+ * that executes one of the following HTTP methods:
*
* <ul>
* <li>GET</li>
@@ -49,9 +50,9 @@
* </ul>
*
* @param <V>
- * The type of the value retrieved or sent via the query. For GET operations,
- * it is {@link Object}; for POST operations, the type is {@link URL}. For PUT
- * and DELETE, it is {@link Void}.
+ * The type of the value retrieved or sent via the query. For GET
+ * operations, it is {@link Object}; for POST operations, the type is
+ * {@link URL}. For PUT and DELETE, it is {@link Void}.
*
* @author gbrown
* @author tvolkert
@@ -63,10 +64,7 @@
* @author gbrown
*/
public enum Method {
- GET,
- POST,
- PUT,
- DELETE
+ GET, POST, PUT, DELETE
}
/**
@@ -99,92 +97,105 @@
}
/**
- * Arguments dictionary implementation.
+ * This class allows multiple values to be set against a given key.
+ *
+ * @author brindy
*/
- public final class ArgumentsDictionary
- implements Dictionary<String, String>, Iterable<String> {
+ public final class QueryDictionary implements Dictionary<String, String>,
+ Iterable<String> {
+
+ private HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
+
public String get(String key) {
- return arguments.get(key);
+ ArrayList<String> list = map.get(key);
+ if (null != list && list.getLength() > 0) {
+ return list.get(0);
+ }
+ return null;
}
- public String put(String key, String value) {
- return arguments.put(key, value);
+ public String get(String key, int index) {
+ ArrayList<String> list = map.get(key);
+ if (null == list || list.getLength() <= index) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ return list.get(index);
}
- public String remove(String key) {
- return arguments.remove(key);
- }
+ public String put(String key, String value) {
+ ArrayList<String> list = new ArrayList<String>();
+ list.add(value);
- public boolean containsKey(String key) {
- return arguments.containsKey(key);
- }
+ ArrayList<String> old = map.put(key, list);
+ if (old != null && old.getLength() > 0) {
+ return old.get(0);
+ }
- public boolean isEmpty() {
- return arguments.isEmpty();
+ return null;
}
- public Iterator<String> iterator() {
- return arguments.iterator();
- }
- }
+ public int add(String key, String value) {
+ ArrayList<String> list = map.get(key);
+ if (null == list) {
+ put(key, value);
+ return 0;
+ }
- /**
- * Request properties dictionary implementation.
- */
- public final class RequestPropertiesDictionary
- implements Dictionary<String, String>, Iterable<String> {
- public String get(String key) {
- return requestProperties.get(key);
+ list.add(value);
+ return list.getLength() - 1;
}
- public String put(String key, String value) {
- return requestProperties.put(key, value);
- }
+ public void insert(String key, String value, int index) {
+ ArrayList<String> list = map.get(key);
- public String remove(String key) {
- return requestProperties.remove(key);
- }
+ // e.g if index = 0 and length = 0, throw an exception
+ if (null == list || list.getLength() <= index) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
- public boolean containsKey(String key) {
- return requestProperties.containsKey(key);
+ list.insert(value, index);
}
- public boolean isEmpty() {
- return requestProperties.isEmpty();
- }
+ public String remove(String key) {
- public Iterator<String> iterator() {
- return requestProperties.iterator();
- }
- }
+ ArrayList<String> list = map.remove(key);
+ if (null != list && list.getLength() > 0) {
+ return list.get(0);
+ }
- /**
- * Response properties dictionary implementation.
- */
- public final class ResponsePropertiesDictionary
- implements Dictionary<String, String>, Iterable<String> {
- public String get(String key) {
- return responseProperties.get(key);
+ return null;
}
- public String put(String key, String value) {
- throw new UnsupportedOperationException();
+ public String remove(String key, int index) {
+ ArrayList<String> list = map.get(key);
+ if (null == list || list.getLength() <= index) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ return list.get(index);
}
- public String remove(String key) {
- throw new UnsupportedOperationException();
+ public void clear() {
+ map.clear();
}
public boolean containsKey(String key) {
- return responseProperties.containsKey(key);
+ return map.containsKey(key);
}
public boolean isEmpty() {
- return responseProperties.isEmpty();
+ return map.isEmpty();
+ }
+
+ public int getLength(String key) {
+ ArrayList<String> list = map.get(key);
+ if (null == list) {
+ return 0;
+ }
+ return list.getLength();
}
public Iterator<String> iterator() {
- return responseProperties.iterator();
+ return map.iterator();
}
}
@@ -193,8 +204,9 @@
*
* @author tvolkert
*/
- private static class QueryListenerList<V> extends SynchronizedListenerList<QueryListener<V>>
- implements QueryListener<V> {
+ private static class QueryListenerList<V> extends
+ SynchronizedListenerList<QueryListener<V>> implements
+ QueryListener<V> {
public synchronized void connected(Query<V> query) {
for (QueryListener<V> listener : this) {
listener.connected(query);
@@ -223,13 +235,9 @@
private URL locationContext = null;
private HostnameVerifier hostnameVerifier = null;
- private HashMap<String, String> arguments = new HashMap<String, String>();
- private HashMap<String, String> requestProperties = new HashMap<String, String>();
- private HashMap<String, String> responseProperties = new HashMap<String, String>();
-
- private ArgumentsDictionary argumentsDictionary = new ArgumentsDictionary();
- private RequestPropertiesDictionary requestPropertiesDictionary = new RequestPropertiesDictionary();
- private ResponsePropertiesDictionary responsePropertiesDictionary = new ResponsePropertiesDictionary();
+ private QueryDictionary parameters = new QueryDictionary();
+ private QueryDictionary requestHeaders = new QueryDictionary();
+ private QueryDictionary responseHeaders = new QueryDictionary();
private int status = 0;
private volatile long bytesExpected = -1;
@@ -258,11 +266,12 @@
try {
locationContext = new URL(secure ? HTTPS_PROTOCOL : HTTP_PROTOCOL,
- hostname, port, path);
+ hostname, port, path);
} catch (MalformedURLException exception) {
- throw new IllegalArgumentException("Unable to construct context URL.",
- exception);
+ throw new IllegalArgumentException(
+ "Unable to construct context URL.", exception);
}
+
}
public abstract Method getMethod();
@@ -295,30 +304,38 @@
public URL getLocation() {
StringBuilder queryStringBuilder = new StringBuilder();
- for (String key : arguments) {
- try {
- if (queryStringBuilder.length() > 0) {
- queryStringBuilder.append("&");
- }
+ for (String key : parameters) {
+
+ for (int index = 0; index < parameters.getLength(key); index++) {
+ try {
+ if (queryStringBuilder.length() > 0) {
+ queryStringBuilder.append("&");
+ }
- queryStringBuilder.append(URLEncoder.encode(key, URL_ENCODING)
- + "=" + URLEncoder.encode(arguments.get(key), URL_ENCODING));
- } catch (UnsupportedEncodingException exception) {
- throw new IllegalStateException("Unable to construct query string.", exception);
+ queryStringBuilder.append(URLEncoder.encode(key,
+ URL_ENCODING)
+ + "="
+ + URLEncoder.encode(parameters.get(key, index),
+ URL_ENCODING));
+ } catch (UnsupportedEncodingException exception) {
+ throw new IllegalStateException(
+ "Unable to construct query string.", exception);
+ }
}
}
URL location = null;
try {
- String queryString = queryStringBuilder.length() > 0 ?
- "?" + queryStringBuilder.toString() : "";
+ String queryString = queryStringBuilder.length() > 0 ? "?"
+ + queryStringBuilder.toString() : "";
- location = new URL(locationContext.getProtocol(),
- locationContext.getHost(),
- locationContext.getPort(),
- locationContext.getPath() + queryString);
+ location = new URL(locationContext.getProtocol(), locationContext
+ .getHost(), locationContext.getPort(), locationContext
+ .getPath()
+ + queryString);
} catch (MalformedURLException exception) {
- throw new IllegalStateException("Unable to construct query URL.", exception);
+ throw new IllegalStateException("Unable to construct query URL.",
+ exception);
}
return location;
@@ -328,50 +345,70 @@
* Returns the web query's arguments dictionary. Arguments are passed via
* the query string of the web query's URL.
*/
- public ArgumentsDictionary getArguments() {
- return argumentsDictionary;
+ public QueryDictionary getParameters() {
+ return parameters;
}
/**
* Returns the web query's request property dictionary. Request properties
* are passed via HTTP headers when the query is executed.
*/
- public RequestPropertiesDictionary getRequestProperties() {
- return requestPropertiesDictionary;
+ public QueryDictionary getRequestHeaders() {
+ return requestHeaders;
}
/**
* Returns the web query's response property dictionary. Response properties
* are returned via HTTP headers when the query is executed.
*/
- public ResponsePropertiesDictionary getResponseProperties() {
- return responsePropertiesDictionary;
+ public QueryDictionary getResponseHeaders() {
+ return responseHeaders;
+ }
+
+ /**
+ * @deprecated use {@link #getParameters()} instead
+ */
+ public QueryDictionary getArguments() {
+ return parameters;
+ }
+
+ /**
+ * @deprecated use {@link #getRequestHeaders()} instead
+ */
+ public QueryDictionary getRequestProperties() {
+ return requestHeaders;
+ }
+
+ /**
+ * @deprecated use {@link #getResponseHeaders()} instead
+ */
+ public QueryDictionary getResponseProperties() {
+ return responseHeaders;
}
/**
* Returns the status of the most recent execution.
*
- * @return
- * An HTTP code representing the most recent execution status.
+ * @return An HTTP code representing the most recent execution status.
*/
public int getStatus() {
return status;
}
/**
- * Returns the serializer used to stream the value passed to or from the
- * web query. By default, an instance of {@link JSONSerializer} is used.
+ * Returns the serializer used to stream the value passed to or from the web
+ * query. By default, an instance of {@link JSONSerializer} is used.
*/
public Serializer<?> getSerializer() {
return serializer;
}
/**
- * Sets the serializer used to stream the value passed to or from the
- * web query.
+ * Sets the serializer used to stream the value passed to or from the web
+ * query.
*
* @param serializer
- * The serializer (must be non-null).
+ * The serializer (must be non-null).
*/
public void setSerializer(Serializer<?> serializer) {
if (serializer == null) {
@@ -382,9 +419,9 @@
}
/**
- * Gets the number of bytes that have been sent in the body of this
- * query's HTTP request. This will only be non-zero for POST and PUT
- * requests, as GET and DELETE requests send no content to the server.
+ * Gets the number of bytes that have been sent in the body of this query's
+ * HTTP request. This will only be non-zero for POST and PUT requests, as
+ * GET and DELETE requests send no content to the server.
* <p>
* For POST and PUT requests, this number will increment in between the
* {@link QueryListener#connected(Query) connected} and
@@ -413,9 +450,9 @@
}
/**
- * Gets the number of bytes that are expected to be received from the
- * server in the body of the server's HTTP response. This value reflects
- * the <tt>Content-Length</tt> HTTP response header and is thus merely an
+ * Gets the number of bytes that are expected to be received from the server
+ * in the body of the server's HTTP response. This value reflects the
+ * <tt>Content-Length</tt> HTTP response header and is thus merely an
* expectation. The actual total number of bytes that will be received is
* not known for certain until the full response has been received.
* <p>
@@ -428,12 +465,11 @@
}
@SuppressWarnings("unchecked")
- protected Object execute(Method method, Object value)
- throws QueryException {
+ protected Object execute(Method method, Object value) throws QueryException {
URL location = getLocation();
HttpURLConnection connection = null;
- Serializer<Object> serializer = (Serializer<Object>)this.serializer;
+ Serializer<Object> serializer = (Serializer<Object>) this.serializer;
bytesSent = 0;
bytesReceived = 0;
@@ -444,32 +480,37 @@
try {
// Clear any properties from a previous response
- responseProperties.clear();
+ responseHeaders.clear();
// Open a connection
- connection = (HttpURLConnection)location.openConnection();
+ connection = (HttpURLConnection) location.openConnection();
connection.setRequestMethod(method.toString());
connection.setAllowUserInteraction(false);
connection.setInstanceFollowRedirects(false);
connection.setUseCaches(false);
if (connection instanceof HttpsURLConnection
- && hostnameVerifier != null) {
- HttpsURLConnection httpsConnection = (HttpsURLConnection)connection;
+ && hostnameVerifier != null) {
+ HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
httpsConnection.setHostnameVerifier(hostnameVerifier);
}
// Set the request headers
if (method == Method.POST || method == Method.PUT) {
- connection.setRequestProperty("Content-Type", serializer.getMIMEType(value));
+ connection.setRequestProperty("Content-Type", serializer
+ .getMIMEType(value));
}
- for (String key : requestProperties) {
- connection.setRequestProperty(key, requestProperties.get(key));
+ for (String key : requestHeaders) {
+ for (int index = 0; index < requestHeaders.getLength(key); index++) {
+ connection.setRequestProperty(key, requestHeaders.get(key,
+ index));
+ }
}
// Set the input/output state
connection.setDoInput(true);
- connection.setDoOutput(method == Method.POST || method == Method.PUT);
+ connection.setDoOutput(method == Method.POST
+ || method == Method.PUT);
// Connect to the server
connection.connect();
@@ -480,7 +521,8 @@
OutputStream outputStream = null;
try {
outputStream = connection.getOutputStream();
- serializer.writeObject(value, new MonitoredOutputStream(outputStream));
+ serializer.writeObject(value, new MonitoredOutputStream(
+ outputStream));
} finally {
if (outputStream != null) {
outputStream.close();
@@ -506,10 +548,9 @@
// NOTE Header indexes start at 1, not 0
int i = 1;
- for (String key = connection.getHeaderFieldKey(i);
- key != null;
- key = connection.getHeaderFieldKey(++i)) {
- responseProperties.put(key, connection.getHeaderField(i));
+ for (String key = connection.getHeaderFieldKey(i); key != null; key = connection
+ .getHeaderFieldKey(++i)) {
+ responseHeaders.add(key, connection.getHeaderField(i));
}
// Read the response body
@@ -517,7 +558,8 @@
InputStream inputStream = null;
try {
inputStream = connection.getInputStream();
- value = serializer.readObject(new MonitoredInputStream(inputStream));
+ value = serializer.readObject(new MonitoredInputStream(
+ inputStream));
} finally {
if (inputStream != null) {
inputStream.close();
Added: incubator/pivot/trunk/web/test/pivot/web/QueryDictionaryTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/web/test/pivot/web/QueryDictionaryTest.java?rev=778203&view=auto
==============================================================================
--- incubator/pivot/trunk/web/test/pivot/web/QueryDictionaryTest.java (added)
+++ incubator/pivot/trunk/web/test/pivot/web/QueryDictionaryTest.java Sun May 24 18:01:42 2009
@@ -0,0 +1,85 @@
+package pivot.web;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+import pivot.web.Query.QueryDictionary;
+
+public class QueryDictionaryTest extends TestCase {
+
+ @SuppressWarnings("unchecked")
+ public void testQueryDictionary() {
+ GetQuery query = new GetQuery("localhost", "path");
+ QueryDictionary dict = query.new QueryDictionary();
+
+ assertNull(dict.get("key"));
+
+ dict.put("key", "value");
+ assertNotNull(dict.get("key"));
+
+ assertEquals("value", dict.get("key", 0));
+
+ assertEquals(1, dict.getLength("key"));
+
+ try {
+ dict.get("key", 1);
+ fail("Expected IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException ex) {
+ }
+
+ assertEquals("value", dict.put("key", "value2"));
+ assertEquals("value2", dict.get("key"));
+
+ dict.add("key", "another value");
+
+ assertEquals("another value", dict.get("key", 1));
+
+ assertEquals(0, dict.getLength("nokey"));
+
+ assertEquals(0, dict.add("key2", "new value"));
+
+ dict.insert("key", "yet another value", 0);
+
+ assertEquals(3, dict.getLength("key"));
+
+ try {
+ dict.insert("key", "bad value", 10);
+ fail("Expected IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException ex) {
+
+ }
+
+ assertEquals("yet another value", dict.remove("key"));
+ assertNull(dict.remove("key"));
+
+ dict.add("key2", "2nd value");
+ assertEquals("new value", dict.remove("key2", 0));
+
+ try {
+ dict.remove("key2", 10);
+ fail("Expected IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException ex) {
+
+ }
+
+ dict.add("key3", "something");
+
+ Set<String> validKeys = new HashSet<String>();
+ validKeys.add("key2");
+ validKeys.add("key3");
+
+ for (String s : (Iterable<String>) dict) {
+ assertTrue(s, validKeys.remove(s));
+ }
+
+ assertEquals(0, validKeys.size());
+
+ assertTrue(dict.containsKey("key2"));
+ assertFalse(dict.isEmpty());
+
+ dict.clear();
+ assertTrue(dict.isEmpty());
+
+ }
+}
Modified: incubator/pivot/trunk/web/test/pivot/web/test/WebQueryTestClient.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/web/test/pivot/web/test/WebQueryTestClient.java?rev=778203&r1=778202&r2=778203&view=diff
==============================================================================
--- incubator/pivot/trunk/web/test/pivot/web/test/WebQueryTestClient.java (original)
+++ incubator/pivot/trunk/web/test/pivot/web/test/WebQueryTestClient.java Sun May 24 18:01:42 2009
@@ -42,7 +42,7 @@
// GET
final GetQuery getQuery = new GetQuery(HOSTNAME, PORT, PATH, SECURE);
- getQuery.getArguments().put("a", "b");
+ getQuery.getParameters().put("a", "b");
getQuery.setSerializer(new BinarySerializer());
authentication.authenticate(getQuery);