From 9aced88ca1f216e66831cde9e2915edc91bc3790 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sun, 19 Sep 2010 10:22:09 -0700 Subject: [PATCH] fixed error handling on vcloud and renamed bluelock-vclouddirector to bluelock-vcdirector --- vcloud/bluelock/pom.xml | 24 +++--- .../BlueLockVCloudDirectorClientLiveTest.java | 10 +-- ...oudDirectorGuestCustomizationLiveTest.java | 10 +-- .../bluelock/ProvidersInPropertiesTest.java | 4 +- .../VCloudSessionRefreshLiveTest.java | 8 +- ...kVCloudDirectorComputeServiceLiveTest.java | 10 +-- vcloud/core/pom.xml | 6 +- .../org/jclouds/vcloud/VCloudMediaType.java | 10 +++ .../vcloud/VCloudResponseException.java | 74 +++++++++++++++++ .../java/org/jclouds/vcloud/domain/Task.java | 2 +- .../domain/{Error.java => VCloudError.java} | 15 +++- .../vcloud/domain/internal/ErrorImpl.java | 12 +-- .../vcloud/domain/internal/TaskImpl.java | 8 +- .../ParseVCloudErrorFromHttpResponse.java | 81 ++++++++++++------- .../java/org/jclouds/vcloud/util/Utils.java | 16 ++-- .../org/jclouds/vcloud/util/VCloudUtils.java | 68 ++++++++++++++++ .../org/jclouds/vcloud/xml/ErrorHandler.java | 49 +++++++++++ .../org/jclouds/vcloud/xml/TaskHandler.java | 4 +- .../jclouds/vcloud/VCloudLoginLiveTest.java | 6 +- .../vcloud/VCloudVersionsLiveTest.java | 6 +- .../jclouds/vcloud/xml/TaskHandlerTest.java | 7 +- vcloud/terremark/pom.xml | 50 ++++++------ 22 files changed, 356 insertions(+), 124 deletions(-) create mode 100644 vcloud/core/src/main/java/org/jclouds/vcloud/VCloudResponseException.java rename vcloud/core/src/main/java/org/jclouds/vcloud/domain/{Error.java => VCloudError.java} (88%) create mode 100644 vcloud/core/src/main/java/org/jclouds/vcloud/util/VCloudUtils.java create mode 100644 vcloud/core/src/main/java/org/jclouds/vcloud/xml/ErrorHandler.java diff --git a/vcloud/bluelock/pom.xml b/vcloud/bluelock/pom.xml index 234dfe213f..59f6d562c1 100644 --- a/vcloud/bluelock/pom.xml +++ b/vcloud/bluelock/pom.xml @@ -35,10 +35,10 @@ - https://vcenterprise.bluelock.com/api - 1.0 - FIXME - FIXME + https://vcenterprise.bluelock.com/api + 1.0 + FIXME + FIXME @@ -79,20 +79,20 @@ - bluelock-vclouddirector.endpoint - ${bluelock-vclouddirector.endpoint} + bluelock-vcdirector.endpoint + ${bluelock-vcdirector.endpoint} - bluelock-vclouddirector.apiversion - ${bluelock-vclouddirector.apiversion} + bluelock-vcdirector.apiversion + ${bluelock-vcdirector.apiversion} - bluelock-vclouddirector.identity - ${bluelock-vclouddirector.identity} + bluelock-vcdirector.identity + ${bluelock-vcdirector.identity} - bluelock-vclouddirector.credential - ${bluelock-vclouddirector.credential} + bluelock-vcdirector.credential + ${bluelock-vcdirector.credential} jclouds.compute.blacklist.nodes diff --git a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/BlueLockVCloudDirectorClientLiveTest.java b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/BlueLockVCloudDirectorClientLiveTest.java index 929c25059a..76c3d537f0 100644 --- a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/BlueLockVCloudDirectorClientLiveTest.java +++ b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/BlueLockVCloudDirectorClientLiveTest.java @@ -43,11 +43,11 @@ public class BlueLockVCloudDirectorClientLiveTest extends VCloudClientLiveTest { @BeforeGroups(groups = { "live" }) @Override public void setupClient() { - identity = checkNotNull(System.getProperty("bluelock-vclouddirector.identity"), - "bluelock-vclouddirector.identity"); - String credential = checkNotNull(System.getProperty("bluelock-vclouddirector.credential"), - "bluelock-vclouddirector.credential"); - context = new ComputeServiceContextFactory().createContext("bluelock-vclouddirector", identity, credential, ImmutableSet + identity = checkNotNull(System.getProperty("bluelock-vcdirector.identity"), + "bluelock-vcdirector.identity"); + String credential = checkNotNull(System.getProperty("bluelock-vcdirector.credential"), + "bluelock-vcdirector.credential"); + context = new ComputeServiceContextFactory().createContext("bluelock-vcdirector", identity, credential, ImmutableSet . of(new Log4JLoggingModule()), new Properties()).getProviderSpecificContext(); connection = context.getApi(); } diff --git a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/BlueLockVCloudDirectorGuestCustomizationLiveTest.java b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/BlueLockVCloudDirectorGuestCustomizationLiveTest.java index 71a97aed3f..7f0f854497 100644 --- a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/BlueLockVCloudDirectorGuestCustomizationLiveTest.java +++ b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/BlueLockVCloudDirectorGuestCustomizationLiveTest.java @@ -34,11 +34,11 @@ public class BlueLockVCloudDirectorGuestCustomizationLiveTest extends VCloudGues @Override protected void setupCredentials() { - provider = "bluelock-vclouddirector"; - identity = checkNotNull(System.getProperty("bluelock-vclouddirector.identity"), - "bluelock-vclouddirector.identity"); - credential = checkNotNull(System.getProperty("bluelock-vclouddirector.credential"), - "bluelock-vclouddirector.credential"); + provider = "bluelock-vcdirector"; + identity = checkNotNull(System.getProperty("bluelock-vcdirector.identity"), + "bluelock-vcdirector.identity"); + credential = checkNotNull(System.getProperty("bluelock-vcdirector.credential"), + "bluelock-vcdirector.credential"); } } \ No newline at end of file diff --git a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/ProvidersInPropertiesTest.java b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/ProvidersInPropertiesTest.java index cf2f3367a1..263e76fb08 100644 --- a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/ProvidersInPropertiesTest.java +++ b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/ProvidersInPropertiesTest.java @@ -36,14 +36,14 @@ public class ProvidersInPropertiesTest { @Test public void testSupportedProviders() { Iterable providers = Utils.getSupportedProviders(); - assert Iterables.contains(providers, "bluelock-vclouddirector") : providers; + assert Iterables.contains(providers, "bluelock-vcdirector") : providers; } @Test public void testSupportedComputeServiceProviders() { Iterable providers = ComputeServiceUtils.getSupportedProviders(); - assert Iterables.contains(providers, "bluelock-vclouddirector") : providers; + assert Iterables.contains(providers, "bluelock-vcdirector") : providers; } } diff --git a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/VCloudSessionRefreshLiveTest.java b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/VCloudSessionRefreshLiveTest.java index 5000bcdc40..7542adba5d 100644 --- a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/VCloudSessionRefreshLiveTest.java +++ b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/VCloudSessionRefreshLiveTest.java @@ -60,14 +60,14 @@ public class VCloudSessionRefreshLiveTest { @BeforeGroups(groups = { "live" }) public void setupClient() throws IOException { - identity = checkNotNull(System.getProperty("bluelock-vclouddirector.identity"), "bluelock-vclouddirector.identity"); - String credential = checkNotNull(System.getProperty("bluelock-vclouddirector.credential"), - "bluelock-vclouddirector.credential"); + identity = checkNotNull(System.getProperty("bluelock-vcdirector.identity"), "bluelock-vcdirector.identity"); + String credential = checkNotNull(System.getProperty("bluelock-vcdirector.credential"), + "bluelock-vcdirector.credential"); Properties props = new Properties(); props.setProperty(PROPERTY_SESSION_INTERVAL, 40 + ""); - context = new ComputeServiceContextFactory().createContext("bluelock-vclouddirector", identity, credential, + context = new ComputeServiceContextFactory().createContext("bluelock-vcdirector", identity, credential, ImmutableSet. of(new Log4JLoggingModule()), props); connection = VCloudClient.class.cast(context.getProviderSpecificContext().getApi()); diff --git a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/compute/BlueLockVCloudDirectorComputeServiceLiveTest.java b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/compute/BlueLockVCloudDirectorComputeServiceLiveTest.java index 0f6a6ce9dd..8b68be5050 100644 --- a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/compute/BlueLockVCloudDirectorComputeServiceLiveTest.java +++ b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/compute/BlueLockVCloudDirectorComputeServiceLiveTest.java @@ -40,16 +40,16 @@ import org.testng.annotations.Test; public class BlueLockVCloudDirectorComputeServiceLiveTest extends VCloudComputeServiceLiveTest { @Override public void setServiceDefaults() { - provider = "bluelock-vclouddirector"; + provider = "bluelock-vcdirector"; tag = "director"; } @Override protected void setupCredentials() { - identity = checkNotNull(System.getProperty("bluelock-vclouddirector.identity"), - "bluelock-vclouddirector.identity"); - credential = checkNotNull(System.getProperty("bluelock-vclouddirector.credential"), - "bluelock-vclouddirector.credential"); + identity = checkNotNull(System.getProperty("bluelock-vcdirector.identity"), + "bluelock-vcdirector.identity"); + credential = checkNotNull(System.getProperty("bluelock-vcdirector.credential"), + "bluelock-vcdirector.credential"); } @Test diff --git a/vcloud/core/pom.xml b/vcloud/core/pom.xml index 198eca48f4..910d7c0251 100644 --- a/vcloud/core/pom.xml +++ b/vcloud/core/pom.xml @@ -31,9 +31,9 @@ jclouds vcloud Components Core jclouds Core components to access vcloud - ${jclouds.vcloud.user} - ${jclouds.vcloud.password} - ${jclouds.vcloud.endpoint} + ${jclouds.vcloud.user} + ${jclouds.vcloud.password} + ${jclouds.vcloud.endpoint} diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/VCloudMediaType.java b/vcloud/core/src/main/java/org/jclouds/vcloud/VCloudMediaType.java index fbb6c95f20..83e6fbb0c8 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/VCloudMediaType.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/VCloudMediaType.java @@ -27,6 +27,16 @@ import javax.ws.rs.core.MediaType; * @see MediaType */ public interface VCloudMediaType { + /** + * "application/vnd.vmware.vcloud.error+xml" + */ + public final static String ERROR_XML = "application/vnd.vmware.vcloud.error+xml"; + + /** + * "application/vnd.vmware.vcloud.error+xml" + */ + public final static MediaType ERROR_XML_TYPE = new MediaType("application", "vnd.vmware.vcloud.error+xml"); + /** * "application/vnd.vmware.vcloud.vcloud+xml" */ diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/VCloudResponseException.java b/vcloud/core/src/main/java/org/jclouds/vcloud/VCloudResponseException.java new file mode 100644 index 0000000000..b0081c2c8d --- /dev/null +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/VCloudResponseException.java @@ -0,0 +1,74 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.vcloud; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.vcloud.domain.VCloudError; + +/** + * Encapsulates an VCloud Error. + * + * @author Adrian Cole + * + */ +public class VCloudResponseException extends HttpResponseException { + + private static final long serialVersionUID = 1L; + + private org.jclouds.vcloud.domain.VCloudError error; + + public VCloudResponseException(HttpCommand command, HttpResponse response, VCloudError error) { + super(String.format("request %s failed with code %s, error: %s", command.getRequest().getRequestLine(), response + .getStatusCode(), error.toString()), command, response); + this.setError(error); + + } + + public VCloudResponseException(HttpCommand command, HttpResponse response, VCloudError error, Throwable cause) { + super(String.format("request %1$s failed with error: %2$s", command.getRequest().getRequestLine(), error + .toString()), command, response, cause); + this.setError(error); + + } + + public VCloudResponseException(String message, HttpCommand command, HttpResponse response, VCloudError error) { + super(message, command, response); + this.setError(error); + + } + + public VCloudResponseException(String message, HttpCommand command, HttpResponse response, VCloudError error, + Throwable cause) { + super(message, command, response, cause); + this.setError(error); + + } + + public void setError(VCloudError error) { + this.error = error; + } + + public VCloudError getError() { + return error; + } + +} diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Task.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Task.java index ee8b13efca..60133089d1 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Task.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Task.java @@ -71,6 +71,6 @@ public interface Task extends ReferenceType { * error message or related information returned by the task */ @Nullable - Error getError(); + VCloudError getError(); } \ No newline at end of file diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Error.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/VCloudError.java similarity index 88% rename from vcloud/core/src/main/java/org/jclouds/vcloud/domain/Error.java rename to vcloud/core/src/main/java/org/jclouds/vcloud/domain/VCloudError.java index dd311111d4..ccd6ccafd0 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Error.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/VCloudError.java @@ -19,6 +19,8 @@ package org.jclouds.vcloud.domain; +import static com.google.common.base.Preconditions.checkNotNull; + import javax.annotation.Nullable; import org.jclouds.vcloud.domain.internal.ErrorImpl; @@ -31,7 +33,7 @@ import com.google.inject.ImplementedBy; * @author Adrian Cole */ @ImplementedBy(ErrorImpl.class) -public interface Error { +public interface VCloudError { public static enum MinorCode { /** * The request was made by a user who had insufficient rights to the object or operation. @@ -75,8 +77,15 @@ public interface Error { /** * The wrong content type was specified for the request. */ - UNSUPPORTED_MEDIA_TYPE; + UNSUPPORTED_MEDIA_TYPE, UNRECOGNIZED; + public static MinorCode fromValue(String minorCode) { + try { + return valueOf(checkNotNull(minorCode, "minorCode")); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } } /** @@ -96,7 +105,7 @@ public interface Error { * @return error code specific to the failed operation or null if vcloud <0.9 */ @Nullable - String getMinorErrorCode(); + MinorCode getMinorErrorCode(); /** * diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/ErrorImpl.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/ErrorImpl.java index 536d3cd8bb..1b25c3e9e7 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/ErrorImpl.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/ErrorImpl.java @@ -21,7 +21,7 @@ package org.jclouds.vcloud.domain.internal; import static com.google.common.base.Preconditions.checkNotNull; -import org.jclouds.vcloud.domain.Error; +import org.jclouds.vcloud.domain.VCloudError; import com.google.inject.internal.Nullable; @@ -30,19 +30,19 @@ import com.google.inject.internal.Nullable; * @author Adrian Cole * */ -public class ErrorImpl implements Error { +public class ErrorImpl implements VCloudError { private final String message; private final int majorErrorCode; - private final String minorErrorCode; + private final MinorCode minorErrorCode; @Nullable private final String vendorSpecificErrorCode; @Nullable private final String stackTrace; - public ErrorImpl(String message, int majorErrorCode, @Nullable String minorErrorCode, + public ErrorImpl(String message, int majorErrorCode, @Nullable MinorCode minorErrorCode, @Nullable String vendorSpecificErrorCode, @Nullable String stackTrace) { this.message = checkNotNull(message, "message"); - this.majorErrorCode = checkNotNull(majorErrorCode, "majorErrorCode"); + this.majorErrorCode = majorErrorCode; this.minorErrorCode = minorErrorCode; // check null after 0.8 is gone this.vendorSpecificErrorCode = vendorSpecificErrorCode; this.stackTrace = stackTrace; @@ -56,7 +56,7 @@ public class ErrorImpl implements Error { return majorErrorCode; } - public String getMinorErrorCode() { + public MinorCode getMinorErrorCode() { return minorErrorCode; } diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/TaskImpl.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/TaskImpl.java index 25ebeff8e8..61a6fe4843 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/TaskImpl.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/TaskImpl.java @@ -25,7 +25,7 @@ import java.net.URI; import java.util.Date; import org.jclouds.vcloud.VCloudMediaType; -import org.jclouds.vcloud.domain.Error; +import org.jclouds.vcloud.domain.VCloudError; import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.TaskStatus; @@ -48,10 +48,10 @@ public class TaskImpl extends ReferenceTypeImpl implements Task { private final Date expiryTime; private final ReferenceType owner; @Nullable - private final Error error; + private final VCloudError error; public TaskImpl(URI id, String operation, TaskStatus status, Date startTime, @Nullable Date endTime, - @Nullable Date expiryTime, ReferenceType owner, Error error) { + @Nullable Date expiryTime, ReferenceType owner, VCloudError error) { super(null, VCloudMediaType.TASK_XML, id); this.operation = operation; this.status = checkNotNull(status, "status"); @@ -83,7 +83,7 @@ public class TaskImpl extends ReferenceTypeImpl implements Task { } @Override - public Error getError() { + public VCloudError getError() { return error; } diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/handlers/ParseVCloudErrorFromHttpResponse.java b/vcloud/core/src/main/java/org/jclouds/vcloud/handlers/ParseVCloudErrorFromHttpResponse.java index a1c0c8e459..d68157367e 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/handlers/ParseVCloudErrorFromHttpResponse.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/handlers/ParseVCloudErrorFromHttpResponse.java @@ -26,16 +26,22 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Resource; +import javax.inject.Inject; import javax.inject.Singleton; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseException; import org.jclouds.logging.Logger; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.util.Utils; +import org.jclouds.vcloud.VCloudMediaType; +import org.jclouds.vcloud.VCloudResponseException; +import org.jclouds.vcloud.domain.VCloudError; +import org.jclouds.vcloud.util.VCloudUtils; /** * This will parse and set an appropriate exception on the command object. @@ -48,47 +54,60 @@ public class ParseVCloudErrorFromHttpResponse implements HttpErrorHandler { @Resource protected Logger logger = Logger.NULL; public static final Pattern RESOURCE_PATTERN = Pattern.compile(".*/v[^/]+/([^/]+)/([0-9]+)"); + private final VCloudUtils utils; + + @Inject + public ParseVCloudErrorFromHttpResponse(VCloudUtils utils) { + this.utils = utils; + } public void handleError(HttpCommand command, HttpResponse response) { + HttpRequest request = command.getRequest(); Exception exception = new HttpResponseException(command, response); - try { - String content = parseErrorFromContentOrNull(command, response); - switch (response.getStatusCode()) { - case 401: - case 403: - exception = new AuthorizationException(command.getRequest(), content); - break; - case 404: - if (!command.getRequest().getMethod().equals("DELETE")) { - String path = command.getRequest().getEndpoint().getPath(); - Matcher matcher = RESOURCE_PATTERN.matcher(path); - String message; - if (matcher.find()) { - message = String.format("%s %s not found", matcher.group(1), matcher.group(2)); - } else { - message = path; + VCloudError error = null; + String message = null; + if (response.getPayload() != null) { + String contentType = response.getPayload().getContentMetadata().getContentType(); + if (VCloudMediaType.ERROR_XML.equals(contentType)) { + error = utils.parseErrorFromContent(request, response); + if (error != null) { + message = error.getMessage(); + exception = new VCloudResponseException(command, response, error); + } + } else { + try { + message = Utils.toStringAndClose(response.getPayload().getInput()); + } catch (IOException e) { } - exception = new ResourceNotFoundException(message); } - break; - default: - exception = new HttpResponseException(command, response, content); + } + message = message != null ? message : String.format("%s -> %s", request.getRequestLine(), response + .getStatusLine()); + + switch (response.getStatusCode()) { + case 400: + exception = new IllegalArgumentException(message, exception); + case 401: + case 403: + exception = new AuthorizationException(command.getRequest(), message); + break; + case 404: + if (!command.getRequest().getMethod().equals("DELETE")) { + String path = command.getRequest().getEndpoint().getPath(); + Matcher matcher = RESOURCE_PATTERN.matcher(path); + if (matcher.find()) { + message = String.format("%s %s not found", matcher.group(1), matcher.group(2)); + } else { + message = path; + } + exception = new ResourceNotFoundException(message); + } + break; } } finally { releasePayload(response); command.setException(exception); } } - - String parseErrorFromContentOrNull(HttpCommand command, HttpResponse response) { - if (response.getPayload() != null) { - try { - return Utils.toStringAndClose(response.getPayload().getInput()); - } catch (IOException e) { - logger.warn(e, "exception reading error from response", response); - } - } - return null; - } } \ No newline at end of file diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/util/Utils.java b/vcloud/core/src/main/java/org/jclouds/vcloud/util/Utils.java index c15a52ad98..81461bb57a 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/util/Utils.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/util/Utils.java @@ -22,8 +22,9 @@ package org.jclouds.vcloud.util; import java.net.URI; import java.util.Map; -import org.jclouds.vcloud.domain.Error; +import org.jclouds.vcloud.domain.VCloudError; import org.jclouds.vcloud.domain.ReferenceType; +import org.jclouds.vcloud.domain.VCloudError.MinorCode; import org.jclouds.vcloud.domain.internal.ErrorImpl; import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl; import org.xml.sax.Attributes; @@ -57,12 +58,8 @@ public class Utils { return newReferenceType(attributes, null); } - /** - * note that vCloud 0.9+ the error isn't attributes, it is a nested object. see - * {@link ErrorHandler} - */ - public static Error newError(Map attributes) { - String minorErrorCode = attributes.get("minorErrorCode"); + public static VCloudError newError(Map attributes) { + String vendorSpecificErrorCode = attributes.get("vendorSpecificErrorCode"); int errorCode; // remove this logic when vcloud 0.8 is gone @@ -72,6 +69,11 @@ public class Utils { errorCode = 500; vendorSpecificErrorCode = attributes.get("majorErrorCode"); } + MinorCode minorErrorCode = MinorCode.fromValue(attributes.get("minorErrorCode")); + if (minorErrorCode == MinorCode.UNRECOGNIZED) { + vendorSpecificErrorCode = attributes.get("minorErrorCode"); + } + return new ErrorImpl(attributes.get("message"), errorCode, minorErrorCode, vendorSpecificErrorCode, attributes .get("stackTrace")); } diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/util/VCloudUtils.java b/vcloud/core/src/main/java/org/jclouds/vcloud/util/VCloudUtils.java new file mode 100644 index 0000000000..aab4b17e33 --- /dev/null +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/util/VCloudUtils.java @@ -0,0 +1,68 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.vcloud.util; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.jclouds.http.HttpException; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.http.functions.ParseSax.Factory; +import org.jclouds.logging.Logger; +import org.jclouds.vcloud.VCloudMediaType; +import org.jclouds.vcloud.domain.VCloudError; +import org.jclouds.vcloud.xml.ErrorHandler; + +/** + * Needed to sign and verify requests and responses. + * + * @author Adrian Cole + */ +@Singleton +public class VCloudUtils { + private final ParseSax.Factory factory; + private final Provider errorHandlerProvider; + @Resource + protected Logger logger = Logger.NULL; + + @Inject + VCloudUtils(Factory factory, Provider errorHandlerProvider) { + this.factory = factory; + this.errorHandlerProvider = errorHandlerProvider; + } + + public VCloudError parseErrorFromContent(HttpRequest request, HttpResponse response) { + // HEAD has no content + if (response.getPayload() == null) + return null; + if (VCloudMediaType.ERROR_XML.equals(response.getPayload().getContentMetadata().getContentType())) { + try { + return (VCloudError) factory.create(errorHandlerProvider.get()).setContext(request).apply(response); + } catch (HttpException e) { + logger.warn(e, "error parsing error"); + } + } + return null; + } +} \ No newline at end of file diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/xml/ErrorHandler.java b/vcloud/core/src/main/java/org/jclouds/vcloud/xml/ErrorHandler.java new file mode 100644 index 0000000000..0250ff4c90 --- /dev/null +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/xml/ErrorHandler.java @@ -0,0 +1,49 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.vcloud.xml; + +import static org.jclouds.vcloud.util.Utils.cleanseAttributes; + +import java.util.Map; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.vcloud.domain.VCloudError; +import org.jclouds.vcloud.util.Utils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @author Adrian Cole + */ +public class ErrorHandler extends ParseSax.HandlerWithResult { + private VCloudError error; + + public VCloudError getResult() { + return error; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { + Map attributes = cleanseAttributes(attrs); + if (qName.equals("Error")) { + error = Utils.newError(attributes); + } + } +} diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/xml/TaskHandler.java b/vcloud/core/src/main/java/org/jclouds/vcloud/xml/TaskHandler.java index 0edff7c502..7d2fdfe6b9 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/xml/TaskHandler.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/xml/TaskHandler.java @@ -30,10 +30,10 @@ import javax.inject.Inject; import org.jclouds.date.DateService; import org.jclouds.http.functions.ParseSax; import org.jclouds.logging.Logger; -import org.jclouds.vcloud.domain.Error; import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.TaskStatus; +import org.jclouds.vcloud.domain.VCloudError; import org.jclouds.vcloud.domain.internal.TaskImpl; import org.jclouds.vcloud.util.Utils; import org.xml.sax.Attributes; @@ -52,7 +52,7 @@ public class TaskHandler extends ParseSax.HandlerWithResult { private Date endTime; private Date expiryTime; private Task task; - private Error error; + private VCloudError error; private boolean inOwner; protected Logger logger = Logger.NULL; diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudLoginLiveTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudLoginLiveTest.java index 53309f3f61..17f341d55c 100755 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudLoginLiveTest.java +++ b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudLoginLiveTest.java @@ -75,11 +75,11 @@ public class VCloudLoginLiveTest { @BeforeClass void setupFactory() { - String endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"), "jclouds.test.endpoint") + String endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint") + "/v0.8/login"; - String identity = checkNotNull(System.getProperty("jclouds.test.identity"), "jclouds.test.identity"); - String credential = checkNotNull(System.getProperty("jclouds.test.credential"), "jclouds.test.credential"); + String identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); + String credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider + ".credential"); ContextSpec contextSpec = contextSpec("test", endpoint, "1", identity, credential, VCloudLoginClient.class, VCloudExpressLoginAsyncClient.class); diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudVersionsLiveTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudVersionsLiveTest.java index f5fa1379d4..ca6a6fb744 100644 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudVersionsLiveTest.java +++ b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudVersionsLiveTest.java @@ -69,9 +69,9 @@ public class VCloudVersionsLiveTest { @BeforeClass void setupFactory() { - String endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"), "jclouds.test.endpoint"); - String identity = checkNotNull(System.getProperty("jclouds.test.identity"), "jclouds.test.identity"); - String credential = checkNotNull(System.getProperty("jclouds.test.credential"), "jclouds.test.credential"); + String endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint"); + String identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); + String credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider + ".credential"); ContextSpec contextSpec = contextSpec("test", endpoint, "1", identity, credential, VCloudVersionsClient.class, VCloudVersionsAsyncClient.class); diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/xml/TaskHandlerTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/xml/TaskHandlerTest.java index 0261a72a51..78fce0b160 100644 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/xml/TaskHandlerTest.java +++ b/vcloud/core/src/test/java/org/jclouds/vcloud/xml/TaskHandlerTest.java @@ -29,6 +29,7 @@ import org.jclouds.http.functions.BaseHandlerTest; import org.jclouds.vcloud.VCloudMediaType; import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.TaskStatus; +import org.jclouds.vcloud.domain.VCloudError.MinorCode; import org.jclouds.vcloud.domain.internal.ErrorImpl; import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl; import org.jclouds.vcloud.domain.internal.TaskImpl; @@ -121,9 +122,9 @@ public class TaskHandlerTest extends BaseHandlerTest { Task expects = new TaskImpl(URI.create("http://10.150.4.49/api/v0.8/task/23"), null, TaskStatus.ERROR, dateService.iso8601SecondsDateParse("2009-12-07T19:05:02Z"), dateService .iso8601SecondsDateParse("2009-12-10T14:40:32Z"), null, new ReferenceTypeImpl("testapp1", - VCloudMediaType.VAPP_XML, URI.create("http://10.150.4.49/api/v0.8/vapp/1")), - new ErrorImpl("Error processing job", 500, - " Error in runDailySummaries date used:2009-12-09 19:40:30.577326+00:00", null, null)); + VCloudMediaType.VAPP_XML, URI.create("http://10.150.4.49/api/v0.8/vapp/1")), new ErrorImpl( + "Error processing job", 500, MinorCode.UNRECOGNIZED, + " Error in runDailySummaries date used:2009-12-09 19:40:30.577326+00:00", null)); assertEquals(result, expects); } diff --git a/vcloud/terremark/pom.xml b/vcloud/terremark/pom.xml index 17783c4c13..613d21b536 100644 --- a/vcloud/terremark/pom.xml +++ b/vcloud/terremark/pom.xml @@ -32,15 +32,15 @@ jclouds Core components to access terremark - trmkrun-ccc,trmk-924 - https://services.vcloudexpress.terremark.com/api - 0.8a-ext1.6 - FIXME - FIXME - https://services.enterprisecloud.terremark.com/api - 0.8b-ext2.3 - FIXME - FIXME + trmkrun-ccc,test.trmk-924 + https://services.vcloudexpress.terremark.com/api + 0.8a-ext1.6 + FIXME + FIXME + https://services.enterprisecloud.terremark.com/api + 0.8b-ext2.3 + FIXME + FIXME @@ -82,36 +82,36 @@ - trmk-vcloudexpress.endpoint - ${trmk-vcloudexpress.endpoint} + test.trmk-vcloudexpress.endpoint + ${test.trmk-vcloudexpress.endpoint} - trmk-vcloudexpress.apiversion - ${trmk-vcloudexpress.apiversion} + test.trmk-vcloudexpress.apiversion + ${test.trmk-vcloudexpress.apiversion} - trmk-vcloudexpress.identity - ${trmk-vcloudexpress.identity} + test.trmk-vcloudexpress.identity + ${test.trmk-vcloudexpress.identity} - trmk-vcloudexpress.credential - ${trmk-vcloudexpress.credential} + test.trmk-vcloudexpress.credential + ${test.trmk-vcloudexpress.credential} - trmk-ecloud.endpoint - ${trmk-ecloud.endpoint} + test.trmk-ecloud.endpoint + ${test.trmk-ecloud.endpoint} - trmk-ecloud.apiversion - ${trmk-ecloud.apiversion} + test.trmk-ecloud.apiversion + ${test.trmk-ecloud.apiversion} - trmk-ecloud.identity - ${trmk-ecloud.identity} + test.trmk-ecloud.identity + ${test.trmk-ecloud.identity} - trmk-ecloud.credential - ${trmk-ecloud.credential} + test.trmk-ecloud.credential + ${test.trmk-ecloud.credential} jclouds.compute.blacklist.nodes