fixed error parsing in azure

This commit is contained in:
Adrian Cole 2010-11-06 10:49:58 +01:00
parent 0c690f686f
commit 63ca8c1e96
4 changed files with 42 additions and 26 deletions

View File

@ -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);

View File

@ -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", "<HTML><HEAD><TITLE>Length Required</TITLE>\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", "<?xml version=\"1.0\" encoding=\"utf-8\"?><Error><Code>ConditionNotMet</Code><Message>The condition specified using HTTP conditional header(s) is not met.\nRequestId:921efcad-84bc-4e0a-863d-24810d1096e1\nTime:2010-11-04T15:03:07.8694513Z</Message></Error>",
AzureStorageResponseException.class);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
String content, Class<? extends Exception> expected) {

View File

@ -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> T proxy(Class<T> 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<ClassMethodArgs, Object> delegateMap, Map<Class<?>, Class<?>> sync2Async)
throws SecurityException, NoSuchMethodException {
@Named("sync") ConcurrentMap<ClassMethodArgs, Object> delegateMap, Map<Class<?>, 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;
}

View File

@ -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 <T> back to the
@ -52,8 +51,6 @@ public class ParseSax<T> implements Function<HttpResponse, T>, InvocationContext
private final XMLReader parser;
private final HandlerWithResult<T> handler;
@Resource
protected Logger logger = Logger.NULL;
private HttpRequest request;
public static interface Factory {
@ -71,7 +68,7 @@ public class ParseSax<T> implements Function<HttpResponse, T>, 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<T> implements Function<HttpResponse, T>, 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<T> implements Function<HttpResponse, T>, 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<T> implements Function<HttpResponse, T>, 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<T> getHandler() {