diff --git a/azure/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java b/azure/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java
index cf0cbd58ce..6a165e8dcd 100644
--- a/azure/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java
+++ b/azure/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java
@@ -89,7 +89,6 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
exception = new AuthorizationException(command.getRequest(), message);
break;
case 404:
-
if (!command.getRequest().getMethod().equals("DELETE")) {
String path = command.getRequest().getEndpoint().getPath();
Matcher matcher = CONTAINER_PATH.matcher(path);
diff --git a/azure/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java b/azure/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java
index 5f19192af7..8600120f44 100644
--- a/azure/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java
+++ b/azure/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java
@@ -28,6 +28,7 @@ import static org.easymock.classextension.EasyMock.verify;
import java.net.URI;
import org.easymock.IArgumentMatcher;
+import org.jclouds.azure.storage.AzureStorageResponseException;
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
@@ -54,6 +55,14 @@ public class ParseAzureErrorFromXmlContentTest {
"Length Required", "text/html; charset=us-ascii", "
Length Required\r\n",
IllegalArgumentException.class);
}
+
+ @Test
+ public void test412WithTextHtmlHttpResponseException() {
+ assertCodeMakes("GET", URI
+ .create("https://jclouds.blob.core.windows.net/adriancole-blobstore2?restype=container&comp=list&prefix=apps/apps/apps/&include=metadata"), 412,
+ "HTTP/1.1 412 The condition specified using HTTP conditional header(s) is not met.", "application/xml", "ConditionNotMet
The condition specified using HTTP conditional header(s) is not met.\nRequestId:921efcad-84bc-4e0a-863d-24810d1096e1\nTime:2010-11-04T15:03:07.8694513Z",
+ AzureStorageResponseException.class);
+ }
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
String content, Class extends Exception> expected) {
diff --git a/core/src/main/java/org/jclouds/concurrent/internal/SyncProxy.java b/core/src/main/java/org/jclouds/concurrent/internal/SyncProxy.java
index fa5e52477e..9594a7ecff 100644
--- a/core/src/main/java/org/jclouds/concurrent/internal/SyncProxy.java
+++ b/core/src/main/java/org/jclouds/concurrent/internal/SyncProxy.java
@@ -35,6 +35,7 @@ import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.concurrent.Timeout;
+import org.jclouds.http.HttpResponseException;
import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
@@ -57,7 +58,7 @@ public class SyncProxy implements InvocationHandler {
@SuppressWarnings("unchecked")
public static T proxy(Class clazz, SyncProxy proxy) throws IllegalArgumentException, SecurityException,
- NoSuchMethodException {
+ NoSuchMethodException {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class>[] { clazz }, proxy);
}
@@ -72,8 +73,8 @@ public class SyncProxy implements InvocationHandler {
@Inject
public SyncProxy(Class> declaring, Object async,
- @Named("sync") ConcurrentMap delegateMap, Map, Class>> sync2Async)
- throws SecurityException, NoSuchMethodException {
+ @Named("sync") ConcurrentMap delegateMap, Map, Class>> sync2Async)
+ throws SecurityException, NoSuchMethodException {
this.delegateMap = delegateMap;
this.delegate = async;
this.declaring = declaring;
@@ -92,7 +93,7 @@ public class SyncProxy implements InvocationHandler {
Method delegatedMethod = delegate.getClass().getMethod(method.getName(), method.getParameterTypes());
if (!Arrays.equals(delegatedMethod.getExceptionTypes(), method.getExceptionTypes()))
throw new IllegalArgumentException(String.format(
- "method %s has different typed exceptions than delegated method %s", method, delegatedMethod));
+ "method %s has different typed exceptions than delegated method %s", method, delegatedMethod));
if (delegatedMethod.getReturnType().isAssignableFrom(ListenableFuture.class)) {
if (method.isAnnotationPresent(Timeout.class)) {
Timeout methodTimeout = method.getAnnotation(Timeout.class);
@@ -124,7 +125,7 @@ public class SyncProxy implements InvocationHandler {
} else if (method.isAnnotationPresent(Delegate.class)) {
Class> asyncClass = sync2Async.get(method.getReturnType());
checkState(asyncClass != null, "please configure corresponding async class for " + method.getReturnType()
- + " in your RestClientModule");
+ + " in your RestClientModule");
Object returnVal = delegateMap.get(new ClassMethodArgs(asyncClass, method, args));
return returnVal;
} else if (syncMethodMap.containsKey(method)) {
@@ -132,7 +133,7 @@ public class SyncProxy implements InvocationHandler {
} else {
try {
return ((ListenableFuture>) methodMap.get(method).invoke(delegate, args)).get(timeoutMap.get(method),
- TimeUnit.NANOSECONDS);
+ TimeUnit.NANOSECONDS);
} catch (ProvisionException e) {
throw throwTypedExceptionOrCause(method.getExceptionTypes(), e);
} catch (ExecutionException e) {
@@ -143,6 +144,7 @@ public class SyncProxy implements InvocationHandler {
}
}
+ // Note this needs to be kept up-to-date with all top-level exceptions jclouds works against
@SuppressWarnings("unchecked")
public static Exception throwTypedExceptionOrCause(Class[] exceptionTypes, Exception exception) throws Exception {
for (Class type : exceptionTypes) {
@@ -154,6 +156,7 @@ public class SyncProxy implements InvocationHandler {
Throwables.propagateIfInstanceOf(exception, IllegalStateException.class);
Throwables.propagateIfInstanceOf(exception, AuthorizationException.class);
Throwables.propagateIfInstanceOf(exception, ResourceNotFoundException.class);
+ Throwables.propagateIfInstanceOf(exception, HttpResponseException.class);
Throwables.throwCause(exception, true);
return exception;
}
diff --git a/core/src/main/java/org/jclouds/http/functions/ParseSax.java b/core/src/main/java/org/jclouds/http/functions/ParseSax.java
index cb2045e2c1..d313e468ca 100644
--- a/core/src/main/java/org/jclouds/http/functions/ParseSax.java
+++ b/core/src/main/java/org/jclouds/http/functions/ParseSax.java
@@ -26,12 +26,10 @@ import static com.google.common.io.Closeables.closeQuietly;
import java.io.InputStream;
import java.io.StringReader;
-import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
-import org.jclouds.logging.Logger;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.Utils;
@@ -41,6 +39,7 @@ import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import com.google.common.base.Function;
+import com.google.common.base.Throwables;
/**
* This object will parse the body of an HttpResponse and return the result of type back to the
@@ -52,8 +51,6 @@ public class ParseSax implements Function, InvocationContext
private final XMLReader parser;
private final HandlerWithResult handler;
- @Resource
- protected Logger logger = Logger.NULL;
private HttpRequest request;
public static interface Factory {
@@ -71,7 +68,7 @@ public class ParseSax implements Function, InvocationContext
checkNotNull(from, "http response");
checkNotNull(from.getPayload(), "payload in " + from);
} catch (NullPointerException e) {
- return addRequestDetailsToException(e);
+ return addDetailsAndPropagate(from, e);
}
if (from.getStatusCode() >= 300)
return convertStreamToStringAndParse(from);
@@ -82,7 +79,7 @@ public class ParseSax implements Function, InvocationContext
try {
return parse(Utils.toStringAndClose(from.getPayload().getInput()));
} catch (Exception e) {
- return addRequestDetailsToException(e);
+ return addDetailsAndPropagate(from, e);
}
}
@@ -91,7 +88,7 @@ public class ParseSax implements Function, InvocationContext
checkNotNull(from, "xml string");
checkArgument(from.indexOf('<') >= 0, String.format("not an xml document [%s] ", from));
} catch (RuntimeException e) {
- return addRequestDetailsToException(e);
+ return addDetailsAndPropagate(null, e);
}
return parse(new InputSource(new StringReader(from)));
}
@@ -113,31 +110,39 @@ public class ParseSax implements Function, InvocationContext
parser.parse(from);
return getHandler().getResult();
} catch (Exception e) {
- return addRequestDetailsToException(e);
+ return addDetailsAndPropagate(null, e);
}
}
- private T addRequestDetailsToException(Exception e) {
- String exceptionMessage = e.getMessage();
+ public T addDetailsAndPropagate(HttpResponse response, Exception e) {
+ StringBuilder message = new StringBuilder();
+ if (request != null) {
+ message.append("request: ").append(request.getRequestLine());
+ }
+ if (response != null) {
+ if (message.length() != 0)
+ message.append("; ");
+ message.append("response: ").append(response.getStatusLine());
+ }
if (e instanceof SAXParseException) {
SAXParseException parseException = (SAXParseException) e;
String systemId = parseException.getSystemId();
if (systemId == null) {
systemId = "";
}
- exceptionMessage = String.format("Error on line %d of document %s: %s", systemId, parseException
- .getLineNumber(), parseException.getMessage());
+ if (message.length() != 0)
+ message.append("; ");
+ message.append(String.format("error at %d:%d in document %s", parseException.getColumnNumber(),
+ parseException.getLineNumber(), systemId));
}
- if (request != null) {
- StringBuilder message = new StringBuilder();
- message.append("Error parsing input for ").append(request.getRequestLine()).append(": ");
- message.append(exceptionMessage);
- logger.error(e, message.toString());
+ if (message.length() != 0) {
+ message.append("; cause: ").append(e.toString());
throw new RuntimeException(message.toString(), e);
} else {
- logger.error(e, exceptionMessage.toString());
- throw new RuntimeException(exceptionMessage.toString(), e);
+ Throwables.propagate(e);
+ return null;
}
+
}
public HandlerWithResult getHandler() {