diff --git a/pom.xml b/pom.xml
index 3638e84..3bd8b3d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
com.ciscospark
ciscospark-client
- 1.0-SNAPSHOT
+ 1.0-elibra.0
diff --git a/src/main/java/com/ciscospark/Client.java b/src/main/java/com/ciscospark/Client.java
index 69f6ca2..accd6ec 100644
--- a/src/main/java/com/ciscospark/Client.java
+++ b/src/main/java/com/ciscospark/Client.java
@@ -12,6 +12,8 @@
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.net.*;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.security.SecureRandom;
import javax.net.ssl.HttpsURLConnection;
@@ -85,6 +87,15 @@ Iterator list(Class clazz, URL url) {
return new PagingIterator(clazz, url);
}
+ T head(Class clazz, String path, List params){
+ return readHeaders(clazz, requestHeaders("HEAD", path, params, null));
+ }
+
+ T head(Class clazz, URL url){
+ return readHeaders(clazz, request(url, "HEAD", null).connection.getHeaderFields());
+ }
+
+
void delete(String path) {
delete(getUrl(path, null));
}
@@ -135,6 +146,14 @@ InputStream request(String method, String path, List params, T bod
URL url = getUrl(path, params);
return request(url, method, body).inputStream;
}
+
+ Map> requestHeaders(String method, String path, List params, T body) {
+ URL url = getUrl(path, params);
+ return request(url, method, body).connection.getHeaderFields();
+ }
+
+
+
static class Response {
HttpsURLConnection connection;
InputStream inputStream;
@@ -167,7 +186,7 @@ private boolean authenticate() {
if (clientId != null && clientSecret != null) {
if (authCode != null && redirectUri != null) {
log(Level.FINE, "Requesting access token");
- URL url = getUrl("/access_token",null);
+ URL url = getUrl("/access_token", null);
AccessTokenRequest body = new AccessTokenRequest();
body.setGrant_type("authorization_code");
body.setClient_id(clientId);
@@ -182,7 +201,7 @@ private boolean authenticate() {
return true;
} else if (refreshToken != null) {
log(Level.FINE, "Refreshing access token");
- URL url = getUrl("/access_token",null);
+ URL url = getUrl("/access_token", null);
AccessTokenRequest body = new AccessTokenRequest();
body.setClient_id(clientId);
body.setClient_secret(clientSecret);
@@ -202,15 +221,18 @@ private void log(Level level, String msg, Object... args) {
logger.log(level, msg, args);
}
}
-
private Response doRequest(URL url, String method, T body) {
+ return doRequest(url, method, body, 0);
+ }
+
+ private Response doRequest(URL url, String method, T body, int retryNumber) {
try {
HttpsURLConnection connection = getConnection(url);
String trackingId = connection.getRequestProperty(TRACKING_ID);
connection.setRequestMethod(method);
if (logger != null && logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Request {0}: {1} {2}",
- new Object[] { trackingId, method, connection.getURL().toString() });
+ new Object[]{trackingId, method, connection.getURL().toString()});
}
if (body != null) {
connection.setDoOutput(true);
@@ -218,7 +240,7 @@ private Response doRequest(URL url, String method, T body) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
writeJson(body, byteArrayOutputStream);
logger.log(Level.FINEST, "Request Body {0}: {1}",
- new Object[] { trackingId, byteArrayOutputStream.toString() });
+ new Object[]{trackingId, byteArrayOutputStream.toString()});
byteArrayOutputStream.writeTo(connection.getOutputStream());
} else {
writeJson(body, connection.getOutputStream());
@@ -228,9 +250,23 @@ private Response doRequest(URL url, String method, T body) {
int responseCode = connection.getResponseCode();
if (logger != null && logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Response {0}: {1} {2}",
- new Object[] { trackingId, responseCode, connection.getResponseMessage() });
+ new Object[]{trackingId, responseCode, connection.getResponseMessage()});
+ }
+ if (responseCode == 429) {
+ if(retryNumber>5)
+ throw new RuntimeException("Too many retry after HTTP response 429");
+
+ // retry based of Retry-After response header
+ final String retryAfter = connection.getHeaderField("Retry-After");
+ try {
+ Thread.sleep(Long.parseLong(retryAfter));
+ return doRequest(url, method, body, retryNumber+1);
+ } catch (InterruptedException e) {
+ log(Level.SEVERE, e.getMessage());
+ }
+ } else {
+ checkForErrorResponse(connection, responseCode);
}
- checkForErrorResponse(connection, responseCode);
if (logger != null && logger.isLoggable(Level.FINEST)) {
InputStream inputStream = logResponse(trackingId, connection.getInputStream());
@@ -337,6 +373,25 @@ private HttpsURLConnection getConnection(URL url) throws IOException {
}
+ private static T readHeaders(Class clazz, Map> headerFields){
+ try{
+ T result = clazz.newInstance();
+ for (Field field : clazz.getDeclaredFields()){
+ field.setAccessible(true);
+ Object fieldObject = field.get(result);
+ if (fieldObject instanceof HeaderField &&
+ headerFields.containsKey(((HeaderField) fieldObject).getHeaderName())){
+ ((HeaderField) fieldObject).setHeaderValue(headerFields.get(((HeaderField) fieldObject).getHeaderName()));
+ }
+ }
+ return result;
+ } catch (Exception ex) {
+ throw new SparkException(ex);
+ }
+ }
+
+
+
private static T readJson(Class clazz, InputStream inputStream) {
JsonParser parser = Json.createParser(inputStream);
parser.next();
@@ -349,7 +404,8 @@ private static T readObject(Class clazz, JsonParser parser) {
List