Merge branch 'master' of github.com:jclouds/jclouds

This commit is contained in:
Lili Nader 2010-11-22 12:44:15 -08:00
commit 8b716a06d8
212 changed files with 11360 additions and 3565 deletions

View File

@ -19,22 +19,26 @@
Overview:
jclouds is an open source framework that helps you get started in the cloud
jclouds is an open source library that helps you get started in the cloud
and reuse your java and clojure development skills. Our api allows you to
freedom to use portable abstractions or cloud-specific features.
freedom to use portable abstractions or cloud-specific features. We have
two abstractions at the moment: compute and blobstore. compute helps you
bootstrap machines in the cloud. blobstore helps you manage key-value
data.
our current version is 1.0-beta-7
our current version is 1.0-beta-8
our dev version is 1.0-SNAPSHOT
our compute api supports: ec2, gogrid, rackspace, rimuhosting, vcloud, trmk-ecloud,
trmk-vcloudexpress, eucalyptus, bluelock-vclouddirector,
bluelock-vcloudexpress, slicehost, stub (in-memory)
our compute api supports: ec2, gogrid, cloudservers (rackspace), rimuhosting, vcloud,
trmk-ecloud, trmk-vcloudexpress, eucalyptus,
bluelock-vclouddirector, slicehost, stub (in-memory)
* note * the pom dependency org.jclouds/jclouds-allcompute gives you access to
to all of these providers
our blobstore api supports: s3, rackspace, azure, atmos online, att synaptic,
walrus, googlestorage, transient (in-memory), filesystem (on-disk)
our blobstore api supports: s3, cloudfiles (rackspace), azurestorage, atmosonline,
synaptic, peer1-storage, walrus, googlestorage,
transient (in-memory), filesystem (on-disk)
* note * the pom dependency org.jclouds/jclouds-allblobstore gives you access to
to all of these providers
@ -98,13 +102,13 @@ Compute Example (Clojure):
(run-nodes "mycluster" 2))
Downloads:
* distribution zip: http://jclouds.googlecode.com/files/jclouds-1.0-beta-7.zip
* distribution zip: http://jclouds.googlecode.com/files/jclouds-1.0-beta-8.zip
* maven repo: http://jclouds.googlecode.com/svn/repo
* snapshot repo: http://jclouds.rimuhosting.com/maven2/snapshots
Links:
* project page: http://code.google.com/p/jclouds/
* javadocs (1.0-beta-7): http://jclouds.rimuhosting.com/apidocs/
* javadocs (1.0-beta-8): http://jclouds.rimuhosting.com/apidocs/
* javadocs (1.0-SNAPSHOT): http://jclouds.rimuhosting.com/apidocs-SNAPSHOT/
* community: http://code.google.com/p/jclouds/wiki/AppsThatUseJClouds
* user group: http://groups.google.com/group/jclouds

View File

@ -36,6 +36,10 @@
<test.atmosonline.apiversion>1.3.0</test.atmosonline.apiversion>
<test.atmosonline.identity>FIXME</test.atmosonline.identity>
<test.atmosonline.credential>FIXME</test.atmosonline.credential>
<test.peer1-storage.endpoint>https://cloudonestorage.peer1.com</test.peer1-storage.endpoint>
<test.peer1-storage.apiversion>1.3.0</test.peer1-storage.apiversion>
<test.peer1-storage.identity>FIXME</test.peer1-storage.identity>
<test.peer1-storage.credential>FIXME</test.peer1-storage.credential>
<test.synaptic.endpoint>https://storage.synaptic.att.com</test.synaptic.endpoint>
<test.synaptic.apiversion>1.3.0</test.synaptic.apiversion>
<test.synaptic.identity>FIXME</test.synaptic.identity>
@ -107,6 +111,22 @@
<name>test.atmosonline.credential</name>
<value>${test.atmosonline.credential}</value>
</property>
<property>
<name>test.peer1-storage.endpoint</name>
<value>${test.peer1-storage.endpoint}</value>
</property>
<property>
<name>test.peer1-storage.apiversion</name>
<value>${test.peer1-storage.apiversion}</value>
</property>
<property>
<name>test.peer1-storage.identity</name>
<value>${test.peer1-storage.identity}</value>
</property>
<property>
<name>test.peer1-storage.credential</name>
<value>${test.peer1-storage.credential}</value>
</property>
<property>
<name>test.synaptic.endpoint</name>
<value>${test.synaptic.endpoint}</value>

View File

@ -29,6 +29,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.atmosonline.saas.binders.BindMetadataToHeaders;
@ -103,6 +104,7 @@ public interface AtmosStorageAsyncClient {
@POST
@Path("/{directoryName}/")
@ExceptionParser(ReturnEndpointIfAlreadyExists.class)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes(MediaType.WILDCARD)
ListenableFuture<URI> createDirectory(@PathParam("directoryName") String directoryName);

View File

@ -148,7 +148,7 @@ public class SignRequest implements HttpRequestFilter {
// TreeSet == Sort the headers alphabetically.
Set<String> headers = new TreeSet<String>(request.getHeaders().keySet());
for (String header : headers) {
if (header.startsWith("x-emc-")) {
if (header.startsWith("x-emc-") && !header.equals(AtmosStorageHeaders.SIGNATURE)) {
// Convert all header names to lowercase.
toSign.append(header.toLowerCase()).append(":");
// For headers with values that span multiple lines, convert them into one line by

View File

@ -64,28 +64,36 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
}
public static final Pattern DIRECTORY_PATH = Pattern.compile("^/rest/namespace/?([^/]+)/$");
public static final Pattern DIRECTORY_KEY_PATH = Pattern
.compile("^/rest/namespace/?([^/]+)/(.*)");
public static final Pattern DIRECTORY_KEY_PATH = Pattern.compile("^/rest/namespace/?([^/]+)/(.*)");
public void handleError(HttpCommand command, HttpResponse response) {
Exception exception = new HttpResponseException(command, response);
try {
AtmosStorageError error = parseErrorFromContentOrNull(command, response);
AtmosStorageError error = null;
if (response.getPayload() != null) {
try {
String content = Utils.toStringAndClose(response.getPayload().getInput());
if (content != null && content.indexOf('<') >= 0) {
error = utils.parseAtmosStorageErrorFromContent(command, response, Utils.toInputStream(content));
} else {
exception = content != null ? new HttpResponseException(command, response, content) : exception;
}
} catch (IOException e) {
logger.warn(e, "exception reading error from response", response);
}
}
if (error != null && error.getCode() == 1016) {
File file = new File(command.getRequest().getEndpoint().getPath());
exception = new KeyAlreadyExistsException(file.getParentFile().getAbsolutePath(), file
.getName());
exception = new KeyAlreadyExistsException(file.getParentFile().getAbsolutePath(), file.getName());
} else {
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(command.getRequest(),
error != null ? error.getMessage() : response.getStatusLine());
exception = new AuthorizationException(exception.getMessage(), exception);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
String message = error != null ? error.getMessage() : String.format(
"%s -> %s", command.getRequest().getRequestLine(), response
.getStatusLine());
String message = error != null ? error.getMessage() : String.format("%s -> %s", command.getRequest()
.getRequestLine(), response.getStatusLine());
String path = command.getRequest().getEndpoint().getPath();
Matcher matcher = DIRECTORY_PATH.matcher(path);
if (matcher.find()) {
@ -93,15 +101,14 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
} else {
matcher = DIRECTORY_KEY_PATH.matcher(path);
if (matcher.find()) {
exception = new KeyNotFoundException(matcher.group(1), matcher.group(2),
message);
exception = new KeyNotFoundException(matcher.group(1), matcher.group(2), message);
}
}
}
break;
default:
exception = error != null ? new AtmosStorageResponseException(command, response,
error) : new HttpResponseException(command, response);
exception = error != null ? new AtmosStorageResponseException(command, response, error)
: new HttpResponseException(command, response);
}
}
@ -111,17 +118,4 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
}
}
AtmosStorageError parseErrorFromContentOrNull(HttpCommand command, HttpResponse response) {
if (response.getPayload() != null) {
try {
String content = Utils.toStringAndClose(response.getPayload().getInput());
if (content != null && content.indexOf('<') >= 0)
return utils.parseAtmosStorageErrorFromContent(command, response, Utils
.toInputStream(content));
} catch (IOException e) {
logger.warn(e, "exception reading error from response", response);
}
}
return null;
}
}

View File

@ -140,7 +140,7 @@ public class AtmosStorageAsyncClientTest extends RestClientTest<AtmosStorageAsyn
assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/ HTTP/1.1");
assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\n");
assertPayloadEquals(request, null, null, false);
assertPayloadEquals(request, "", "application/octet-stream", false);
assertResponseParserClassEquals(method, request, ParseURIFromListOrLocationHeaderIf20x.class);
assertSaxResponseParserClassEquals(method, null);

View File

@ -42,6 +42,8 @@ public class Region {
* consistency for PUTS of new objects in your Amazon S3 bucket and eventual
* consistency for overwrite PUTS and DELETES.
*/
public static final String EU = "EU";
public static final String EU_WEST_1 = "eu-west-1";
/**
@ -85,8 +87,8 @@ public class Region {
*/
public static final String AP_SOUTHEAST_1 = "ap-southeast-1";
public static Set<String> ALL_S3 = ImmutableSet.of("EU", US_STANDARD,
US_EAST_1, US_WEST_1, AP_SOUTHEAST_1);
public static Set<String> ALL_S3 = ImmutableSet.of(EU, US_STANDARD,
US_WEST_1, AP_SOUTHEAST_1);
public static Set<String> ALL_SQS = ImmutableSet.of(EU_WEST_1, US_STANDARD,
US_EAST_1, US_WEST_1, AP_SOUTHEAST_1);
}

View File

@ -26,6 +26,7 @@ import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_CC_AMIs;
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_ELB_ENDPOINT;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_TIMEOUT_NODE_SUSPENDED;
import java.util.Properties;
@ -49,6 +50,10 @@ public class EC2PropertiesBuilder extends PropertiesBuilder {
properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "137112412989,063491364108,099720109477,411009282317");
// amis that work with the cluster instances
properties.setProperty(PROPERTY_EC2_CC_AMIs, "us-east-1/ami-7ea24a17");
// sometimes, like in ec2, stop takes a very long time, perhaps
// due to volume management. one example spent 2 minutes moving
// from stopping->stopped state on an ec2 micro
properties.setProperty(PROPERTY_TIMEOUT_NODE_SUSPENDED, 120 * 1000 + "");
// auth fail sometimes happens in EC2, as the rc.local script that injects the
// authorized key executes after ssh has started
properties.setProperty("jclouds.ssh.max_retries", "7");

View File

@ -24,8 +24,8 @@ import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
import static org.jclouds.util.Utils.checkNotEmpty;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
@ -55,12 +55,13 @@ import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.http.HttpResponseException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
@ -94,9 +95,9 @@ public class EC2ComputeService extends BaseComputeService {
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy,
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
nodeSuspended, utils, timeouts, executor);
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended, utils,
timeouts, executor);
this.ec2Client = ec2Client;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
@ -108,12 +109,13 @@ public class EC2ComputeService extends BaseComputeService {
void deletePlacementGroup(String region, String tag) {
checkNotEmpty(tag, "tag");
String group = String.format("jclouds#%s#%s", tag, region);
try {
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, group).size() > 0) {
logger.debug(">> deleting placementGroup(%s)", group);
try {
ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, group);
checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)), String
.format("placementGroup region(%s) name(%s) failed to delete", region, group));
checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)),
String.format("placementGroup region(%s) name(%s) failed to delete", region, group));
placementGroupMap.remove(new RegionAndName(region, tag));
logger.debug("<< deleted placementGroup(%s)", group);
} catch (AWSResponseException e) {
@ -124,6 +126,12 @@ public class EC2ComputeService extends BaseComputeService {
}
}
}
} catch (HttpResponseException e) {
// Eucalyptus does not support placement groups yet.
if (!(e.getResponse().getStatusCode() == 400 && context.getProviderSpecificContext().getProvider()
.equals("eucalyptus")))
throw e;
}
}
@VisibleForTesting

View File

@ -22,7 +22,6 @@ package org.jclouds.aws.ec2.compute.config;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.compute.domain.OsFamily.AMZN_LINUX;
import static org.jclouds.compute.domain.OsFamily.CENTOS;
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import java.util.Map;
@ -65,12 +64,12 @@ public class EC2ComputeServiceContextModule extends BaseComputeServiceContextMod
@Override
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
String provider = injector.getInstance(Key.get(String.class, Provider.class));
if ("eucalyptus".equals(provider))
return template.osFamily(CENTOS);
else if ("nova".equals(provider))
return template.osFamily(UBUNTU);
else
if ("ec2".equals(provider))
return template.osFamily(AMZN_LINUX).os64Bit(true);
else if ("nova".equals(provider))
return super.provideTemplate(injector, template);
else
return template.osFamily(CENTOS);
}
@Provides

View File

@ -21,8 +21,8 @@ package org.jclouds.aws.ec2.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseOsFamilyOrNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseVersionOrReturnEmptyString;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher;
@ -42,6 +42,7 @@ import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
@ -81,23 +82,26 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
.compile("[^/]*/([^_]*)_([^_]*)_[^vV]*[vV](.*)(\\.manifest.xml)?");
// ex 411009282317/RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha
// 411009282317/RightImage_Windows_2008_x64_v5.5.5
public static final Pattern RIGHTIMAGE_PATTERN = Pattern
.compile("[^/]*/RightImage_([^_]*)_([^_]*)_[^vV]*[vV](.*)(\\.manifest.xml)?");
.compile("[^/]*/RightImage[_ ]([^_]*)_([^_]*)_[^vV]*[vV](.*)(\\.manifest.xml)?");
private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
private final Supplier<Set<? extends Location>> locations;
private final Supplier<Location> defaultLocation;
private final String provider;
private final Map<OsFamily, Map<String, String>> osVersionMap;
@Inject
ImageParser(PopulateDefaultLoginCredentialsForImageStrategy credentialProvider,
@Memoized Supplier<Set<? extends Location>> locations, Supplier<Location> defaultLocation,
@Provider String provider) {
Map<OsFamily, Map<String, String>> osVersionMap, @Memoized Supplier<Set<? extends Location>> locations,
Supplier<Location> defaultLocation, @Provider String provider) {
this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider");
this.locations = checkNotNull(locations, "locations");
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
this.provider = checkNotNull(provider, "provider");
this.osVersionMap = checkNotNull(osVersionMap, "utils");
}
@Override
@ -116,7 +120,8 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
OsFamily osFamily = parseOsFamilyOrNull(provider, from.getImageLocation());
String osName = null;
String osArch = from.getVirtualizationType();
String osVersion = parseVersionOrReturnEmptyString(osFamily, from.getImageLocation());
String osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, from.getImageLocation(),
osVersionMap);
String osDescription = from.getImageLocation();
boolean is64Bit = from.getArchitecture() == Architecture.X86_64;
try {
@ -126,10 +131,10 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
osVersion = matcher.group(1);
builder.version(osVersion);
} else if (matcher.pattern() == NEBULA_PATTERN) {
osVersion = parseVersionOrReturnEmptyString(osFamily, matcher.group(2));
osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(2), osVersionMap);
} else {
osFamily = OsFamily.fromValue(matcher.group(1));
osVersion = parseVersionOrReturnEmptyString(osFamily, matcher.group(2));
osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(2), osVersionMap);
builder.version(matcher.group(3).replace(".manifest.xml", ""));
}
} catch (IllegalArgumentException e) {

View File

@ -29,7 +29,6 @@ import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.compute.domain.RegionAndName;
import org.jclouds.compute.domain.Image;
import org.jclouds.logging.Logger;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
@ -57,9 +56,8 @@ public final class RegionAndIdToImage implements Function<RegionAndName, Image>
org.jclouds.aws.ec2.domain.Image image = Iterables.getOnlyElement(sync.getAMIServices()
.describeImagesInRegion(key.getRegion(), imageIds(key.getName())));
return parser.apply(image);
} catch (ResourceNotFoundException e) {
logger.warn(e, "no image found for %s/%s: %s", key.getRegion(), key.getName(), e
.getMessage());
} catch (Exception e) {
logger.warn(e, "could not find image %s/%s: %s", key.getRegion(), key.getName(), e.getMessage());
return null;
}
}

View File

@ -90,7 +90,7 @@ public class EC2HardwareSupplier implements Supplier<Set<? extends Hardware>> {
sizes.add(cc1_4xlarge().location(location).supportsImageIds(ccAmi).build());
}
sizes.addAll(ImmutableSet.<Hardware> of(t1_micro().build(), c1_medium().build(), c1_xlarge().build(), m1_large()
.build(), "nova".equals(providerName) ? m1_small().supportsImage(any()).build() : m1_small().build(),
.build(), !"ec2".equals(providerName) ? m1_small().supportsImage(any()).build() : m1_small().build(),
m1_xlarge().build(), m2_xlarge().build(), m2_2xlarge().build(), m2_4xlarge().build()));
return sizes;
}

View File

@ -35,10 +35,14 @@ import com.google.common.collect.Sets;
*/
public class BaseEC2RequestOptions extends BaseHttpRequestOptions {
@Override
public String toString() {
return "[formParameters=" + formParameters + "]";
}
protected void indexFormValuesWithPrefix(String prefix, String... values) {
for (int i = 0; i < values.length; i++) {
formParameters.put(prefix + "." + (i + 1), checkNotNull(values[i], prefix.toLowerCase()
+ "s[" + i + "]"));
formParameters.put(prefix + "." + (i + 1), checkNotNull(values[i], prefix.toLowerCase() + "s[" + i + "]"));
}
}

View File

@ -72,8 +72,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
String message = null;
if (response.getPayload() != null) {
String contentType = response.getPayload().getContentMetadata().getContentType();
if (contentType != null
&& (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)) {
if (contentType != null && (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)) {
error = utils.parseAWSErrorFromContent(request, response);
if (error != null) {
message = error.getMessage();
@ -82,29 +81,29 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
} else {
try {
message = Utils.toStringAndClose(response.getPayload().getInput());
exception = new HttpResponseException(command, response, message);
} catch (IOException e) {
}
}
}
message = message != null ? message : String.format("%s -> %s", request.getRequestLine(), response
.getStatusLine());
message = message != null ? message : String.format("%s -> %s", request.getRequestLine(),
response.getStatusLine());
switch (response.getStatusCode()) {
case 400:
if (error != null && error.getCode() != null
&& (error.getCode().endsWith(".NotFound") || error.getCode().endsWith(".Unknown")))
exception = new ResourceNotFoundException(message, exception);
else if ((error != null && error.getCode() != null && (error.getCode().equals("IncorrectState") || error
.getCode().endsWith(".Duplicate")))
|| (message != null && message.indexOf("already exists") != -1))
.getCode().endsWith(".Duplicate"))) || (message != null && message.indexOf("already exists") != -1))
exception = new IllegalStateException(message, exception);
else if (error != null && error.getCode() != null && error.getCode().equals("AuthFailure"))
exception = new AuthorizationException(command.getRequest(), message);
exception = new AuthorizationException(exception.getMessage(), exception);
else if (message != null && message.indexOf("Failed to bind the following fields") != -1)// Nova
exception = new IllegalArgumentException(message, exception);
break;
case 401:
case 403:
exception = new AuthorizationException(command.getRequest(), message);
exception = new AuthorizationException(exception.getMessage(), exception);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
@ -116,6 +115,8 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
exception = new KeyNotFoundException(container, key, message);
}
break;
case 409:
exception = new IllegalStateException(message, exception);
}
} finally {
releasePayload(response);

View File

@ -60,20 +60,15 @@ public class S3PropertiesBuilder extends PropertiesBuilder {
}
protected Properties addEndpoints(Properties properties) {
properties.setProperty(PROPERTY_REGIONS, Joiner.on(',').join(Region.US_STANDARD,
Region.US_EAST_1, Region.US_WEST_1, "EU", Region.AP_SOUTHEAST_1));
properties.setProperty(PROPERTY_DEFAULT_REGIONS, Joiner.on(',').join(Region.US_STANDARD,
Region.US_EAST_1));
properties.setProperty(PROPERTY_REGIONS,
Joiner.on(',').join(Region.US_STANDARD, Region.US_WEST_1, "EU", Region.AP_SOUTHEAST_1));
properties.setProperty(PROPERTY_DEFAULT_REGIONS, Region.US_STANDARD);
properties.setProperty(PROPERTY_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.US_STANDARD,
"https://s3.amazonaws.com");
properties
.setProperty(PROPERTY_ENDPOINT + "." + Region.US_EAST_1, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.US_WEST_1,
"https://s3-us-west-1.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.US_STANDARD, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.US_WEST_1, "https://s3-us-west-1.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + "EU", "https://s3-eu-west-1.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.AP_SOUTHEAST_1,
"https://s3-ap-southeast-1.amazonaws.com");
properties
.setProperty(PROPERTY_ENDPOINT + "." + Region.AP_SOUTHEAST_1, "https://s3-ap-southeast-1.amazonaws.com");
return properties;
}
@ -92,8 +87,8 @@ public class S3PropertiesBuilder extends PropertiesBuilder {
protected void setMetaPrefix() {
if (properties.getProperty(PROPERTY_USER_METADATA_PREFIX) == null) {
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, String.format("x-%s-meta-",
properties.getProperty(PROPERTY_HEADER_TAG)));
properties.setProperty(PROPERTY_USER_METADATA_PREFIX,
String.format("x-%s-meta-", properties.getProperty(PROPERTY_HEADER_TAG)));
}
}

View File

@ -71,19 +71,21 @@ public class BucketToResourceMetadata implements Function<BucketMetadata, Storag
private Location getLocation(BucketMetadata from) {
try {
Set<? extends Location> locations = this.locations.get();
final String region = client.getBucketLocation(from.getName());
assert region != null : String.format("could not get region for %s", from.getName());
if (region != null) {
try {
return Iterables.find(locations.get(), new Predicate<Location>() {
return Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(region.toString());
return input.getId().equalsIgnoreCase(region.toString());
}
});
} catch (NoSuchElementException e) {
logger.error("could not get location for region %s in %s", region, locations.get());
logger.error("could not get location for region %s in %s", region, locations);
}
} else {
logger.error("could not get region for %s", from.getName());

View File

@ -50,8 +50,8 @@ public class LocationConstraintHandler extends ParseSax.HandlerWithResult<String
public static String fromValue(String v) {
if (v.equals(""))
return Region.US_STANDARD;
if (v.equals("EU"))
return Region.EU_WEST_1;
if (v.equals(Region.EU))
return Region.EU;
else if (v.equals(Region.US_WEST_1))
return Region.US_WEST_1;
else if (v.equals(Region.AP_SOUTHEAST_1))

View File

@ -93,7 +93,7 @@ public class ComputeAndBlobStoreTogetherHappilyLiveTest extends BlobStoreAndComp
Statement installOpenJDK = execHttpResponse(signedRequestOfInstallScript);
// if we want to, we can mix and match batched and ad-hoc commands, such as extracting maven
String mavenVersion = "3.0-beta-3";
String mavenVersion = "3.0";
Statement extractMavenIntoUsrLocal = extractTargzIntoDirectory(
URI.create("http://mirrors.ibiblio.org/pub/mirrors/apache//maven/binaries/apache-maven-" + mavenVersion
+ "-bin.tar.gz"), "/usr/local");

View File

@ -141,8 +141,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
checkMonitoringEnabled(before, instance);
// make sure we made our dummy group and also let in the user's group
assertEquals(Sets.newTreeSet(instance.getGroupIds()), ImmutableSortedSet.<String> of("jclouds#" + tag + "#"
+ instance.getRegion(), tag));
assertEquals(Sets.newTreeSet(instance.getGroupIds()),
ImmutableSortedSet.<String> of("jclouds#" + tag + "#" + instance.getRegion(), tag));
// make sure our dummy group has no rules
SecurityGroup group = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null,
@ -150,8 +150,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assert group.getIpPermissions().size() == 0 : group;
// try to run a script with the original keyPair
runScriptWithCreds(tag, first.getOperatingSystem(), new Credentials(first.getCredentials().identity, result
.getKeyMaterial()));
runScriptWithCreds(tag, first.getOperatingSystem(),
new Credentials(first.getCredentials().identity, result.getKeyMaterial()));
} finally {
client.destroyNodesMatching(NodePredicates.withTag(tag));
@ -215,12 +215,12 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assertEquals(instance.getKeyName(), null);
// make sure we made our dummy group and also let in the user's group
assertEquals(instance.getGroupIds(), ImmutableSet.<String> of(tag, String.format("jclouds#%s#%s", tag,
instance.getRegion())));
assertEquals(Sets.newTreeSet(instance.getGroupIds()),
ImmutableSortedSet.<String> of(tag, String.format("jclouds#%s#%s", tag, instance.getRegion())));
// make sure our dummy group has no rules
SecurityGroup group = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null, String
.format("jclouds#%s#%s", tag, instance.getRegion())));
SecurityGroup group = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null,
String.format("jclouds#%s#%s", tag, instance.getRegion())));
assert group.getIpPermissions().size() == 0 : group;
} finally {

View File

@ -19,24 +19,24 @@
package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Properties;
import org.jclouds.Constants;
import org.jclouds.aws.ec2.domain.InstanceType;
import org.jclouds.aws.ec2.reference.EC2Constants;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
@ -45,69 +45,48 @@ import com.google.inject.Module;
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ec2.EC2TemplateBuilderLiveTest")
public class EC2TemplateBuilderLiveTest {
protected String provider = "ec2";
protected String identity;
protected String credential;
protected String endpoint;
protected String apiversion;
public class EC2TemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
@BeforeClass
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
public EC2TemplateBuilderLiveTest() {
provider = "ec2";
}
protected Properties setupProperties() {
Properties overrides = new Properties();
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return new Predicate<OsFamilyVersion64Bit>() {
@Override
public boolean apply(OsFamilyVersion64Bit input) {
return input.family == OsFamily.RHEL || //
(input.family == OsFamily.CENTOS && !input.version.matches("5.[42]")) || //
(input.family == OsFamily.WINDOWS && !input.version.matches("200[38]"));
}
};
}
@Test
public void testTemplateBuilderM1SMALLWithDescription() {
ComputeServiceContext newContext = null;
try {
newContext = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), setupProperties());
Template template = newContext.getComputeService().templateBuilder().hardwareId(InstanceType.M1_SMALL)
Template template = context.getComputeService().templateBuilder().hardwareId(InstanceType.M1_SMALL)
.osVersionMatches("10.10").imageDescriptionMatches("ubuntu-images").osFamily(OsFamily.UBUNTU).build();
System.out.println(template.getHardware());
assert (template.getImage().getProviderId().startsWith("ami-")) : template;
assertEquals(template.getImage().getOperatingSystem().getVersion(), "10.10");
assertEquals(template.getImage().getOperatingSystem().is64Bit(), false);
assertEquals(template.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(template.getImage().getVersion(), "20101027");
assertEquals(template.getImage().getVersion(), "20101106");
assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");
assertEquals(template.getLocation().getId(), "us-east-1");
assertEquals(getCores(template.getHardware()), 1.0d);
assertEquals(template.getHardware().getId(), InstanceType.M1_SMALL);
} finally {
if (newContext != null)
newContext.close();
}
}
@Test
public void testTemplateBuilderCanUseImageIdAndhardwareId() {
ComputeServiceContext newContext = null;
try {
newContext = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), setupProperties());
Template template = newContext.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5")
Template template = context.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5")
.hardwareId(InstanceType.M2_2XLARGE).build();
System.out.println(template.getHardware());
@ -120,20 +99,13 @@ public class EC2TemplateBuilderLiveTest {
assertEquals(template.getLocation().getId(), "us-east-1");
assertEquals(getCores(template.getHardware()), 4.0d);
assertEquals(template.getHardware().getId(), InstanceType.M2_2XLARGE);
} finally {
if (newContext != null)
newContext.close();
}
}
@Test
public void testDefaultTemplateBuilder() throws IOException {
ComputeServiceContext newContext = null;
try {
newContext = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), setupProperties());
Template defaultTemplate = newContext.getComputeService().templateBuilder().build();
Template defaultTemplate = context.getComputeService().templateBuilder().build();
assert (defaultTemplate.getImage().getProviderId().startsWith("ami-")) : defaultTemplate;
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "0.9.9-beta");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
@ -142,22 +114,12 @@ public class EC2TemplateBuilderLiveTest {
assertEquals(defaultTemplate.getLocation().getId(), "us-east-1");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
} finally {
if (newContext != null)
newContext.close();
}
}
@Test
public void testTemplateBuilderMicro() throws IOException {
ComputeServiceContext newContext = null;
try {
newContext = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), setupProperties());
Template microTemplate = newContext.getComputeService().templateBuilder().hardwareId(InstanceType.T1_MICRO)
.build();
System.out.println(microTemplate.getHardware());
Template microTemplate = context.getComputeService().templateBuilder().hardwareId(InstanceType.T1_MICRO).build();
assert (microTemplate.getImage().getProviderId().startsWith("ami-")) : microTemplate;
assertEquals(microTemplate.getImage().getOperatingSystem().getVersion(), "9.10");
@ -166,26 +128,23 @@ public class EC2TemplateBuilderLiveTest {
assertEquals(microTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
assertEquals(microTemplate.getLocation().getId(), "us-east-1");
assertEquals(getCores(microTemplate.getHardware()), 1.0d);
} finally {
if (newContext != null)
newContext.close();
}
}
@Test
public void testTemplateBuilderWithNoOwnersParsesImageOnDemand() throws IOException {
ComputeServiceContext newContext = null;
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
// set owners to nothing
overrides.setProperty(EC2Constants.PROPERTY_EC2_AMI_OWNERS, "");
newContext = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides);
assertEquals(newContext.getComputeService().listImages().size(), 0);
assertEquals(context.getComputeService().listImages().size(), 0);
Template template = newContext.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5").build();
Template template = context.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5").build();
System.out.println(template.getHardware());
assert (template.getImage().getProviderId().startsWith("ami-")) : template;
assertEquals(template.getImage().getOperatingSystem().getVersion(), "5.4");
@ -199,11 +158,11 @@ public class EC2TemplateBuilderLiveTest {
// is 64bit
// ensure we cache the new image for next time
assertEquals(newContext.getComputeService().listImages().size(), 1);
assertEquals(context.getComputeService().listImages().size(), 1);
} finally {
if (newContext != null)
newContext.close();
if (context != null)
context.close();
}
}

View File

@ -28,13 +28,14 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Disabled until we have an environment with enough room to run a few nodes simultaneously.
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "ec2.EucalyptusComputeServiceLiveTest")
public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.EucalyptusComputeServiceLiveTest")
public class EucalyptusComputeServiceLiveTestDisabled extends EC2ComputeServiceLiveTest {
public EucalyptusComputeServiceLiveTest() {
public EucalyptusComputeServiceLiveTestDisabled() {
provider = "eucalyptus";
}
@ -45,12 +46,18 @@ public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest
tag = "euc";
}
@Override
@Test(enabled = false)
public void testExtendedOptionsAndLogin() throws Exception {
// euc does not support monitoring
}
@Override
protected void assertDefaultWorks() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.CENTOS);
assertEquals(getCores(defaultTemplate.getHardware()), 2.0d);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
}

View File

@ -21,18 +21,23 @@ package org.jclouds.aws.ec2.compute.functions;
import static org.testng.Assert.assertEquals;
import java.util.Map;
import java.util.Set;
import org.jclouds.aws.ec2.compute.strategy.EC2PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.aws.ec2.domain.Image;
import org.jclouds.aws.ec2.xml.DescribeImagesResponseHandlerTest;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystemBuilder;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule;
import org.testng.annotations.Test;
import com.google.common.base.Predicates;
@ -42,6 +47,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.inject.Guice;
/**
* @author Adrian Cole
@ -141,6 +147,10 @@ public class ImageParserTest {
assertEquals(
new Gson().toJson(Iterables.get(result, 1)),
"{\"operatingSystem\":{\"family\":\"UBUNTU\",\"arch\":\"paravirtual\",\"version\":\"9.10\",\"description\":\"411009282317/RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha\",\"is64Bit\":true},\"version\":\"4.5.3_EBS_Alpha\",\"description\":\"RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha\",\"defaultCredentials\":{\"identity\":\"root\"},\"id\":\"us-east-1/ami-c19db6b5\",\"type\":\"IMAGE\",\"providerId\":\"ami-c19db6b5\",\"location\":{\"scope\":\"REGION\",\"id\":\"us-east-1\",\"description\":\"us-east-1\"},\"userMetadata\":{\"owner\":\"411009282317\",\"rootDeviceType\":\"ebs\"}}");
assertEquals(
new Gson().toJson(Iterables.get(result, 2)),
"{\"operatingSystem\":{\"family\":\"WINDOWS\",\"arch\":\"hvm\",\"version\":\"2003\",\"description\":\"411009282317/RightImage Windows_2003_i386_v5.4.3\",\"is64Bit\":false},\"version\":\"5.4.3\",\"description\":\"Built by RightScale\",\"defaultCredentials\":{\"identity\":\"root\"},\"id\":\"us-east-1/ami-710c2605\",\"type\":\"IMAGE\",\"providerId\":\"ami-710c2605\",\"location\":{\"scope\":\"REGION\",\"id\":\"us-east-1\",\"description\":\"us-east-1\"},\"userMetadata\":{\"owner\":\"411009282317\",\"rootDeviceType\":\"ebs\"}}");
}
public void testParseEucalyptusImage() {
@ -208,8 +218,13 @@ public class ImageParserTest {
static Location defaultLocation = new LocationImpl(LocationScope.REGION, "us-east-1", "us-east-1", null);
public static Set<org.jclouds.compute.domain.Image> convertImages(String resource) {
Map<OsFamily, Map<String, String>> map = new BaseComputeServiceContextModule() {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(new GsonModule())
.getInstance(Json.class));
Set<Image> result = DescribeImagesResponseHandlerTest.parseImages(resource);
ImageParser parser = new ImageParser(new EC2PopulateDefaultLoginCredentialsForImageStrategy(),
ImageParser parser = new ImageParser(new EC2PopulateDefaultLoginCredentialsForImageStrategy(), map,
Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet.<Location> of(defaultLocation)),
Suppliers.ofInstance(defaultLocation), "ec2");
return Sets.newLinkedHashSet(Iterables.filter(Iterables.transform(result, parser), Predicates.notNull()));

View File

@ -27,6 +27,7 @@ import static org.easymock.classextension.EasyMock.verify;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
import static org.testng.Assert.assertEquals;
import java.util.NoSuchElementException;
import java.util.Set;
import org.jclouds.aws.ec2.EC2Client;
@ -107,4 +108,36 @@ public class RegionAndIdToImageTest {
verify(client);
}
@SuppressWarnings({ "unchecked" })
@Test
public void testApplyNoSuchElementException() {
ImageParser parser = createMock(ImageParser.class);
EC2Client caller = createMock(EC2Client.class);
AMIClient client = createMock(AMIClient.class);
org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class);
Image image = createNiceMock(Image.class);
Set<? extends org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set) images);
expect(parser.apply(ec2Image)).andThrow(new NoSuchElementException());
replay(caller);
replay(image);
replay(parser);
replay(client);
RegionAndIdToImage function = new RegionAndIdToImage(parser, caller);
assertEquals(function.apply(new RegionAndName("region", "ami")), null);
verify(caller);
verify(image);
verify(parser);
verify(client);
}
}

View File

@ -36,12 +36,13 @@ import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.domain.Image;
import org.jclouds.aws.ec2.domain.RootDeviceType;
import org.jclouds.aws.ec2.domain.Image.ImageType;
import org.jclouds.aws.ec2.domain.RootDeviceType;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -74,13 +75,12 @@ public class AMIClientLiveTest {
protected String endpoint;
protected String apiversion;
@BeforeClass
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint");
apiversion = checkNotNull(System.getProperty("test." + provider + ".apiversion"), "test." + provider
+ ".apiversion");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -88,8 +88,11 @@ public class AMIClientLiveTest {
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}

View File

@ -27,10 +27,10 @@ import static org.testng.Assert.assertNotNull;
import java.net.URI;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.Map.Entry;
import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
@ -41,13 +41,13 @@ import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Module;
/**
@ -66,13 +66,12 @@ public class AvailabilityZoneAndRegionClientLiveTest {
protected String endpoint;
protected String apiversion;
@BeforeClass
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint");
apiversion = checkNotNull(System.getProperty("test." + provider + ".apiversion"), "test." + provider
+ ".apiversion");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -80,8 +79,11 @@ public class AvailabilityZoneAndRegionClientLiveTest {
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}
@ -90,26 +92,25 @@ public class AvailabilityZoneAndRegionClientLiveTest {
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet.<Module> of(new Log4JLoggingModule()),
overrides).getProviderSpecificContext();
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides).getProviderSpecificContext();
client = context.getApi().getAvailabilityZoneAndRegionServices();
}
public void testDescribeAvailabilityZones() {
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1,
Region.US_WEST_1, Region.AP_SOUTHEAST_1)) {
Set<AvailabilityZoneInfo> allResults = Sets.newLinkedHashSet(client
.describeAvailabilityZonesInRegion(region));
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
Region.AP_SOUTHEAST_1)) {
Set<AvailabilityZoneInfo> allResults = client.describeAvailabilityZonesInRegion(region);
assertNotNull(allResults);
assert allResults.size() >= 2 : allResults.size();
Iterator<AvailabilityZoneInfo> iterator = allResults.iterator();
String id1 = iterator.next().getZone();
String id2 = iterator.next().getZone();
Set<AvailabilityZoneInfo> twoResults = Sets.newLinkedHashSet(client
.describeAvailabilityZonesInRegion(region, availabilityZones(id1, id2)));
Set<AvailabilityZoneInfo> twoResults = client.describeAvailabilityZonesInRegion(region,
availabilityZones(id1, id2));
assertNotNull(twoResults);
assertEquals(twoResults.size(), 2);
iterator = twoResults.iterator();
iterator = allResults.iterator();
assertEquals(iterator.next().getZone(), id1);
assertEquals(iterator.next().getZone(), id2);
}

View File

@ -30,7 +30,6 @@ import java.util.SortedSet;
import java.util.concurrent.TimeUnit;
import org.jclouds.Constants;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
@ -44,6 +43,7 @@ import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -71,13 +71,12 @@ public class ElasticBlockStoreClientLiveTest {
protected String endpoint;
protected String apiversion;
@BeforeClass
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint");
apiversion = checkNotNull(System.getProperty("test." + provider + ".apiversion"), "test." + provider
+ ".apiversion");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -85,8 +84,11 @@ public class ElasticBlockStoreClientLiveTest {
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}
@ -95,8 +97,8 @@ public class ElasticBlockStoreClientLiveTest {
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet.<Module> of(new Log4JLoggingModule()),
overrides).getProviderSpecificContext();
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides).getProviderSpecificContext();
client = context.getApi().getElasticBlockStoreServices();
}
@ -166,8 +168,8 @@ public class ElasticBlockStoreClientLiveTest {
@Test(dependsOnMethods = "testCreateSnapshotInRegion")
void testCreateVolumeFromSnapshotInAvailabilityZoneWithSize() {
Volume volume = client.createVolumeFromSnapshotInAvailabilityZone(AvailabilityZone.US_EAST_1B, 2, snapshot
.getId());
Volume volume = client.createVolumeFromSnapshotInAvailabilityZone(AvailabilityZone.US_EAST_1B, 2,
snapshot.getId());
assertNotNull(volume);
Predicate<Volume> availabile = new RetryablePredicate<Volume>(new VolumeAvailable(client), 600, 10,
@ -202,8 +204,8 @@ public class ElasticBlockStoreClientLiveTest {
assertNotNull(allResults);
if (allResults.size() >= 1) {
Snapshot snapshot = allResults.last();
Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(region, snapshotIds(snapshot
.getId())));
Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(region,
snapshotIds(snapshot.getId())));
assertNotNull(result);
assertEquals(result, snapshot);
}
@ -246,12 +248,7 @@ public class ElasticBlockStoreClientLiveTest {
@Test(dependsOnMethods = "testGetCreateVolumePermissionForSnapshot")
void testDeleteSnapshotInRegion() {
client.deleteSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
try {
client.describeSnapshotsInRegion(snapshot.getRegion(), snapshotIds(snapshot.getId()));
assert false : "shoud have exception";
} catch (AWSResponseException e) {
assertEquals(e.getError().getCode(), "InvalidSnapshot.NotFound");
}
assert client.describeSnapshotsInRegion(snapshot.getRegion(), snapshotIds(snapshot.getId())).size() == 0;
}
@AfterTest

View File

@ -56,7 +56,9 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -85,13 +87,12 @@ public class PlacementGroupClientLiveTest {
protected String endpoint;
protected String apiversion;
@BeforeClass
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint");
apiversion = checkNotNull(System.getProperty("test." + provider + ".apiversion"), "test." + provider
+ ".apiversion");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -99,8 +100,11 @@ public class PlacementGroupClientLiveTest {
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}
@ -109,8 +113,8 @@ public class PlacementGroupClientLiveTest {
public void setupClient() throws FileNotFoundException, IOException {
setupCredentials();
Properties overrides = setupProperties();
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides);
keyPair = setupKeyPair();
client = EC2Client.class.cast(context.getProviderSpecificContext().getApi());
@ -169,6 +173,7 @@ public class PlacementGroupClientLiveTest {
}
public void testStartCCInstance() throws Exception {
Set<? extends Hardware> sizes = context.getComputeService().listHardwareProfiles();
assert any(sizes, new Predicate<Hardware>() {
@ -198,6 +203,8 @@ public class PlacementGroupClientLiveTest {
String tag = PREFIX + "cccluster";
context.getComputeService().destroyNodesMatching(NodePredicates.withTag(tag));
// TODO make this not lookup an explicit region
client.getPlacementGroupServices().deletePlacementGroupInRegion(null, "jclouds#" + tag + "#us-east-1");
try {
Set<? extends NodeMetadata> nodes = context.getComputeService().runNodesWithTag(tag, 1, template);

View File

@ -69,6 +69,12 @@ public class ParseAWSErrorFromXmlContentTest {
"<Error><Code>IncorrectState</Code></Error>", IllegalStateException.class);
}
@Test
public void test409SetsIllegalStateException() {
assertCodeMakes("PUT", URI.create("https://adriancole-blobstore011.s3.amazonaws.com/"), 409, "",
"<Error><Code>OperationAborted</Code><Message>A conflicting conditional operation is currently in progress against this resource. Please try again.</Message><RequestId>F716E81C3D814E59</RequestId><HostId>SDprHxWzG/YXzanVnV7VTz/wP+6fRt1dS+q00kH1rz248YOOSddkFiTXF04XtqNO</HostId></Error>", IllegalStateException.class);
}
@Test
public void test400WithInvalidGroupDuplicateIllegalStateException() {
assertCodeMakes("GET", URI.create("https://amazonaws.com/foo"), 400,"Bad Request", "application/unknown",

View File

@ -39,17 +39,17 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.AccessControlList.CanonicalUserGrantee;
import org.jclouds.aws.s3.domain.AccessControlList.EmailAddressGrantee;
import org.jclouds.aws.s3.domain.AccessControlList.Grant;
import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI;
import org.jclouds.aws.s3.domain.AccessControlList.Permission;
import org.jclouds.aws.s3.domain.BucketLogging;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.CannedAccessPolicy;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.Payer;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.AccessControlList.CanonicalUserGrantee;
import org.jclouds.aws.s3.domain.AccessControlList.EmailAddressGrantee;
import org.jclouds.aws.s3.domain.AccessControlList.Grant;
import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI;
import org.jclouds.aws.s3.domain.AccessControlList.Permission;
import org.jclouds.aws.s3.internal.StubS3AsyncClient;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.util.Utils;
@ -221,8 +221,8 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
assertNull(getApi().getBucketLogging(bucketName));
setupAclForBucketLoggingTarget(targetBucket);
final BucketLogging logging = new BucketLogging(targetBucket, "access_log-", ImmutableSet
.<Grant> of(new Grant(new EmailAddressGrantee(StubS3AsyncClient.TEST_ACL_EMAIL),
final BucketLogging logging = new BucketLogging(targetBucket, "access_log-",
ImmutableSet.<Grant> of(new Grant(new EmailAddressGrantee(StubS3AsyncClient.TEST_ACL_EMAIL),
Permission.FULL_CONTROL)));
getApi().enableBucketLogging(bucketName, logging);
@ -231,6 +231,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
public void run() {
try {
BucketLogging newLogging = getApi().getBucketLogging(bucketName);
assert newLogging !=null;
AccessControlList acl = new AccessControlList();
for (Grant grant : newLogging.getTargetGrants()) { // TODO: add permission
// checking features to
@ -277,7 +278,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
public void testEu() throws Exception {
final String bucketName = getScratchContainerName();
try {
getApi().putBucketInRegion(Region.EU_WEST_1, bucketName + "eu", withBucketAcl(CannedAccessPolicy.PUBLIC_READ));
getApi().putBucketInRegion(Region.EU, bucketName + "eu", withBucketAcl(CannedAccessPolicy.PUBLIC_READ));
assertConsistencyAware(new Runnable() {
public void run() {
try {
@ -288,7 +289,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
}
}
});
assertEquals(Region.EU_WEST_1, getApi().getBucketLocation(bucketName + "eu"));
assertEquals(Region.EU, getApi().getBucketLocation(bucketName + "eu"));
// TODO: I believe that the following should work based on the above acl assertion passing.
// However, it fails on 403
// URL url = new URL(String.format("http://%s.s3.amazonaws.com", bucketName));
@ -298,7 +299,6 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
}
}
void bucketExists() throws Exception {
String bucketName = getContainerName();
try {

View File

@ -69,9 +69,8 @@ public class SQSClientLiveTest {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint");
apiversion = checkNotNull(System.getProperty("test." + provider + ".apiversion"), "test." + provider
+ ".apiversion");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -79,8 +78,11 @@ public class SQSClientLiveTest {
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}

View File

@ -41,5 +41,54 @@
</item>
</blockDeviceMapping>
</item>
<item>
<imageId>ami-710c2605</imageId>
<imageLocation>411009282317/RightImage Windows_2003_i386_v5.4.3</imageLocation>
<imageState>available</imageState>
<imageOwnerId>411009282317</imageOwnerId>
<isPublic>true</isPublic>
<architecture>i386</architecture>
<imageType>machine</imageType>
<platform>windows</platform>
<name>RightImage Windows_2003_i386_v5.4.3</name>
<description>Built by RightScale</description>
<rootDeviceType>ebs</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping>
<item>
<deviceName>/dev/sda1</deviceName>
<ebs>
<snapshotId>snap-9460affd</snapshotId>
<volumeSize>35</volumeSize>
<deleteOnTermination>true</deleteOnTermination>
</ebs>
</item>
</blockDeviceMapping>
<virtualizationType>hvm</virtualizationType>
</item>
<item>
<imageId>ami-c6a882b2</imageId>
<imageLocation>411009282317/RightImage_Windows_2008_x64_v5.5.5</imageLocation>
<imageOwnerId>411009282317</imageOwnerId>
<isPublic>true</isPublic>
<architecture>x86_64</architecture>
<imageType>machine</imageType>
<platform>windows</platform>
<name>RightImage_Windows_2008_x64_v5.5.5</name>
<description>Built by RightScale</description>
<rootDeviceType>ebs</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping>
<item>
<deviceName>/dev/sda1</deviceName>
<ebs>
<snapshotId>snap-68b26c01</snapshotId>
<volumeSize>80</volumeSize>
<deleteOnTermination>true</deleteOnTermination>
</ebs>
</item>
</blockDeviceMapping>
<virtualizationType>hvm</virtualizationType>
</item>
</imagesSet>
</DescribeImagesResponse>

View File

@ -162,12 +162,10 @@
<priority value="DEBUG" />
<appender-ref ref="ASYNCSSH" />
</category>
<!--
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
-->
<category name="jclouds.blobstore">
<priority value="DEBUG" />
<appender-ref ref="ASYNCBLOBSTORE" />

View File

@ -68,16 +68,26 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
try {
if (response.getPayload() != null) {
String contentType = response.getPayload().getContentMetadata().getContentType();
if (contentType != null && (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)) {
if (contentType != null && (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)
&& !new Long(0).equals(response.getPayload().getContentMetadata().getContentLength())) {
try {
AzureStorageError error = utils.parseAzureStorageErrorFromContent(command, response, response
.getPayload().getInput());
if (error != null) {
message = error.getMessage();
exception = new AzureStorageResponseException(command, response, error);
}
} catch (RuntimeException e) {
try {
message = Utils.toStringAndClose(response.getPayload().getInput());
exception = new HttpResponseException(command, response, message);
} catch (IOException e1) {
}
}
} else {
try {
message = Utils.toStringAndClose(response.getPayload().getInput());
exception = new HttpResponseException(command, response, message);
} catch (IOException e) {
}
}
@ -86,10 +96,9 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
response.getStatusLine());
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(command.getRequest(), message);
exception = new AuthorizationException(exception.getMessage(), exception);
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;
@ -49,12 +50,31 @@ public class ParseAzureErrorFromXmlContentTest {
@Test
public void test411WithTextHtmlIllegalArgumentException() {
assertCodeMakes("PUT", URI
.create("https://jclouds.blob.core.windows.net/adriancole-azureblob-413790770?restype=container"), 411,
assertCodeMakes("PUT",
URI.create("https://jclouds.blob.core.windows.net/adriancole-azureblob-413790770?restype=container"), 411,
"Length Required", "text/html; charset=us-ascii", "<HTML><HEAD><TITLE>Length Required</TITLE>\r\n",
IllegalArgumentException.class);
}
@Test
public void test304WithNoContentIllegalArgumentException() {
assertCodeMakes("GET", URI.create("https://jclouds.blob.core.windows.net/adriancole-blobstore0/apples"), 411,
"HTTP/1.1 304 The condition specified using HTTP conditional header(s) is not met.", "application/unknown",
"", 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

@ -21,7 +21,8 @@
"A clojure binding for the jclouds BlobStore.
Current supported services are:
[transient, filesystem, s3, azureblob, atmos, cloudfiles, walrus, googlestorage]
[transient, filesystem, s3, azureblob, atmos, cloudfiles, walrus,
googlestorage, synaptic, peer1-storage]
Here's a quick example of how to viewresources in rackspace

View File

@ -148,6 +148,10 @@ public interface ComputeService {
/**
* resume the node from {@link org.jclouds.compute.domain.NodeState#SUSPENDED suspended} state,
* given its id.
*
* <h4>note</h4>
*
* affected nodes may not resume with the same IP address(es)
*/
void resumeNode(String id);
@ -155,6 +159,10 @@ public interface ComputeService {
* nodes matching the filter are treated as a logical set. Using the resume command, you can save
* time by resumeing the nodes in parallel.
*
* <h4>note</h4>
*
* affected nodes may not resume with the same IP address(es)
*
* @throws UnsupportedOperationException
* if the underlying provider doesn't support suspend/resume
*/
@ -164,6 +172,10 @@ public interface ComputeService {
* suspend the node, given its id. This will result in
* {@link org.jclouds.compute.domain.NodeState#SUSPENDED suspended} state.
*
* <h4>note</h4>
*
* affected nodes may not resume with the same IP address(es)
*
* @throws UnsupportedOperationException
* if the underlying provider doesn't support suspend/resume
*/
@ -173,6 +185,9 @@ public interface ComputeService {
* nodes matching the filter are treated as a logical set. Using the suspend command, you can
* save time by suspending the nodes in parallel.
*
* <h4>note</h4>
*
* affected nodes may not resume with the same IP address(es)
*/
void suspendNodesMatching(Predicate<NodeMetadata> filter);

View File

@ -44,4 +44,5 @@ public interface Utils extends org.jclouds.rest.Utils {
* @return function that gets an ssh client for a node that is available via ssh.
*/
Function<NodeMetadata, SshClient> sshForNode();
}

View File

@ -35,9 +35,12 @@ import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.functions.CreateSshClientOncePortIsListeningOnNode;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.json.Json;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import org.jclouds.ssh.SshClient;
@ -70,13 +73,20 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null)).in(Scopes.SINGLETON);
}
@Provides
@Singleton
public Map<OsFamily, Map<String, String>> provideOsVersionMap(ComputeServiceConstants.ReferenceData data, Json json) {
return json.fromJson(data.osVersionMapJson, new TypeLiteral<Map<OsFamily, Map<String, String>>>() {
}.getType());
}
/**
* The default template if none is provided.
*/
@Provides
@Named("DEFAULT")
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
return template.osFamily(UBUNTU);
return template.osFamily(UBUNTU).osVersionMatches("10.04").os64Bit(true);
}
/**

View File

@ -83,7 +83,6 @@ import org.jclouds.domain.Location;
import org.jclouds.io.Payload;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.scriptbuilder.InitBuilder;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.util.Utils;
@ -175,9 +174,6 @@ public class BaseComputeService implements ComputeService {
throws RunNodesException {
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
checkNotNull(template.getLocation(), "location");
if (template.getOptions().getTaskName() == null && template.getOptions().getRunScript() != null
&& !(template.getOptions().getRunScript() instanceof InitBuilder))
template.getOptions().nameTask("bootstrap");
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) hardwareProfile(%s) options(%s)", count,
count > 1 ? "s" : "", tag, template.getLocation().getId(), template.getImage().getId(), template
.getHardware().getId(), template.getOptions());

View File

@ -38,10 +38,28 @@ public interface ComputeServiceConstants {
public static final String PROPERTY_TIMEOUT_SCRIPT_COMPLETE = "jclouds.compute.timeout.script-complete";
public static final String PROPERTY_TIMEOUT_PORT_OPEN = "jclouds.compute.timeout.port-open";
/**
* comma-separated nodes that we shouldn't attempt to list as they are dead
* in the provider for some reason.
* comma-separated nodes that we shouldn't attempt to list as they are dead in the provider for
* some reason.
*/
public static final String PROPERTY_BLACKLIST_NODES = "jclouds.compute.blacklist.nodes";
public static final String PROPERTY_BLACKLIST_NODES = "jclouds.compute.blacklist-nodes";
/**
* os to map of version input string to output string
* <p/>
* ex.
*
* <pre>
* {"centos":{"5.4":"5.4","5.5":"5.5"},"rhel":{"5.4":"5.4","5.5":"5.5"},"ubuntu":{"karmic":"9.10","lucid":"10.04","maverick":"10.10","natty":"11.04"},"windows":{"2008":"2008","Server 2008":"2008","2008 R2":"2008 R2","Server 2008 R2":"2008 R2","2008 SP2":"2008 SP2","Server 2008 SP2":"2008 SP2"}}
* </pre>
*/
public static final String PROPERTY_OS_VERSION_MAP_JSON = "jclouds.compute.os-version-map-json";
@Singleton
public static class ReferenceData {
@Inject(optional = true)
@Named(PROPERTY_OS_VERSION_MAP_JSON)
public String osVersionMapJson = "{\"centos\":{\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\"},\"rhel\":{\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\"},\"ubuntu\":{\"hardy\":\"8.04\",\"karmic\":\"9.10\",\"lucid\":\"10.04\",\"maverick\":\"10.10\",\"natty\":\"11.04\"},\"windows\":{\"2003\":\"2003\",\"2003 Standard\":\"2003\",\"2008\":\"2008\",\"2008 Web\":\"2008\",\"Server 2008\":\"2008\",\"2008 R2\":\"2008 R2\",\"Server 2008 R2\":\"2008 R2\",\"2008 Server R2\":\"2008 R2\",\"2008 SP2\":\"2008 SP2\",\"Server 2008 SP2\":\"2008 SP2\"}}";
}
@Singleton
public static class Timeouts {

View File

@ -20,6 +20,8 @@
package org.jclouds.compute.stub.config;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject;
@ -46,6 +48,7 @@ import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
/**
*
@ -60,12 +63,13 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
private final String privateIpPrefix;
private final String passwordPrefix;
private final String providerName;
private final Map<OsFamily, Map<String, String>> osToVersionMap;
@Inject
public StubComputeServiceAdapter(ConcurrentMap<String, NodeMetadata> nodes, Supplier<Location> location,
@Named("NODE_ID") Provider<Integer> idProvider, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PASSWORD_PREFIX") String passwordPrefix,
@org.jclouds.rest.annotations.Provider String providerName) {
@org.jclouds.rest.annotations.Provider String providerName, Map<OsFamily, Map<String, String>> osToVersionMap) {
this.nodes = nodes;
this.location = location;
this.idProvider = idProvider;
@ -73,6 +77,7 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
this.privateIpPrefix = privateIpPrefix;
this.passwordPrefix = passwordPrefix;
this.providerName = providerName;
this.osToVersionMap = osToVersionMap;
}
@Override
@ -100,8 +105,8 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
@Override
public Iterable<Hardware> listHardwareProfiles() {
return ImmutableSet.<Hardware> of(StubComputeServiceDependenciesModule.stub("small", 1, 1740, 160),
StubComputeServiceDependenciesModule.stub("medium", 4, 7680, 850), StubComputeServiceDependenciesModule
.stub("large", 8, 15360, 1690));
StubComputeServiceDependenciesModule.stub("medium", 4, 7680, 850),
StubComputeServiceDependenciesModule.stub("large", 8, 15360, 1690));
}
@Override
@ -109,20 +114,19 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
Location zone = location.get().getParent();
String parentId = zone.getId();
Credentials defaultCredentials = new Credentials("root", null);
return ImmutableSet.<Image> of(new ImageBuilder().providerId("1").name(OsFamily.UBUNTU.name())
.id(parentId + "/1").location(zone).operatingSystem(
new OperatingSystem(OsFamily.UBUNTU, "ubuntu 32", null, "X86_32", "ubuntu 32", false))
.description("stub ubuntu 32").defaultCredentials(defaultCredentials).build(), //
new ImageBuilder().providerId("2").name(OsFamily.UBUNTU.name()).id(parentId + "/2").location(zone)
.operatingSystem(
new OperatingSystem(OsFamily.UBUNTU, "ubuntu 64", null, "X86_64", "ubuntu 64", true))
.description("stub ubuntu 64").defaultCredentials(defaultCredentials).build(), //
new ImageBuilder().providerId("3").name(OsFamily.CENTOS.name()).id(parentId + "/3").location(zone)
.operatingSystem(
new OperatingSystem(OsFamily.CENTOS, "centos 64", null, "X86_64", "centos 64", true))
.description("stub centos 64").defaultCredentials(defaultCredentials).build() //
);
Set<Image> images = Sets.newLinkedHashSet();
int id = 1;
for (boolean is64Bit : new boolean[] { true, false })
for (Entry<OsFamily, Map<String, String>> osVersions : this.osToVersionMap.entrySet()) {
for (String version : Sets.newHashSet(osVersions.getValue().values())) {
String desc = String.format("stub %s %s", osVersions.getKey(), is64Bit);
images.add(new ImageBuilder().providerId(id + "").name(osVersions.getKey().name())
.id(parentId + "/" + id++).location(zone)
.operatingSystem(new OperatingSystem(osVersions.getKey(), desc, version, null, desc, is64Bit))
.description(desc).defaultCredentials(defaultCredentials).build());
}
}
return images;
}
@Override

View File

@ -38,7 +38,6 @@ import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jclouds.compute.ComputeServiceContextBuilder;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Hardware;
@ -56,7 +55,7 @@ import org.jclouds.ssh.SshClient;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/**
*
@ -131,33 +130,6 @@ public class ComputeServiceUtils {
return total;
}
public static final Map<org.jclouds.compute.domain.OsFamily, Map<String, String>> NAME_VERSION_MAP = ImmutableMap
.<org.jclouds.compute.domain.OsFamily, Map<String, String>> of(
org.jclouds.compute.domain.OsFamily.CENTOS,
ImmutableMap.<String, String> builder().put("5.3", "5.3").put("5.4", "5.4").put("5.5", "5.5").build(),
org.jclouds.compute.domain.OsFamily.RHEL,
ImmutableMap.<String, String> builder().put("5.3", "5.3").put("5.4", "5.4").put("5.5", "5.5").build(),
org.jclouds.compute.domain.OsFamily.UBUNTU,
ImmutableMap.<String, String> builder().put("hardy", "8.04").put("intrepid", "8.10")
.put("jaunty", "9.04").put("karmic", "9.10").put("lucid", "10.04").put("maverick", "10.10")
.put("natty", "11.04").build());
public static String parseVersionOrReturnEmptyString(org.jclouds.compute.domain.OsFamily family, final String in) {
if (NAME_VERSION_MAP.containsKey(family)) {
CONTAINS_SUBSTRING contains = new CONTAINS_SUBSTRING(in.replace('-', '.'));
try {
String key = find(NAME_VERSION_MAP.get(family).keySet(), contains);
return NAME_VERSION_MAP.get(family).get(key);
} catch (NoSuchElementException e) {
try {
return find(NAME_VERSION_MAP.get(family).values(), contains);
} catch (NoSuchElementException e1) {
}
}
}
return "";
}
public static org.jclouds.compute.domain.OsFamily parseOsFamilyOrNull(String provider, String in) {
org.jclouds.compute.domain.OsFamily myOs = null;
for (org.jclouds.compute.domain.OsFamily os : org.jclouds.compute.domain.OsFamily.values()) {
@ -201,19 +173,6 @@ public class ComputeServiceUtils {
});
}
private static final class CONTAINS_SUBSTRING implements Predicate<String> {
private final String in;
private CONTAINS_SUBSTRING(String in) {
this.in = in;
}
@Override
public boolean apply(String input) {
return in.indexOf(input) != -1;
}
}
public static interface SshCallable<T> extends Callable<T> {
NodeMetadata getNode();
@ -249,4 +208,36 @@ public class ComputeServiceUtils {
"node does not have IP addresses configured: " + node);
}
public static String parseVersionOrReturnEmptyString(org.jclouds.compute.domain.OsFamily family, final String in,
Map<OsFamily, Map<String, String>> osVersionMap) {
if (osVersionMap.containsKey(family)) {
if (osVersionMap.get(family).containsKey(in))
return osVersionMap.get(family).get(in);
CONTAINS_SUBSTRING contains = new CONTAINS_SUBSTRING(in.replace('-', '.'));
try {
String key = Iterables.find(osVersionMap.get(family).keySet(), contains);
return osVersionMap.get(family).get(key);
} catch (NoSuchElementException e) {
try {
return Iterables.find(osVersionMap.get(family).values(), contains);
} catch (NoSuchElementException e1) {
}
}
}
return "";
}
static final class CONTAINS_SUBSTRING implements Predicate<String> {
private final String in;
CONTAINS_SUBSTRING(String in) {
this.in = in;
}
@Override
public boolean apply(String input) {
return in.indexOf(input) != -1;
}
}
}

View File

@ -55,6 +55,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
import org.jclouds.logging.Logger;
import org.jclouds.scriptbuilder.InitBuilder;
import org.jclouds.scriptbuilder.domain.AuthorizeRSAPublicKey;
import org.jclouds.scriptbuilder.domain.InstallRSAPrivateKey;
import org.jclouds.scriptbuilder.domain.Statement;
@ -144,8 +145,11 @@ public class ComputeUtils {
bootstrap.add(options.getRunScript());
if (options.getPrivateKey() != null)
bootstrap.add(new InstallRSAPrivateKey(options.getPrivateKey()));
if (bootstrap.size() >= 1)
if (bootstrap.size() >= 1) {
if (options.getTaskName() == null && !(options.getRunScript() instanceof InitBuilder))
options.nameTask("bootstrap");
runScriptOnNode(node, bootstrap.size() == 1 ? bootstrap.get(0) : new StatementList(bootstrap), options);
}
return node;
}

View File

@ -161,8 +161,8 @@ public abstract class BaseComputeServiceLiveTest {
if (context != null)
context.close();
Properties props = setupProperties();
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet.of(new Log4JLoggingModule(),
getSshModule()), props);
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()), props);
client = context.getComputeService();
}
@ -173,8 +173,8 @@ public abstract class BaseComputeServiceLiveTest {
public void testCorrectAuthException() throws Exception {
ComputeServiceContext context = null;
try {
context = new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA", ImmutableSet
.<Module> of(new Log4JLoggingModule()));
context = new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA",
ImmutableSet.<Module> of(new Log4JLoggingModule()));
context.getComputeService().listNodes();
} catch (AuthorizationException e) {
throw e;
@ -287,8 +287,8 @@ public abstract class BaseComputeServiceLiveTest {
protected void checkOsMatchesTemplate(NodeMetadata node) {
if (node.getOperatingSystem() != null)
assert node.getOperatingSystem().getFamily().equals(template.getImage().getOperatingSystem().getFamily()) : String
.format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(), node
.getOperatingSystem());
.format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(),
node.getOperatingSystem());
}
void assertLocationSameOrChild(Location test, Location expected) {
@ -322,8 +322,9 @@ public abstract class BaseComputeServiceLiveTest {
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String tag, OperatingSystem os,
Credentials creds) throws RunScriptOnNodesException {
try {
return client.runScriptOnNodesMatching(runningWithTag(tag), newStringPayload(buildScript(os).render(
OsFamily.UNIX)), overrideCredentialsWith(creds).nameTask("runScriptWithCreds"));
return client.runScriptOnNodesMatching(runningWithTag(tag),
newStringPayload(buildScript(os).render(OsFamily.UNIX)),
overrideCredentialsWith(creds).nameTask("runScriptWithCreds"));
} catch (SshException e) {
throw e;
}
@ -353,8 +354,8 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception {
Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex(filter(client
.listNodesDetailsMatching(all()), and(withTag(tag), not(TERMINATED))),
Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex(
filter(client.listNodesDetailsMatching(all()), and(withTag(tag), not(TERMINATED))),
new Function<NodeMetadata, String>() {
@Override
@ -372,8 +373,9 @@ public abstract class BaseComputeServiceLiveTest {
checkImageIdMatchesTemplate(metadata);
checkOsMatchesTemplate(metadata);
assertEquals(metadata.getState(), NodeState.RUNNING);
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
// due to DHCP the addresses can actually change in-between runs.
assertEquals(metadata.getPrivateAddresses().size(), node.getPrivateAddresses().size());
assertEquals(metadata.getPublicAddresses().size(), node.getPublicAddresses().size());
}
assertNodeZero(metadataMap.values());
}
@ -393,16 +395,20 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testReboot")
public void testSuspendResume() throws Exception {
client.suspendNodesMatching(withTag(tag));
Set<? extends NodeMetadata> stoppedNodes = refreshNodes();
assert Iterables.all(stoppedNodes, new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {
return input.getState() == NodeState.SUSPENDED;
boolean returnVal = input.getState() == NodeState.SUSPENDED;
if (!returnVal)
System.err.printf("warning: node %s in state %s%n", input.getId(), input.getState());
return returnVal;
}
}) : nodes;
}) : stoppedNodes;
client.resumeNodesMatching(withTag(tag));
testGet();

View File

@ -0,0 +1,173 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.jclouds.Constants;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.Guice;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
@Test(groups = "integration,live", testName = "compute.BaseTemplateBuilderLiveTest")
public abstract class BaseTemplateBuilderLiveTest {
protected String provider;
protected String identity;
protected String credential;
protected String endpoint;
protected String apiversion;
protected ComputeServiceContext context;
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
Properties overrides = new Properties();
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}
@BeforeClass
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException, IOException {
setupCredentials();
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), setupProperties());
}
@DataProvider(name = "osSupported")
public Object[][] osSupported() {
return convertToArray(Sets.filter(provideAllOperatingSystems(),
Predicates.not(defineUnsupportedOperatingSystems())));
}
protected Object[][] convertToArray(Set<OsFamilyVersion64Bit> supportedOperatingSystems) {
Object[][] returnVal = new Object[supportedOperatingSystems.size()][1];
int i = 0;
for (OsFamilyVersion64Bit config : supportedOperatingSystems)
returnVal[i++][0] = config;
return returnVal;
}
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return Predicates.alwaysFalse();
}
@DataProvider(name = "osNotSupported")
public Object[][] osNotSupported() {
return convertToArray(Sets.filter(provideAllOperatingSystems(), defineUnsupportedOperatingSystems()));
}
protected Set<OsFamilyVersion64Bit> provideAllOperatingSystems() {
Map<OsFamily, Map<String, String>> map = new BaseComputeServiceContextModule() {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(new GsonModule())
.getInstance(Json.class));
Set<OsFamilyVersion64Bit> supportedOperatingSystems = Sets.newHashSet();
for (Entry<OsFamily, Map<String, String>> osVersions : map.entrySet()) {
for (String version : Sets.newHashSet(osVersions.getValue().values())) {
supportedOperatingSystems.add(new OsFamilyVersion64Bit(osVersions.getKey(), version, false));
supportedOperatingSystems.add(new OsFamilyVersion64Bit(osVersions.getKey(), version, true));
}
}
return supportedOperatingSystems;
}
@Test(dataProvider = "osSupported")
public void testTemplateBuilderCanFind(OsFamilyVersion64Bit matrix) throws InterruptedException {
Template template = context.getComputeService().templateBuilder().osFamily(matrix.family)
.osVersionMatches("^" + matrix.version + "$").os64Bit(matrix.is64Bit).build();
assertEquals(template.getImage().getOperatingSystem().getVersion(), matrix.version);
assertEquals(template.getImage().getOperatingSystem().is64Bit(), matrix.is64Bit);
assertEquals(template.getImage().getOperatingSystem().getFamily(), matrix.family);
}
@Test(dataProvider = "osNotSupported", expectedExceptions = NoSuchElementException.class)
public void testTemplateBuilderCannotFind(OsFamilyVersion64Bit matrix) throws InterruptedException {
context.getComputeService().templateBuilder().osFamily(matrix.family)
.osVersionMatches("^" + matrix.version + "$").os64Bit(matrix.is64Bit).build();
}
@Test
public void testTemplateBuilderCanUseImageId() {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
Template template = context.getComputeService().templateBuilder().imageId(defaultTemplate.getImage().getId())
.build();
assertEquals(template.getImage(), defaultTemplate.getImage());
}
@Test
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
@AfterTest
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
context.close();
}
}

View File

@ -0,0 +1,70 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.compute;
import org.jclouds.compute.domain.OsFamily;
public class OsFamilyVersion64Bit {
public final OsFamily family;
public final String version;
public final boolean is64Bit;
public OsFamilyVersion64Bit(OsFamily family, String version, boolean is64Bit) {
this.family = family;
this.version = version;
this.is64Bit = is64Bit;
}
@Override
public String toString() {
return "OsFamilyVersion64Bit [family=" + family + ", version=" + version + ", is64Bit=" + is64Bit + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((family == null) ? 0 : family.hashCode());
result = prime * result + (is64Bit ? 1231 : 1237);
result = prime * result + ((version == null) ? 0 : version.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OsFamilyVersion64Bit other = (OsFamilyVersion64Bit) obj;
if (family != other.family)
return false;
if (is64Bit != other.is64Bit)
return false;
if (version == null) {
if (other.version != null)
return false;
} else if (!version.equals(other.version))
return false;
return true;
}
}

View File

@ -24,7 +24,6 @@ import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.reportMatcher;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import java.io.FileNotFoundException;
@ -38,8 +37,6 @@ import java.util.concurrent.TimeoutException;
import org.easymock.IArgumentMatcher;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.io.Payload;
import org.jclouds.net.IPSocket;
@ -50,7 +47,6 @@ import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException;
import org.jclouds.util.Utils;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Throwables;
@ -63,15 +59,13 @@ import com.google.inject.Module;
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true, testName = "stub.StubComputeServiceIntegrationTest")
@Test(groups = "live", testName = "stub.StubComputeServiceIntegrationTest")
public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTest {
private static final ExecResponse EXEC_GOOD = new ExecResponse("", "", 0);
private static final ExecResponse EXEC_BAD = new ExecResponse("", "", 1);
@BeforeClass
@Override
public void setServiceDefaults() {
public StubComputeServiceIntegrationTest() {
provider = "stub";
}
@ -79,15 +73,6 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
public void testCorrectAuthException() throws Exception {
}
@Test
public void testTemplateBuilder() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().getArch(), "X86_64");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), provider + "zone");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
protected void buildSocketTester() {
SocketOpen socketOpen = createMock(SocketOpen.class);
@ -149,20 +134,20 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
runScriptAndInstallSsh(client5, "bootstrap", 5);
expect(
factory.create(eq(new IPSocket("144.175.1.1", 22)), eq(new Credentials("root", keyPair
.get("private"))))).andReturn(client1);
factory.create(eq(new IPSocket("144.175.1.1", 22)),
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client1);
expect(
factory.create(eq(new IPSocket("144.175.1.2", 22)), eq(new Credentials("root", keyPair
.get("private"))))).andReturn(client2);
factory.create(eq(new IPSocket("144.175.1.2", 22)),
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client2);
expect(
factory.create(eq(new IPSocket("144.175.1.3", 22)), eq(new Credentials("root", keyPair
.get("private"))))).andReturn(client3);
factory.create(eq(new IPSocket("144.175.1.3", 22)),
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client3);
expect(
factory.create(eq(new IPSocket("144.175.1.4", 22)), eq(new Credentials("root", keyPair
.get("private"))))).andReturn(client4);
factory.create(eq(new IPSocket("144.175.1.4", 22)),
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client4);
expect(
factory.create(eq(new IPSocket("144.175.1.5", 22)), eq(new Credentials("root", keyPair
.get("private"))))).andReturn(client5);
factory.create(eq(new IPSocket("144.175.1.5", 22)),
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client5);
helloAndJava(client2);
helloAndJava(client3);
@ -321,6 +306,11 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
super.testImagesCache();
}
@Override
public void testCompareSizes() throws Exception {
super.testCompareSizes();
}
@Test(enabled = true, dependsOnMethods = { "testImagesCache" })
public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception {
super.testAScriptExecutionAfterBootWithBasicTemplate();

View File

@ -0,0 +1,41 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.compute;
import org.testng.annotations.Test;
/**
*
*
* @author Adrian Cole
*/
@Test(groups = { "integration", "live" }, testName = "stub.StubTemplateBuilderIntegrationTest")
public class StubTemplateBuilderIntegrationTest extends BaseTemplateBuilderLiveTest {
public StubTemplateBuilderIntegrationTest() {
provider = "stub";
}
@Override
protected void setupCredentials() {
identity = "stub";
credential = "stub";
}
}

View File

@ -0,0 +1,928 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.
* ====================================================================
*/
/*
* Copyright (C) 2008 Google Inc.
*
* 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 com.google.gson;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedSet;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.UUID;
import com.google.common.base.Function;
import com.google.common.collect.MapMaker;
/**
* List of all the default type adapters ({@link JsonSerializer}s, {@link JsonDeserializer}s, and
* {@link InstanceCreator}s.
*
* <h4>Note!</h4>
* changed to edit the default behaviour of enum parsing by Adrian Cole
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class JcloudsDefaultTypeAdapters {
private static final DefaultDateTypeAdapter DATE_TYPE_ADAPTER = new DefaultDateTypeAdapter();
private static final DefaultJavaSqlDateTypeAdapter JAVA_SQL_DATE_TYPE_ADAPTER = new DefaultJavaSqlDateTypeAdapter();
private static final DefaultTimeTypeAdapter TIME_TYPE_ADAPTER = new DefaultTimeTypeAdapter();
private static final DefaultTimestampDeserializer TIMESTAMP_DESERIALIZER = new DefaultTimestampDeserializer();
@SuppressWarnings({ "rawtypes" })
private static final EnumTypeAdapter ENUM_TYPE_ADAPTER = new EnumTypeAdapter();
private static final UrlTypeAdapter URL_TYPE_ADAPTER = new UrlTypeAdapter();
private static final UriTypeAdapter URI_TYPE_ADAPTER = new UriTypeAdapter();
private static final UuidTypeAdapter UUUID_TYPE_ADAPTER = new UuidTypeAdapter();
private static final LocaleTypeAdapter LOCALE_TYPE_ADAPTER = new LocaleTypeAdapter();
private static final CollectionTypeAdapter COLLECTION_TYPE_ADAPTER = new CollectionTypeAdapter();
private static final MapTypeAdapter MAP_TYPE_ADAPTER = new MapTypeAdapter();
private static final BigDecimalTypeAdapter BIG_DECIMAL_TYPE_ADAPTER = new BigDecimalTypeAdapter();
private static final BigIntegerTypeAdapter BIG_INTEGER_TYPE_ADAPTER = new BigIntegerTypeAdapter();
private static final BooleanTypeAdapter BOOLEAN_TYPE_ADAPTER = new BooleanTypeAdapter();
private static final ByteTypeAdapter BYTE_TYPE_ADAPTER = new ByteTypeAdapter();
private static final CharacterTypeAdapter CHARACTER_TYPE_ADAPTER = new CharacterTypeAdapter();
private static final DoubleDeserializer DOUBLE_TYPE_ADAPTER = new DoubleDeserializer();
private static final FloatDeserializer FLOAT_TYPE_ADAPTER = new FloatDeserializer();
private static final IntegerTypeAdapter INTEGER_TYPE_ADAPTER = new IntegerTypeAdapter();
private static final LongDeserializer LONG_DESERIALIZER = new LongDeserializer();
private static final NumberTypeAdapter NUMBER_TYPE_ADAPTER = new NumberTypeAdapter();
private static final ShortTypeAdapter SHORT_TYPE_ADAPTER = new ShortTypeAdapter();
private static final StringTypeAdapter STRING_TYPE_ADAPTER = new StringTypeAdapter();
private static final PropertiesCreator PROPERTIES_CREATOR = new PropertiesCreator();
private static final TreeSetCreator TREE_SET_CREATOR = new TreeSetCreator();
private static final HashSetCreator HASH_SET_CREATOR = new HashSetCreator();
private static final GregorianCalendarTypeAdapter GREGORIAN_CALENDAR_TYPE_ADAPTER = new GregorianCalendarTypeAdapter();
// The constants DEFAULT_SERIALIZERS, DEFAULT_DESERIALIZERS, and DEFAULT_INSTANCE_CREATORS
// must be defined after the constants for the type adapters. Otherwise, the type adapter
// constants will appear as nulls.
private static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS = createDefaultSerializers();
private static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS = createDefaultDeserializers();
private static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS = createDefaultInstanceCreators();
private static ParameterizedTypeHandlerMap<JsonSerializer<?>> createDefaultSerializers() {
ParameterizedTypeHandlerMap<JsonSerializer<?>> map = new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
map.registerForTypeHierarchy(Enum.class, ENUM_TYPE_ADAPTER);
map.register(URL.class, URL_TYPE_ADAPTER);
map.register(URI.class, URI_TYPE_ADAPTER);
map.register(UUID.class, UUUID_TYPE_ADAPTER);
map.register(Locale.class, LOCALE_TYPE_ADAPTER);
map.registerForTypeHierarchy(Collection.class, COLLECTION_TYPE_ADAPTER);
map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER);
map.register(Date.class, DATE_TYPE_ADAPTER);
map.register(java.sql.Date.class, JAVA_SQL_DATE_TYPE_ADAPTER);
map.register(Timestamp.class, DATE_TYPE_ADAPTER);
map.register(Time.class, TIME_TYPE_ADAPTER);
map.register(Calendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER);
map.register(GregorianCalendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER);
map.register(BigDecimal.class, BIG_DECIMAL_TYPE_ADAPTER);
map.register(BigInteger.class, BIG_INTEGER_TYPE_ADAPTER);
// Add primitive serializers
map.register(Boolean.class, BOOLEAN_TYPE_ADAPTER);
map.register(boolean.class, BOOLEAN_TYPE_ADAPTER);
map.register(Byte.class, BYTE_TYPE_ADAPTER);
map.register(byte.class, BYTE_TYPE_ADAPTER);
map.register(Character.class, CHARACTER_TYPE_ADAPTER);
map.register(char.class, CHARACTER_TYPE_ADAPTER);
map.register(Integer.class, INTEGER_TYPE_ADAPTER);
map.register(int.class, INTEGER_TYPE_ADAPTER);
map.register(Number.class, NUMBER_TYPE_ADAPTER);
map.register(Short.class, SHORT_TYPE_ADAPTER);
map.register(short.class, SHORT_TYPE_ADAPTER);
map.register(String.class, STRING_TYPE_ADAPTER);
map.makeUnmodifiable();
return map;
}
private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> createDefaultDeserializers() {
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map = new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
map.registerForTypeHierarchy(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER));
map.register(URL.class, wrapDeserializer(URL_TYPE_ADAPTER));
map.register(URI.class, wrapDeserializer(URI_TYPE_ADAPTER));
map.register(UUID.class, wrapDeserializer(UUUID_TYPE_ADAPTER));
map.register(Locale.class, wrapDeserializer(LOCALE_TYPE_ADAPTER));
map.registerForTypeHierarchy(Collection.class, wrapDeserializer(COLLECTION_TYPE_ADAPTER));
map.registerForTypeHierarchy(Map.class, wrapDeserializer(MAP_TYPE_ADAPTER));
map.register(Date.class, wrapDeserializer(DATE_TYPE_ADAPTER));
map.register(java.sql.Date.class, wrapDeserializer(JAVA_SQL_DATE_TYPE_ADAPTER));
map.register(Timestamp.class, wrapDeserializer(TIMESTAMP_DESERIALIZER));
map.register(Time.class, wrapDeserializer(TIME_TYPE_ADAPTER));
map.register(Calendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER);
map.register(GregorianCalendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER);
map.register(BigDecimal.class, wrapDeserializer(BIG_DECIMAL_TYPE_ADAPTER));
map.register(BigInteger.class, wrapDeserializer(BIG_INTEGER_TYPE_ADAPTER));
// Add primitive deserializers
map.register(Boolean.class, wrapDeserializer(BOOLEAN_TYPE_ADAPTER));
map.register(boolean.class, wrapDeserializer(BOOLEAN_TYPE_ADAPTER));
map.register(Byte.class, wrapDeserializer(BYTE_TYPE_ADAPTER));
map.register(byte.class, wrapDeserializer(BYTE_TYPE_ADAPTER));
map.register(Character.class, wrapDeserializer(CHARACTER_TYPE_ADAPTER));
map.register(char.class, wrapDeserializer(CHARACTER_TYPE_ADAPTER));
map.register(Double.class, wrapDeserializer(DOUBLE_TYPE_ADAPTER));
map.register(double.class, wrapDeserializer(DOUBLE_TYPE_ADAPTER));
map.register(Float.class, wrapDeserializer(FLOAT_TYPE_ADAPTER));
map.register(float.class, wrapDeserializer(FLOAT_TYPE_ADAPTER));
map.register(Integer.class, wrapDeserializer(INTEGER_TYPE_ADAPTER));
map.register(int.class, wrapDeserializer(INTEGER_TYPE_ADAPTER));
map.register(Long.class, wrapDeserializer(LONG_DESERIALIZER));
map.register(long.class, wrapDeserializer(LONG_DESERIALIZER));
map.register(Number.class, wrapDeserializer(NUMBER_TYPE_ADAPTER));
map.register(Short.class, wrapDeserializer(SHORT_TYPE_ADAPTER));
map.register(short.class, wrapDeserializer(SHORT_TYPE_ADAPTER));
map.register(String.class, wrapDeserializer(STRING_TYPE_ADAPTER));
map.makeUnmodifiable();
return map;
}
private static ParameterizedTypeHandlerMap<InstanceCreator<?>> createDefaultInstanceCreators() {
ParameterizedTypeHandlerMap<InstanceCreator<?>> map = new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER);
// Add Collection type instance creators
map.registerForTypeHierarchy(Collection.class, COLLECTION_TYPE_ADAPTER);
map.registerForTypeHierarchy(Set.class, HASH_SET_CREATOR);
map.registerForTypeHierarchy(SortedSet.class, TREE_SET_CREATOR);
map.register(Properties.class, PROPERTIES_CREATOR);
map.makeUnmodifiable();
return map;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static JsonDeserializer<?> wrapDeserializer(JsonDeserializer<?> deserializer) {
return new JsonDeserializerExceptionWrapper(deserializer);
}
static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers() {
return getDefaultSerializers(false, LongSerializationPolicy.DEFAULT);
}
static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers(
boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy) {
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers = new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
// Double primitive
JcloudsDefaultTypeAdapters.DoubleSerializer doubleSerializer = new JcloudsDefaultTypeAdapters.DoubleSerializer(
serializeSpecialFloatingPointValues);
serializers.registerIfAbsent(Double.class, doubleSerializer);
serializers.registerIfAbsent(double.class, doubleSerializer);
// Float primitive
JcloudsDefaultTypeAdapters.FloatSerializer floatSerializer = new JcloudsDefaultTypeAdapters.FloatSerializer(
serializeSpecialFloatingPointValues);
serializers.registerIfAbsent(Float.class, floatSerializer);
serializers.registerIfAbsent(float.class, floatSerializer);
// Long primitive
JcloudsDefaultTypeAdapters.LongSerializer longSerializer = new JcloudsDefaultTypeAdapters.LongSerializer(
longSerializationPolicy);
serializers.registerIfAbsent(Long.class, longSerializer);
serializers.registerIfAbsent(long.class, longSerializer);
serializers.registerIfAbsent(DEFAULT_SERIALIZERS);
return serializers;
}
static ParameterizedTypeHandlerMap<JsonDeserializer<?>> getDefaultDeserializers() {
return DEFAULT_DESERIALIZERS;
}
static ParameterizedTypeHandlerMap<InstanceCreator<?>> getDefaultInstanceCreators() {
return DEFAULT_INSTANCE_CREATORS;
}
static class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
private final DateFormat format;
DefaultDateTypeAdapter() {
this.format = DateFormat.getDateTimeInstance();
}
DefaultDateTypeAdapter(final String datePattern) {
this.format = new SimpleDateFormat(datePattern);
}
DefaultDateTypeAdapter(final int style) {
this.format = DateFormat.getDateInstance(style);
}
public DefaultDateTypeAdapter(final int dateStyle, final int timeStyle) {
this.format = DateFormat.getDateTimeInstance(dateStyle, timeStyle);
}
// These methods need to be synchronized since JDK DateFormat classes are not thread-safe
// See issue 162
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
synchronized (format) {
String dateFormatAsString = format.format(src);
return new JsonPrimitive(dateFormatAsString);
}
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (!(json instanceof JsonPrimitive)) {
throw new JsonParseException("The date should be a string value");
}
try {
synchronized (format) {
return format.parse(json.getAsString());
}
} catch (ParseException e) {
throw new JsonParseException(e);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(DefaultDateTypeAdapter.class.getSimpleName());
sb.append('(').append(format.getClass().getSimpleName()).append(')');
return sb.toString();
}
}
static class DefaultJavaSqlDateTypeAdapter implements JsonSerializer<java.sql.Date>, JsonDeserializer<java.sql.Date> {
private final DateFormat format;
DefaultJavaSqlDateTypeAdapter() {
this.format = new SimpleDateFormat("MMM d, yyyy");
}
public JsonElement serialize(java.sql.Date src, Type typeOfSrc, JsonSerializationContext context) {
synchronized (format) {
String dateFormatAsString = format.format(src);
return new JsonPrimitive(dateFormatAsString);
}
}
public java.sql.Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (!(json instanceof JsonPrimitive)) {
throw new JsonParseException("The date should be a string value");
}
try {
synchronized (format) {
Date date = format.parse(json.getAsString());
return new java.sql.Date(date.getTime());
}
} catch (ParseException e) {
throw new JsonParseException(e);
}
}
}
static class DefaultTimestampDeserializer implements JsonDeserializer<Timestamp> {
public Timestamp deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
Date date = context.deserialize(json, Date.class);
return new Timestamp(date.getTime());
}
}
static class DefaultTimeTypeAdapter implements JsonSerializer<Time>, JsonDeserializer<Time> {
private final DateFormat format;
DefaultTimeTypeAdapter() {
this.format = new SimpleDateFormat("hh:mm:ss a");
}
public JsonElement serialize(Time src, Type typeOfSrc, JsonSerializationContext context) {
synchronized (format) {
String dateFormatAsString = format.format(src);
return new JsonPrimitive(dateFormatAsString);
}
}
public Time deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (!(json instanceof JsonPrimitive)) {
throw new JsonParseException("The date should be a string value");
}
try {
synchronized (format) {
Date date = format.parse(json.getAsString());
return new Time(date.getTime());
}
} catch (ParseException e) {
throw new JsonParseException(e);
}
}
}
private static class GregorianCalendarTypeAdapter implements JsonSerializer<GregorianCalendar>,
JsonDeserializer<GregorianCalendar> {
private static final String YEAR = "year";
private static final String MONTH = "month";
private static final String DAY_OF_MONTH = "dayOfMonth";
private static final String HOUR_OF_DAY = "hourOfDay";
private static final String MINUTE = "minute";
private static final String SECOND = "second";
public JsonElement serialize(GregorianCalendar src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject obj = new JsonObject();
obj.addProperty(YEAR, src.get(Calendar.YEAR));
obj.addProperty(MONTH, src.get(Calendar.MONTH));
obj.addProperty(DAY_OF_MONTH, src.get(Calendar.DAY_OF_MONTH));
obj.addProperty(HOUR_OF_DAY, src.get(Calendar.HOUR_OF_DAY));
obj.addProperty(MINUTE, src.get(Calendar.MINUTE));
obj.addProperty(SECOND, src.get(Calendar.SECOND));
return obj;
}
public GregorianCalendar deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
JsonObject obj = json.getAsJsonObject();
int year = obj.get(YEAR).getAsInt();
int month = obj.get(MONTH).getAsInt();
int dayOfMonth = obj.get(DAY_OF_MONTH).getAsInt();
int hourOfDay = obj.get(HOUR_OF_DAY).getAsInt();
int minute = obj.get(MINUTE).getAsInt();
int second = obj.get(SECOND).getAsInt();
return new GregorianCalendar(year, month, dayOfMonth, hourOfDay, minute, second);
}
@Override
public String toString() {
return GregorianCalendarTypeAdapter.class.getSimpleName();
}
}
@SuppressWarnings("unchecked")
private static class EnumTypeAdapter<T extends Enum<T>> implements JsonSerializer<T>, JsonDeserializer<T> {
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.name());
}
@SuppressWarnings("cast")
public T deserialize(JsonElement json, Type classOfT, JsonDeserializationContext context)
throws JsonParseException {
try {
return (T) Enum.valueOf((Class<T>) classOfT, json.getAsString());
} catch (IllegalArgumentException e) {
Method converter = classToConvert.get(classOfT);
if (converter != null)
try {
return (T) converter.invoke(null, json.getAsString());
} catch (Exception e1) {
throw e;
}
else
throw e;
}
}
private final static Map<Class<?>, Method> classToConvert = new MapMaker()
.makeComputingMap(new Function<Class<?>, Method>() {
@Override
public Method apply(Class<?> from) {
try {
Method method = from.getMethod("fromValue", String.class);
method.setAccessible(true);
return method;
} catch (Exception e) {
return null;
}
}
});
@Override
public String toString() {
return EnumTypeAdapter.class.getSimpleName();
}
}
private static class UrlTypeAdapter implements JsonSerializer<URL>, JsonDeserializer<URL> {
public JsonElement serialize(URL src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toExternalForm());
}
public URL deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
try {
return new URL(json.getAsString());
} catch (MalformedURLException e) {
throw new JsonParseException(e);
}
}
@Override
public String toString() {
return UrlTypeAdapter.class.getSimpleName();
}
}
private static class UriTypeAdapter implements JsonSerializer<URI>, JsonDeserializer<URI> {
public JsonElement serialize(URI src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toASCIIString());
}
public URI deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
try {
return new URI(json.getAsString());
} catch (URISyntaxException e) {
throw new JsonParseException(e);
}
}
@Override
public String toString() {
return UriTypeAdapter.class.getSimpleName();
}
}
private static class UuidTypeAdapter implements JsonSerializer<UUID>, JsonDeserializer<UUID> {
public JsonElement serialize(UUID src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toString());
}
public UUID deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return UUID.fromString(json.getAsString());
}
@Override
public String toString() {
return UuidTypeAdapter.class.getSimpleName();
}
}
private static class LocaleTypeAdapter implements JsonSerializer<Locale>, JsonDeserializer<Locale> {
public JsonElement serialize(Locale src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toString());
}
public Locale deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String locale = json.getAsString();
StringTokenizer tokenizer = new StringTokenizer(locale, "_");
String language = null;
String country = null;
String variant = null;
if (tokenizer.hasMoreElements()) {
language = tokenizer.nextToken();
}
if (tokenizer.hasMoreElements()) {
country = tokenizer.nextToken();
}
if (tokenizer.hasMoreElements()) {
variant = tokenizer.nextToken();
}
if (country == null && variant == null) {
return new Locale(language);
} else if (variant == null) {
return new Locale(language, country);
} else {
return new Locale(language, country, variant);
}
}
@Override
public String toString() {
return LocaleTypeAdapter.class.getSimpleName();
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static class CollectionTypeAdapter implements JsonSerializer<Collection>, JsonDeserializer<Collection>,
InstanceCreator<Collection> {
public JsonElement serialize(Collection src, Type typeOfSrc, JsonSerializationContext context) {
if (src == null) {
return JsonNull.createJsonNull();
}
JsonArray array = new JsonArray();
Type childGenericType = null;
if (typeOfSrc instanceof ParameterizedType) {
childGenericType = new TypeInfoCollection(typeOfSrc).getElementType();
}
for (Object child : src) {
if (child == null) {
array.add(JsonNull.createJsonNull());
} else {
Type childType = (childGenericType == null || childGenericType == Object.class) ? child.getClass()
: childGenericType;
JsonElement element = context.serialize(child, childType);
array.add(element);
}
}
return array;
}
public Collection deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (json.isJsonNull()) {
return null;
}
// Use ObjectConstructor to create instance instead of hard-coding a specific type.
// This handles cases where users are using their own subclass of Collection.
Collection collection = constructCollectionType(typeOfT, context);
Type childType = new TypeInfoCollection(typeOfT).getElementType();
for (JsonElement childElement : json.getAsJsonArray()) {
if (childElement == null || childElement.isJsonNull()) {
collection.add(null);
} else {
Object value = context.deserialize(childElement, childType);
collection.add(value);
}
}
return collection;
}
private Collection constructCollectionType(Type collectionType, JsonDeserializationContext context) {
JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context;
ObjectConstructor objectConstructor = contextImpl.getObjectConstructor();
return (Collection) objectConstructor.construct(collectionType);
}
public Collection createInstance(Type type) {
return new LinkedList();
}
}
private static class PropertiesCreator implements InstanceCreator<Properties> {
public Properties createInstance(Type type) {
return new Properties();
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
static class MapTypeAdapter implements JsonSerializer<Map>, JsonDeserializer<Map>, InstanceCreator<Map> {
public JsonElement serialize(Map src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject map = new JsonObject();
Type childGenericType = null;
if (typeOfSrc instanceof ParameterizedType) {
childGenericType = new TypeInfoMap(typeOfSrc).getValueType();
}
for (Map.Entry entry : (Set<Map.Entry>) src.entrySet()) {
Object value = entry.getValue();
JsonElement valueElement;
if (value == null) {
valueElement = JsonNull.createJsonNull();
} else {
Type childType = (childGenericType == null) ? value.getClass() : childGenericType;
valueElement = context.serialize(value, childType);
}
map.add(String.valueOf(entry.getKey()), valueElement);
}
return map;
}
public Map deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
// Use ObjectConstructor to create instance instead of hard-coding a specific type.
// This handles cases where users are using their own subclass of Map.
Map<Object, Object> map = constructMapType(typeOfT, context);
TypeInfoMap mapTypeInfo = new TypeInfoMap(typeOfT);
for (Map.Entry<String, JsonElement> entry : json.getAsJsonObject().entrySet()) {
Object key = context.deserialize(new JsonPrimitive(entry.getKey()), mapTypeInfo.getKeyType());
Object value = context.deserialize(entry.getValue(), mapTypeInfo.getValueType());
map.put(key, value);
}
return map;
}
private Map constructMapType(Type mapType, JsonDeserializationContext context) {
JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context;
ObjectConstructor objectConstructor = contextImpl.getObjectConstructor();
return (Map) objectConstructor.construct(mapType);
}
public Map createInstance(Type type) {
return new LinkedHashMap();
}
@Override
public String toString() {
return MapTypeAdapter.class.getSimpleName();
}
}
private static class BigDecimalTypeAdapter implements JsonSerializer<BigDecimal>, JsonDeserializer<BigDecimal> {
public JsonElement serialize(BigDecimal src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src);
}
public BigDecimal deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsBigDecimal();
}
@Override
public String toString() {
return BigDecimalTypeAdapter.class.getSimpleName();
}
}
private static class BigIntegerTypeAdapter implements JsonSerializer<BigInteger>, JsonDeserializer<BigInteger> {
public JsonElement serialize(BigInteger src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src);
}
public BigInteger deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsBigInteger();
}
@Override
public String toString() {
return BigIntegerTypeAdapter.class.getSimpleName();
}
}
private static class NumberTypeAdapter implements JsonSerializer<Number>, JsonDeserializer<Number> {
public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src);
}
public Number deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsNumber();
}
@Override
public String toString() {
return NumberTypeAdapter.class.getSimpleName();
}
}
private static class LongSerializer implements JsonSerializer<Long> {
private final LongSerializationPolicy longSerializationPolicy;
private LongSerializer(LongSerializationPolicy longSerializationPolicy) {
this.longSerializationPolicy = longSerializationPolicy;
}
public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) {
return longSerializationPolicy.serialize(src);
}
@Override
public String toString() {
return LongSerializer.class.getSimpleName();
}
}
private static class LongDeserializer implements JsonDeserializer<Long> {
public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsLong();
}
@Override
public String toString() {
return LongDeserializer.class.getSimpleName();
}
}
private static class IntegerTypeAdapter implements JsonSerializer<Integer>, JsonDeserializer<Integer> {
public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src);
}
public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsInt();
}
@Override
public String toString() {
return IntegerTypeAdapter.class.getSimpleName();
}
}
private static class ShortTypeAdapter implements JsonSerializer<Short>, JsonDeserializer<Short> {
public JsonElement serialize(Short src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src);
}
public Short deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsShort();
}
@Override
public String toString() {
return ShortTypeAdapter.class.getSimpleName();
}
}
private static class ByteTypeAdapter implements JsonSerializer<Byte>, JsonDeserializer<Byte> {
public JsonElement serialize(Byte src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src);
}
public Byte deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsByte();
}
@Override
public String toString() {
return ByteTypeAdapter.class.getSimpleName();
}
}
static class FloatSerializer implements JsonSerializer<Float> {
private final boolean serializeSpecialFloatingPointValues;
FloatSerializer(boolean serializeSpecialDoubleValues) {
this.serializeSpecialFloatingPointValues = serializeSpecialDoubleValues;
}
public JsonElement serialize(Float src, Type typeOfSrc, JsonSerializationContext context) {
if (!serializeSpecialFloatingPointValues) {
if (Float.isNaN(src) || Float.isInfinite(src)) {
throw new IllegalArgumentException(src
+ " is not a valid float value as per JSON specification. To override this"
+ " behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method.");
}
}
return new JsonPrimitive(src);
}
}
private static class FloatDeserializer implements JsonDeserializer<Float> {
public Float deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsFloat();
}
@Override
public String toString() {
return FloatDeserializer.class.getSimpleName();
}
}
static class DoubleSerializer implements JsonSerializer<Double> {
private final boolean serializeSpecialFloatingPointValues;
DoubleSerializer(boolean serializeSpecialDoubleValues) {
this.serializeSpecialFloatingPointValues = serializeSpecialDoubleValues;
}
public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
if (!serializeSpecialFloatingPointValues) {
if (Double.isNaN(src) || Double.isInfinite(src)) {
throw new IllegalArgumentException(src
+ " is not a valid double value as per JSON specification. To override this"
+ " behavior, use GsonBuilder.serializeSpecialDoubleValues() method.");
}
}
return new JsonPrimitive(src);
}
}
private static class DoubleDeserializer implements JsonDeserializer<Double> {
public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsDouble();
}
@Override
public String toString() {
return DoubleDeserializer.class.getSimpleName();
}
}
private static class CharacterTypeAdapter implements JsonSerializer<Character>, JsonDeserializer<Character> {
public JsonElement serialize(Character src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src);
}
public Character deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsCharacter();
}
@Override
public String toString() {
return CharacterTypeAdapter.class.getSimpleName();
}
}
private static class StringTypeAdapter implements JsonSerializer<String>, JsonDeserializer<String> {
public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src);
}
public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsString();
}
@Override
public String toString() {
return StringTypeAdapter.class.getSimpleName();
}
}
private static class BooleanTypeAdapter implements JsonSerializer<Boolean>, JsonDeserializer<Boolean> {
public JsonElement serialize(Boolean src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src);
}
public Boolean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return json.getAsBoolean();
}
@Override
public String toString() {
return BooleanTypeAdapter.class.getSimpleName();
}
}
private static class TreeSetCreator implements InstanceCreator<TreeSet<?>> {
public TreeSet<?> createInstance(Type type) {
return new TreeSet<Object>();
}
@Override
public String toString() {
return TreeSetCreator.class.getSimpleName();
}
}
private static class HashSetCreator implements InstanceCreator<HashSet<?>> {
public HashSet<?> createInstance(Type type) {
return new HashSet<Object>();
}
@Override
public String toString() {
return HashSetCreator.class.getSimpleName();
}
}
}

View File

@ -0,0 +1,591 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.
* ====================================================================
*/
/*
* Copyright (C) 2008 Google Inc.
*
* 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 com.google.gson;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import com.google.gson.JcloudsDefaultTypeAdapters.DefaultDateTypeAdapter;
/**
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
* options other than the default. For {@link Gson} with default configuration, it is simpler to
* use {@code new Gson()}. {@code JcloudsGsonBuilder} is best used by creating it, and then invoking its
* various configuration methods, and finally calling create.</p>
*
* <p>The following is an example shows how to use the {@code JcloudsGsonBuilder} to construct a Gson
* instance:
*
* <pre>
* Gson gson = new JcloudsGsonBuilder()
* .registerTypeAdapter(Id.class, new IdTypeAdapter())
* .serializeNulls()
* .setDateFormat(DateFormat.LONG)
* .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
* .setPrettyPrinting()
* .setVersion(1.0)
* .create();
* </pre></p>
*
* <p>NOTE: the order of invocation of configuration methods does not matter.</p>
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JcloudsGsonBuilder {
private static final InnerClassExclusionStrategy innerClassExclusionStrategy =
new InnerClassExclusionStrategy();
private static final ExposeAnnotationSerializationExclusionStrategy
exposeAnnotationSerializationExclusionStrategy =
new ExposeAnnotationSerializationExclusionStrategy();
private static final ExposeAnnotationDeserializationExclusionStrategy
exposeAnnotationDeserializationExclusionStrategy =
new ExposeAnnotationDeserializationExclusionStrategy();
private final Collection<ExclusionStrategy> exclusionStrategies =
new HashSet<ExclusionStrategy>();
private double ignoreVersionsAfter;
private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
private boolean serializeInnerClasses;
private boolean excludeFieldsWithoutExposeAnnotation;
private LongSerializationPolicy longSerializationPolicy;
private FieldNamingStrategy2 fieldNamingPolicy;
private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators;
private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers;
private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
private boolean serializeNulls;
private String datePattern;
private int dateStyle;
private int timeStyle;
private boolean serializeSpecialFloatingPointValues;
private boolean escapeHtmlChars;
private boolean prettyPrinting;
private boolean generateNonExecutableJson;
/**
* Creates a JcloudsGsonBuilder instance that can be used to build Gson with various configuration
* settings. JcloudsGsonBuilder follows the builder pattern, and it is typically used by first
* invoking various configuration methods to set desired options, and finally calling
* {@link #create()}.
*/
public JcloudsGsonBuilder() {
// add default exclusion strategies
exclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
exclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
// setup default values
ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS;
serializeInnerClasses = true;
prettyPrinting = false;
escapeHtmlChars = true;
modifierBasedExclusionStrategy = Gson.DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY;
excludeFieldsWithoutExposeAnnotation = false;
longSerializationPolicy = LongSerializationPolicy.DEFAULT;
fieldNamingPolicy = Gson.DEFAULT_NAMING_POLICY;
instanceCreators = new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
serializers = new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
deserializers = new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
serializeNulls = false;
dateStyle = DateFormat.DEFAULT;
timeStyle = DateFormat.DEFAULT;
serializeSpecialFloatingPointValues = false;
generateNonExecutableJson = false;
}
/**
* Configures Gson to enable versioning support.
*
* @param ignoreVersionsAfter any field or type marked with a version higher than this value
* are ignored during serialization or deserialization.
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
public JcloudsGsonBuilder setVersion(double ignoreVersionsAfter) {
this.ignoreVersionsAfter = ignoreVersionsAfter;
return this;
}
/**
* Configures Gson to excludes all class fields that have the specified modifiers. By default,
* Gson will exclude all fields marked transient or static. This method will override that
* behavior.
*
* @param modifiers the field modifiers. You must use the modifiers specified in the
* {@link java.lang.reflect.Modifier} class. For example,
* {@link java.lang.reflect.Modifier#TRANSIENT},
* {@link java.lang.reflect.Modifier#STATIC}.
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
public JcloudsGsonBuilder excludeFieldsWithModifiers(int... modifiers) {
modifierBasedExclusionStrategy = new ModifierBasedExclusionStrategy(modifiers);
return this;
}
/**
* Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
* special text. This prevents attacks from third-party sites through script sourcing. See
* <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
* for details.
*
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public JcloudsGsonBuilder generateNonExecutableJson() {
this.generateNonExecutableJson = true;
return this;
}
/**
* Configures Gson to exclude all fields from consideration for serialization or deserialization
* that do not have the {@link com.google.gson.annotations.Expose} annotation.
*
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
public JcloudsGsonBuilder excludeFieldsWithoutExposeAnnotation() {
excludeFieldsWithoutExposeAnnotation = true;
return this;
}
/**
* Configure Gson to serialize null fields. By default, Gson omits all fields that are null
* during serialization.
*
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public JcloudsGsonBuilder serializeNulls() {
this.serializeNulls = true;
return this;
}
/**
* Configures Gson to exclude inner classes during serialization.
*
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public JcloudsGsonBuilder disableInnerClassSerialization() {
serializeInnerClasses = false;
return this;
}
/**
* Configures Gson to apply a specific serialization policy for {@code Long} and {@code long}
* objects.
*
* @param serializationPolicy the particular policy to use for serializing longs.
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public JcloudsGsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) {
this.longSerializationPolicy = serializationPolicy;
return this;
}
/**
* Configures Gson to apply a specific naming policy to an object's field during serialization
* and deserialization.
*
* @param namingConvention the JSON field naming convention to use for serialization and
* deserialization.
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
public JcloudsGsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) {
return setFieldNamingStrategy(namingConvention.getFieldNamingPolicy());
}
/**
* Configures Gson to apply a specific naming policy strategy to an object's field during
* serialization and deserialization.
*
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public JcloudsGsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
return setFieldNamingStrategy(new FieldNamingStrategy2Adapter(fieldNamingStrategy));
}
/**
* Configures Gson to apply a specific naming policy strategy to an object's field during
* serialization and deserialization.
*
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
JcloudsGsonBuilder setFieldNamingStrategy(FieldNamingStrategy2 fieldNamingStrategy) {
this.fieldNamingPolicy =
new SerializedNameAnnotationInterceptingNamingPolicy(fieldNamingStrategy);
return this;
}
/**
* Configures Gson to apply a set of exclusion strategies during both serialization and
* deserialization. Each of the {@code strategies} will be applied as a disjunction rule.
* This means that if one of the {@code strategies} suggests that a field (or class) should be
* skipped then that field (or object) is skipped during serializaiton/deserialization.
*
* @param strategies the set of strategy object to apply during object (de)serialization.
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.4
*/
public JcloudsGsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
for (ExclusionStrategy strategy : strategies) {
exclusionStrategies.add(strategy);
}
return this;
}
/**
* Configures Gson to output Json that fits in a page for pretty printing. This option only
* affects Json serialization.
*
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
public JcloudsGsonBuilder setPrettyPrinting() {
prettyPrinting = true;
return this;
}
/**
* By default, Gson escapes HTML characters such as &lt; &gt; etc. Use this option to configure
* Gson to pass-through HTML characters as is.
*
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public JcloudsGsonBuilder disableHtmlEscaping() {
this.escapeHtmlChars = false;
return this;
}
/**
* Configures Gson to serialize {@code Date} objects according to the pattern provided. You can
* call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
* will be used to decide the serialization format.
*
* <p>Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
* class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
* valid date and time patterns.</p>
*
* @param pattern the pattern that dates will be serialized/deserialized to/from
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public JcloudsGsonBuilder setDateFormat(String pattern) {
// TODO(Joel): Make this fail fast if it is an invalid date format
this.datePattern = pattern;
return this;
}
/**
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
* information on the valid style constants.</p>
*
* @param style the predefined date style that date objects will be serialized/deserialized
* to/from
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public JcloudsGsonBuilder setDateFormat(int style) {
this.dateStyle = style;
this.datePattern = null;
return this;
}
/**
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
* information on the valid style constants.</p>
*
* @param dateStyle the predefined date style that date objects will be serialized/deserialized
* to/from
* @param timeStyle the predefined style for the time portion of the date objects
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public JcloudsGsonBuilder setDateFormat(int dateStyle, int timeStyle) {
this.dateStyle = dateStyle;
this.timeStyle = timeStyle;
this.datePattern = null;
return this;
}
/**
* Configures Gson for custom serialization or deserialization. This method combines the
* registration of an {@link InstanceCreator}, {@link JsonSerializer}, and a
* {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements
* all the required interfaces for custom serialization with Gson. If an instance creator,
* serializer or deserializer was previously registered for the specified {@code type}, it is
* overwritten.
*
* @param type the type definition for the type adapter being registered
* @param typeAdapter This object must implement at least one of the {@link InstanceCreator},
* {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
public JcloudsGsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?>);
if (typeAdapter instanceof InstanceCreator<?>) {
registerInstanceCreator(type, (InstanceCreator<?>) typeAdapter);
}
if (typeAdapter instanceof JsonSerializer<?>) {
registerSerializer(type, (JsonSerializer<?>) typeAdapter);
}
if (typeAdapter instanceof JsonDeserializer<?>) {
registerDeserializer(type, (JsonDeserializer<?>) typeAdapter);
}
return this;
}
/**
* Configures Gson to use a custom {@link InstanceCreator} for the specified type. If an instance
* creator was previously registered for the specified class, it is overwritten. Since this method
* takes a type instead of a Class object, it can be used to register a specific handler for a
* generic type corresponding to a raw type.
*
* @param <T> the type for which instance creator is being registered
* @param typeOfT The Type definition for T
* @param instanceCreator the instance creator for T
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
private <T> JcloudsGsonBuilder registerInstanceCreator(Type typeOfT,
InstanceCreator<? extends T> instanceCreator) {
instanceCreators.register(typeOfT, instanceCreator);
return this;
}
/**
* Configures Gson to use a custom JSON serializer for the specified type. You should use this
* method if you want to register different serializers for different generic types corresponding
* to a raw type.
*
* @param <T> the type for which the serializer is being registered
* @param typeOfT The type definition for T
* @param serializer the custom serializer
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
private <T> JcloudsGsonBuilder registerSerializer(Type typeOfT, final JsonSerializer<T> serializer) {
serializers.register(typeOfT, serializer);
return this;
}
/**
* Configures Gson to use a custom JSON deserializer for the specified type. You should use this
* method if you want to register different deserializers for different generic types
* corresponding to a raw type.
*
* @param <T> the type for which the deserializer is being registered
* @param typeOfT The type definition for T
* @param deserializer the custom deserializer
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
*/
private <T> JcloudsGsonBuilder registerDeserializer(Type typeOfT, JsonDeserializer<T> deserializer) {
deserializers.register(typeOfT, new JsonDeserializerExceptionWrapper<T>(deserializer));
return this;
}
/**
* Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
* This method combines the registration of an {@link InstanceCreator}, {@link JsonSerializer},
* and a {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter}
* implements all the required interfaces for custom serialization with Gson.
* If an instance creator, serializer or deserializer was previously registered for the specified
* type hierarchy, it is overwritten. If an instance creator, serializer or deserializer is
* registered for a specific type in the type hierarchy, it will be invoked instead of the one
* registered for the type hierarchy.
*
* @param baseType the class definition for the type adapter being registered for the base class
* or interface
* @param typeAdapter This object must implement at least one of the {@link InstanceCreator},
* {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.5
*/
JcloudsGsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?>);
if (typeAdapter instanceof InstanceCreator<?>) {
registerInstanceCreatorForTypeHierarchy(baseType, (InstanceCreator<?>) typeAdapter);
}
if (typeAdapter instanceof JsonSerializer<?>) {
registerSerializerForTypeHierarchy(baseType, (JsonSerializer<?>) typeAdapter);
}
if (typeAdapter instanceof JsonDeserializer<?>) {
registerDeserializerForTypeHierarchy(baseType, (JsonDeserializer<?>) typeAdapter);
}
return this;
}
private <T> JcloudsGsonBuilder registerInstanceCreatorForTypeHierarchy(Class<?> classOfT,
InstanceCreator<? extends T> instanceCreator) {
instanceCreators.registerForTypeHierarchy(classOfT, instanceCreator);
return this;
}
private <T> JcloudsGsonBuilder registerSerializerForTypeHierarchy(Class<?> classOfT,
final JsonSerializer<T> serializer) {
serializers.registerForTypeHierarchy(classOfT, serializer);
return this;
}
private <T> JcloudsGsonBuilder registerDeserializerForTypeHierarchy(Class<?> classOfT,
JsonDeserializer<T> deserializer) {
deserializers.registerForTypeHierarchy(classOfT,
new JsonDeserializerExceptionWrapper<T>(deserializer));
return this;
}
/**
* Section 2.4 of <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON specification</a> disallows
* special double values (NaN, Infinity, -Infinity). However,
* <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf">Javascript
* specification</a> (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript
* values. Moreover, most JavaScript engines will accept these special values in JSON without
* problem. So, at a practical level, it makes sense to accept these values as valid JSON even
* though JSON specification disallows them.
*
* <p>Gson always accepts these special values during deserialization. However, it outputs
* strictly compliant JSON. Hence, if it encounters a float value {@link Float#NaN},
* {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY}, or a double value
* {@link Double#NaN}, {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it
* will throw an {@link IllegalArgumentException}. This method provides a way to override the
* default behavior when you know that the JSON receiver will be able to handle these special
* values.
*
* @return a reference to this {@code JcloudsGsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public JcloudsGsonBuilder serializeSpecialFloatingPointValues() {
this.serializeSpecialFloatingPointValues = true;
return this;
}
/**
* Creates a {@link Gson} instance based on the current configuration. This method is free of
* side-effects to this {@code JcloudsGsonBuilder} instance and hence can be called multiple times.
*
* @return an instance of Gson configured with the options currently set in this builder
*/
public Gson create() {
List<ExclusionStrategy> serializationStrategies =
new LinkedList<ExclusionStrategy>(exclusionStrategies);
List<ExclusionStrategy> deserializationStrategies =
new LinkedList<ExclusionStrategy>(exclusionStrategies);
serializationStrategies.add(modifierBasedExclusionStrategy);
deserializationStrategies.add(modifierBasedExclusionStrategy);
if (!serializeInnerClasses) {
serializationStrategies.add(innerClassExclusionStrategy);
deserializationStrategies.add(innerClassExclusionStrategy);
}
if (ignoreVersionsAfter != VersionConstants.IGNORE_VERSIONS) {
serializationStrategies.add(new VersionExclusionStrategy(ignoreVersionsAfter));
deserializationStrategies.add(new VersionExclusionStrategy(ignoreVersionsAfter));
}
if (excludeFieldsWithoutExposeAnnotation) {
serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy);
deserializationStrategies.add(exposeAnnotationDeserializationExclusionStrategy);
}
ExclusionStrategy serializationExclusionStrategy =
new DisjunctionExclusionStrategy(serializationStrategies);
ExclusionStrategy deserializationExclusionStrategy =
new DisjunctionExclusionStrategy(deserializationStrategies);
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers = deserializers.copyOf();
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
customDeserializers);
customSerializers.registerIfAbsent(JcloudsDefaultTypeAdapters.getDefaultSerializers(
serializeSpecialFloatingPointValues, longSerializationPolicy));
customDeserializers.registerIfAbsent(JcloudsDefaultTypeAdapters.getDefaultDeserializers());
ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators =
instanceCreators.copyOf();
customInstanceCreators.registerIfAbsent(JcloudsDefaultTypeAdapters.getDefaultInstanceCreators());
customSerializers.makeUnmodifiable();
customDeserializers.makeUnmodifiable();
instanceCreators.makeUnmodifiable();
MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators);
JsonFormatter formatter = prettyPrinting ?
new JsonPrintFormatter(escapeHtmlChars) : new JsonCompactFormatter(escapeHtmlChars);
Gson gson = new Gson(serializationExclusionStrategy, deserializationExclusionStrategy,
fieldNamingPolicy, objConstructor, formatter, serializeNulls, customSerializers,
customDeserializers, generateNonExecutableJson);
return gson;
}
private static void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers) {
DefaultDateTypeAdapter dateTypeAdapter = null;
if (datePattern != null && !"".equals(datePattern.trim())) {
dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
}
if (dateTypeAdapter != null) {
if (!serializers.hasSpecificHandlerFor(Date.class)) {
serializers.register(Date.class, dateTypeAdapter);
}
if (!deserializers.hasSpecificHandlerFor(Date.class)) {
deserializers.register(Date.class, dateTypeAdapter);
}
}
}
}

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

@ -19,10 +19,15 @@
package org.jclouds.http;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Nullable;
import org.jclouds.io.Payload;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
/**
* Represents a response produced from {@link HttpCommandExecutorService}
*
@ -34,9 +39,14 @@ public class HttpResponse extends HttpMessage {
private final String message;
public HttpResponse(int statusCode, String message, @Nullable Payload payload) {
this(statusCode, message, payload, ImmutableMultimap.<String, String> of());
}
public HttpResponse(int statusCode, String message, @Nullable Payload payload, Multimap<String, String> headers) {
super(payload);
this.statusCode = statusCode;
this.message = message;
this.headers.putAll(checkNotNull(headers));
}
public int getStatusCode() {
@ -49,8 +59,8 @@ public class HttpResponse extends HttpMessage {
@Override
public String toString() {
return "[message=" + message + ", statusCode=" + statusCode + ", headers=" + headers
+ ", payload=" + payload + "]";
return "[message=" + message + ", statusCode=" + statusCode + ", headers=" + headers + ", payload=" + payload
+ "]";
}
public String getStatusLine() {

View File

@ -19,8 +19,13 @@
package org.jclouds.http;
import java.io.IOException;
import javax.annotation.Nullable;
import org.jclouds.io.payloads.StringPayload;
import org.jclouds.util.Utils;
/**
* Represents an error obtained from an HttpResponse.
*
@ -34,15 +39,14 @@ public class HttpResponseException extends RuntimeException {
protected final HttpResponse response;
private String content;
public HttpResponseException(String message, HttpCommand command,
@Nullable HttpResponse response, Throwable cause) {
public HttpResponseException(String message, HttpCommand command, @Nullable HttpResponse response, Throwable cause) {
super(message, cause);
this.command = command;
this.response = response;
}
public HttpResponseException(String message, HttpCommand command,
@Nullable HttpResponse response, String content, Throwable cause) {
public HttpResponseException(String message, HttpCommand command, @Nullable HttpResponse response, String content,
Throwable cause) {
super(message, cause);
this.command = command;
this.response = response;
@ -50,15 +54,13 @@ public class HttpResponseException extends RuntimeException {
}
public HttpResponseException(HttpCommand command, HttpResponse response, Throwable cause) {
this(String.format("command: %1$s failed with response: %2$s", command.getRequest()
.getRequestLine(), response.getStatusLine()), command, response, cause);
this(String.format("command: %1$s failed with response: %2$s", command.getRequest().getRequestLine(),
response.getStatusLine()), command, response, cause);
}
public HttpResponseException(HttpCommand command, HttpResponse response, String content,
Throwable cause) {
this(String.format("command: %1$s failed with response: %2$s; content: [%3$s]", command
.getRequest().getRequestLine(), response.getStatusLine()), command, response,
content, cause);
public HttpResponseException(HttpCommand command, HttpResponse response, String content, Throwable cause) {
this(String.format("command: %1$s failed with response: %2$s; content: [%3$s]", command.getRequest()
.getRequestLine(), response.getStatusLine()), command, response, content, cause);
}
public HttpResponseException(String message, HttpCommand command, @Nullable HttpResponse response) {
@ -67,8 +69,7 @@ public class HttpResponseException extends RuntimeException {
this.response = response;
}
public HttpResponseException(String message, HttpCommand command,
@Nullable HttpResponse response, String content) {
public HttpResponseException(String message, HttpCommand command, @Nullable HttpResponse response, String content) {
super(message);
this.command = command;
this.response = response;
@ -76,14 +77,29 @@ public class HttpResponseException extends RuntimeException {
}
public HttpResponseException(HttpCommand command, HttpResponse response) {
this(String.format("command: %1$s failed with response: %2$s", command.getRequest()
.getRequestLine(), response.getStatusLine()), command, response);
this(String.format("request: %s %sfailed with response: %s", command.getRequest().getRequestLine(),
requestPayloadIfStringOrFormIfNotReturnEmptyString(command.getRequest()), response.getStatusLine()),
command, response);
}
static String requestPayloadIfStringOrFormIfNotReturnEmptyString(HttpRequest request) {
if (request.getPayload() != null
&& ("application/x-www-form-urlencoded".equals(request.getPayload().getContentMetadata().getContentType()) || request
.getPayload() instanceof StringPayload)
&& request.getPayload().getContentMetadata().getContentLength() != null
&& request.getPayload().getContentMetadata().getContentLength() < 1024) {
try {
return String.format(" [%s] ", request.getPayload() instanceof StringPayload ? request.getPayload()
.getRawContent() : Utils.toStringAndClose(request.getPayload().getInput()));
} catch (IOException e) {
}
}
return "";
}
public HttpResponseException(HttpCommand command, HttpResponse response, String content) {
this(String.format("command: %1$s failed with response: %2$s; content: [%3$s]", command
.getRequest().getRequestLine(), response.getStatusLine(), content), command,
response, content);
this(String.format("command: %s failed with response: %s; content: [%s]", command.getRequest().getRequestLine(),
response.getStatusLine(), content), command, response, content);
}
public HttpCommand getCommand() {

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() {

View File

@ -19,8 +19,8 @@
package org.jclouds.http.handlers;
import static org.jclouds.http.HttpUtils.changePathTo;
import static org.jclouds.http.HttpUtils.changeSchemeHostAndPortTo;
import static java.util.Collections.singletonList;
import static javax.ws.rs.core.HttpHeaders.HOST;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import java.net.URI;
@ -58,8 +58,7 @@ public class RedirectionRetryHandler implements HttpRetryHandler {
protected final Provider<UriBuilder> uriBuilderProvider;
@Inject
protected RedirectionRetryHandler(Provider<UriBuilder> uriBuilderProvider,
BackoffLimitedRetryHandler backoffHandler) {
protected RedirectionRetryHandler(Provider<UriBuilder> uriBuilderProvider, BackoffLimitedRetryHandler backoffHandler) {
this.backoffHandler = backoffHandler;
this.uriBuilderProvider = uriBuilderProvider;
}
@ -67,21 +66,32 @@ public class RedirectionRetryHandler implements HttpRetryHandler {
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
closeClientButKeepContentStream(response);
String hostHeader = response.getFirstHeaderOrNull(HttpHeaders.LOCATION);
if (hostHeader != null && command.incrementRedirectCount() < retryCountLimit) {
URI redirectionUrl = uriBuilderProvider.get().uri(URI.create(hostHeader)).build();
if (redirectionUrl.getScheme().equals(command.getRequest().getEndpoint().getScheme())
&& redirectionUrl.getHost().equals(command.getRequest().getEndpoint().getHost())
&& redirectionUrl.getPort() == command.getRequest().getEndpoint().getPort()) {
if (!redirectionUrl.getPath().equals(command.getRequest().getEndpoint().getPath())) {
changePathTo(command.getRequest(), redirectionUrl.getPath(), uriBuilderProvider
.get());
} else {
if (command.incrementRedirectCount() < retryCountLimit && hostHeader != null) {
URI redirectionUrl = URI.create(hostHeader);
// if you are sent the same uri, assume there's a transient problem and retry.
if (redirectionUrl.equals(command.getRequest().getEndpoint()))
return backoffHandler.shouldRetryRequest(command, response);
UriBuilder builder = uriBuilderProvider.get().uri(command.getRequest().getEndpoint());
assert redirectionUrl.getPath() != null : "no path in redirect header from: " + response;
builder.replacePath(redirectionUrl.getPath());
if (redirectionUrl.getScheme() != null)
builder.scheme(redirectionUrl.getScheme());
if (redirectionUrl.getHost() != null) {
builder.host(redirectionUrl.getHost());
if (command.getRequest().getFirstHeaderOrNull(HOST) != null)
command.getRequest().getHeaders().replaceValues(HOST, singletonList(redirectionUrl.getHost()));
}
} else {
changeSchemeHostAndPortTo(command.getRequest(), redirectionUrl.getScheme(),
redirectionUrl.getHost(), redirectionUrl.getPort(), uriBuilderProvider.get());
}
if (redirectionUrl.getPort() != command.getRequest().getEndpoint().getPort())
builder.port(redirectionUrl.getPort());
if (redirectionUrl.getQuery() != null)
builder.replaceQuery(redirectionUrl.getQuery());
command.getRequest().setEndpoint(builder.build());
return true;
} else {
return false;

View File

@ -227,7 +227,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
connection.setRequestProperty(HttpHeaders.CONTENT_LENGTH, "0");
// for some reason POST/PUT undoes the content length header above.
if (connection.getRequestMethod().equals("POST") || connection.getRequestMethod().equals("PUT"))
connection.setChunkedStreamingMode(0);
connection.setFixedLengthStreamingMode(0);
}
return connection;

View File

@ -38,8 +38,8 @@ import org.jclouds.json.internal.GsonWrapper;
import com.google.common.collect.Maps;
import com.google.common.primitives.Bytes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JcloudsCompactFormatter;
import com.google.gson.JcloudsGsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
@ -64,9 +64,9 @@ public class GsonModule extends AbstractModule {
@Provides
@Singleton
Gson provideGson(JsonBallAdapter jsonObjectAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
ByteArrayAdapter byteArrayAdapter, JsonAdapterBindings bindings) throws SecurityException,
NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
GsonBuilder builder = new GsonBuilder();
ByteArrayAdapter byteArrayAdapter, JsonAdapterBindings bindings) throws ClassNotFoundException, Exception {
JcloudsGsonBuilder builder = new JcloudsGsonBuilder();
builder.registerTypeAdapter(JsonBall.class, jsonObjectAdapter);
builder.registerTypeAdapter(Date.class, adapter);
builder.registerTypeAdapter(new TypeToken<List<Byte>>() {

View File

@ -19,7 +19,6 @@
package org.jclouds.rest;
import org.jclouds.http.HttpRequest;
/**
* Thrown when there is an authorization error.
@ -39,14 +38,6 @@ public class AuthorizationException extends RuntimeException {
super(arg0, arg1);
}
public AuthorizationException(HttpRequest resource, String error) {
super(String.format("%s -> %s", resource.getRequestLine(), error));
}
public AuthorizationException(HttpRequest resource, String error, Throwable arg1) {
super(String.format("%s -> %s", resource.getRequestLine(), error), arg1);
}
public AuthorizationException(Throwable arg0) {
super(arg0);
}

View File

@ -33,7 +33,7 @@ import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.newHashSet;
import static com.google.common.collect.Sets.newTreeSet;
import static java.util.Arrays.asList;
import static javax.ws.rs.core.HttpHeaders.ACCEPT;
import static javax.ws.rs.core.HttpHeaders.*;
import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.HttpHeaders.HOST;
import static org.jclouds.http.HttpUtils.makeQueryLine;
@ -128,6 +128,7 @@ import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.MapMaker;
@ -470,6 +471,9 @@ public class RestAnnotationProcessor<T> {
payload = new MultipartForm(BOUNDARY, parts);
} else if (formParams.size() > 0) {
payload = Payloads.newUrlEncodedFormPayload(formParams, skips);
} else if (headers.containsKey(CONTENT_TYPE)) {
payload = Payloads.newByteArrayPayload(new byte[]{});
payload.getContentMetadata().setContentType(Iterables.get(headers.get(CONTENT_TYPE),0));
}
if (payload != null) {
request.setPayload(payload);

View File

@ -104,7 +104,11 @@ synaptic.contextbuilder=org.jclouds.atmosonline.saas.AtmosStorageContextBuilder
synaptic.endpoint=https://storage.synaptic.att.com
synaptic.apiversion=1.3.0
# TODO peer1 and hostedsolutions use atmos
peer1-storage.contextbuilder=org.jclouds.atmosonline.saas.AtmosStorageContextBuilder
peer1-storage.endpoint=https://storage.synaptic.att.com
peer1-storage.apiversion=1.3.0
# TODO hostedsolutions use atmos
cloudfiles.contextbuilder=org.jclouds.rackspace.cloudfiles.CloudFilesContextBuilder
cloudfiles.propertiesbuilder=org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder
@ -120,4 +124,3 @@ transient.propertiesbuilder=org.jclouds.blobstore.TransientBlobStorePropertiesBu
filesystem.contextbuilder=org.jclouds.filesystem.FilesystemBlobStoreContextBuilder
filesystem.propertiesbuilder=org.jclouds.filesystem.FilesystemBlobStorePropertiesBuilder

View File

@ -0,0 +1,141 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.http.functions;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import org.xml.sax.Locator;
import org.xml.sax.SAXParseException;
public class ParseSaxTest extends BaseHandlerTest {
public static class TestHandler extends ParseSax.HandlerWithResult<String> {
@Override
public String getResult() {
return "";
}
}
ParseSax<String> createParser() {
return factory.create(injector.getInstance(TestHandler.class));
}
@Test
public void testAddDetailsAndPropagateOkWhenRequestWithNoDataAndRuntimeExceptionThrowsOriginalException()
throws ExecutionException, InterruptedException, TimeoutException, IOException {
ParseSax<String> parser = createParser();
Exception input = new RuntimeException("foo");
try {
parser.addDetailsAndPropagate(null, input);
} catch (RuntimeException e) {
assertEquals(e, input);
}
}
@Test
public void testAddDetailsAndPropagateOkWhenRequestWithNoDataAndExceptionPropagates() throws ExecutionException,
InterruptedException, TimeoutException, IOException {
ParseSax<String> parser = createParser();
Exception input = new Exception("foo");
try {
parser.addDetailsAndPropagate(null, input);
} catch (RuntimeException e) {
assertEquals(e.getMessage(), "java.lang.Exception: foo");
assertEquals(e.getCause(), input);
}
}
@Test
public void testAddDetailsAndPropagateOkWhenRequestIsNotNullAndResponseIsNull() throws ExecutionException,
InterruptedException, TimeoutException, IOException {
ParseSax<String> parser = createParser();
HttpRequest request = new HttpRequest("GET", URI.create("http://foohost"));
Exception input = new Exception("foo");
try {
parser.setContext(request);
parser.addDetailsAndPropagate(null, input);
} catch (RuntimeException e) {
assertEquals(e.getMessage(), "request: GET http://foohost HTTP/1.1; cause: java.lang.Exception: foo");
assertEquals(e.getCause(), input);
}
}
@Test
public void testAddDetailsAndPropagateOkWithValidRequestResponse() throws ExecutionException, InterruptedException,
TimeoutException, IOException {
ParseSax<String> parser = createParser();
HttpRequest request = new HttpRequest("GET", URI.create("http://foohost"));
HttpResponse response = new HttpResponse(304, "Not Modified", null);
Exception input = new Exception("foo");
try {
parser.setContext(request);
parser.addDetailsAndPropagate(response, input);
} catch (RuntimeException e) {
assertEquals(e.getMessage(), "request: GET http://foohost HTTP/1.1; response: HTTP/1.1 304 Not Modified; cause: java.lang.Exception: foo");
assertEquals(e.getCause(), input);
}
}
@Test
public void testAddDetailsAndPropagateOkWithValidRequestResponseWithSAXParseException() throws ExecutionException,
InterruptedException, TimeoutException, IOException {
ParseSax<String> parser = createParser();
HttpRequest request = new HttpRequest("GET", URI.create("http://foohost"));
HttpResponse response = new HttpResponse(304, "Not Modified", null);
Locator locator = createMock(Locator.class);
expect(locator.getColumnNumber()).andReturn(1);
expect(locator.getLineNumber()).andReturn(1);
expect(locator.getPublicId()).andReturn("publicId");
expect(locator.getSystemId()).andReturn("systemId");
replay(locator);
Exception input = new SAXParseException("foo", locator);
verify(locator);
try {
parser.setContext(request);
parser.addDetailsAndPropagate(response, input);
} catch (RuntimeException e) {
assertEquals(e.getMessage(),
"request: GET http://foohost HTTP/1.1; response: HTTP/1.1 304 Not Modified; error at 1:1 in document systemId; cause: org.xml.sax.SAXParseException: foo");
assertEquals(e.getCause(), input);
}
}
}

View File

@ -0,0 +1,171 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.http.handlers;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.BaseRestClientTest.MockModule;
import org.jclouds.rest.config.RestModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.inject.Guice;
/**
* Tests behavior of {@code RedirectionRetryHandler}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "http.RedirectionRetryHandlerTest")
public class RedirectionRetryHandlerTest {
@Test
public void test302DoesNotRetry() {
HttpCommand command = createMock(HttpCommand.class);
HttpResponse response = new HttpResponse(302, "HTTP/1.1 302 Found", null);
expect(command.incrementRedirectCount()).andReturn(0);
replay(command);
RedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance(
RedirectionRetryHandler.class);
assert !retry.shouldRetryRequest(command, response);
verify(command);
}
@Test
public void test302DoesNotRetryAfterLimit() {
HttpCommand command = createMock(HttpCommand.class);
HttpResponse response = new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(
HttpHeaders.LOCATION, "/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645"));
expect(command.incrementRedirectCount()).andReturn(5);
replay(command);
RedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance(
RedirectionRetryHandler.class);
assert !retry.shouldRetryRequest(command, response);
verify(command);
}
@Test
public void test302WithPathOnlyHeader() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645")),
new HttpRequest(
"GET",
URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645")));
}
@Test
public void test302ToHttps() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("http://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),//
new HttpRequest("GET", URI
.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")));
}
@Test
public void test302ToDifferentPort() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("http://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"http://services.enterprisecloud.terremark.com:3030/api/v0.8b-ext2.5/org/1906645")),//
new HttpRequest("GET", URI
.create("http://services.enterprisecloud.terremark.com:3030/api/v0.8b-ext2.5/org/1906645")));
}
@Test
public void test302WithHeader() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")), new HttpRequest(
"GET", URI.create("https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")));
}
@Test
public void test302WithHeaderReplacesHostHeader() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645"),
ImmutableMultimap.of(HttpHeaders.HOST, "services.enterprisecloud.terremark.com")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),//
new HttpRequest("GET", URI
.create("https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645"),
ImmutableMultimap.of(HttpHeaders.HOST, "services1.enterprisecloud.terremark.com")));
}
protected void verifyRedirectRoutes(HttpRequest request, HttpResponse response, HttpRequest expected) {
HttpCommand command = createMock(HttpCommand.class);
expect(command.incrementRedirectCount()).andReturn(0);
expect(command.getRequest()).andReturn(request).atLeastOnce();
replay(command);
RedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance(
RedirectionRetryHandler.class);
assert retry.shouldRetryRequest(command, response);
assertEquals(command.getRequest(), expected);
verify(command);
}
}

View File

@ -0,0 +1,78 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.json;
import static org.testng.Assert.assertEquals;
import org.jclouds.json.config.GsonModule;
import org.testng.annotations.Test;
import com.google.gson.JsonParseException;
import com.google.inject.Guice;
@Test
public class JsonTest {
private Json json = Guice.createInjector(new GsonModule()).getInstance(Json.class);
private static class EnumInside {
private static enum Test {
FOO, BAR;
}
private Test enumValue;
}
public void testDeserializeEnum() {
assertEquals(json.fromJson("{enumValue : \"FOO\"}", EnumInside.class).enumValue, EnumInside.Test.FOO);
}
@Test(expectedExceptions = JsonParseException.class)
public void testDeserializeEnumWhenBadValue() {
assertEquals(json.fromJson("{enumValue : \"s\"}", EnumInside.class).enumValue, EnumInside.Test.FOO);
}
private static class EnumInsideWithParser {
private static enum Test {
FOO, BAR, UNRECOGNIZED;
@SuppressWarnings("unused")
public static Test fromValue(String state) {
try {
return valueOf(state);
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
private Test enumValue;
}
public void testDeserializeEnumWithParser() {
assertEquals(json.fromJson("{enumValue : \"FOO\"}", EnumInsideWithParser.class).enumValue,
EnumInsideWithParser.Test.FOO);
}
public void testDeserializeEnumWithParserAndBadValue() {
assertEquals(json.fromJson("{enumValue : \"sd\"}", EnumInsideWithParser.class).enumValue,
EnumInsideWithParser.Test.UNRECOGNIZED);
}
}

View File

@ -29,12 +29,13 @@ import static org.testng.Assert.assertNull;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import javax.annotation.Nullable;
import org.jclouds.Constants;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.http.HttpRequest;
@ -47,6 +48,7 @@ import org.jclouds.rest.internal.RestAnnotationProcessor;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.name.Names;
public abstract class BaseRestClientTest {
@ -69,7 +71,8 @@ public abstract class BaseRestClientTest {
@Override
protected void configure() {
install(new ExecutorServiceModule(MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor()));
bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).toInstance(MoreExecutors.sameThreadExecutor());
bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).toInstance(MoreExecutors.sameThreadExecutor());
bind(TransformingHttpCommandExecutorService.class).toInstance(mock);
}
}

View File

@ -374,9 +374,21 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@Path("")
public void post(HttpRequestOptions options);
@POST
@Path("")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public void post();
}
public void testHttpRequestOptionsPayloadParam() throws SecurityException, NoSuchMethodException, IOException {
Method method = TestPayloadParamVarargs.class.getMethod("post");
HttpRequest request = factory(TestQuery.class).createRequest(method);
assertRequestLineEquals(request, "POST http://localhost:9999?x-ms-version=2009-07-17 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, "", "application/octet-stream", false);
}
public void testHttpRequestWithOnlyContentType() throws SecurityException, NoSuchMethodException, IOException {
Method method = TestPayloadParamVarargs.class.getMethod("post", HttpRequestOptions.class);
verifyTestPostOptions(method);
}

View File

@ -255,44 +255,44 @@
<configuration>
<systemProperties>
<property>
<name>twitter.identity</name>
<value>${jclouds.twitter.user}</value>
<name>test.twitter.identity</name>
<value>${test.twitter.identity}</value>
</property>
<property>
<name>twitter.credential</name>
<value>${jclouds.twitter.password}</value>
<name>test.twitter.credential</name>
<value>${test.twitter.credential}</value>
</property>
<property>
<name>azureblob.identity</name>
<value>${jclouds.azure.storage.account}</value>
<name>test.azureblob.identity</name>
<value>${test.azureblob.identity}</value>
</property>
<property>
<name>azureblob.credential</name>
<value>${jclouds.azure.storage.key}</value>
<name>test.azureblob.credential</name>
<value>${test.azureblob.credential}</value>
</property>
<property>
<name>cloudfiles.identity</name>
<value>${jclouds.rackspace.user}</value>
<name>test.cloudfiles.identity</name>
<value>${test.cloudfiles.identity}</value>
</property>
<property>
<name>cloudfiles.credential</name>
<value>${jclouds.rackspace.key}</value>
<name>test.cloudfiles.credential</name>
<value>${test.cloudfiles.credential}</value>
</property>
<property>
<name>googlestorage.identity</name>
<value>${jclouds.googlestorage.accesskeyid}</value>
<name>test.googlestorage.identity</name>
<value>${test.googlestorage.identity}</value>
</property>
<property>
<name>googlestorage.credential</name>
<value>${jclouds.googlestorage.secretaccesskey}</value>
<name>test.googlestorage.credential</name>
<value>${test.googlestorage.credential}</value>
</property>
<property>
<name>s3.identity</name>
<value>${jclouds.aws.accesskeyid}</value>
<name>test.s3.identity</name>
<value>${test.s3.identity}</value>
</property>
<property>
<name>s3.credential</name>
<value>${jclouds.aws.secretaccesskey}</value>
<name>test.s3.credential</name>
<value>${test.s3.credential}</value>
</property>
<property>
<name>appengine.home</name>

View File

@ -89,8 +89,8 @@ public class SpringServletConfig extends LoggingConfig implements ServletConfigA
Set<Module> modules = ImmutableSet.<Module> of(googleModule);
// shared across all blobstores and used to retrieve tweets
try {
twitterClient = new TwitterFactory().getInstance(props.getProperty("twitter.identity"), props
.getProperty("credential"));
twitterClient = new TwitterFactory().getInstance(props.getProperty("twitter.identity"),
props.getProperty("twitter.credential"));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("properties for twitter not configured properly in " + props.toString(), e);
}

View File

@ -27,9 +27,9 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
@ -75,11 +75,12 @@ public class TweetStoreLiveTest {
private static final Properties props = new Properties();
@BeforeTest
void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException, TwitterException {
void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException,
TwitterException {
container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER),
PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(PROPERTY_TWEETSTORE_CONTAINER,
checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(SpringServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores));
@ -98,8 +99,8 @@ public class TweetStoreLiveTest {
contexts.put(provider, factory.createContext(provider, wiring, props));
}
Twitter client = new TwitterFactory().getInstance(props.getProperty("twitter.identity"), props
.getProperty("twitter.credential"));
Twitter client = new TwitterFactory().getInstance(props.getProperty("twitter.identity"),
props.getProperty("twitter.credential"));
StoreTweetsController controller = new StoreTweetsController(contexts, container, client);
ResponseList<Status> statuses = client.getMentions();
@ -134,17 +135,18 @@ public class TweetStoreLiveTest {
}
private void addConfigurationForTwitter(Properties props) {
props.setProperty("twitter.identity", checkNotNull(System.getProperty("twitter.identity"), "twitter.identity"));
props.setProperty("twitter.credential", checkNotNull(System.getProperty("twitter.credential"),
"twitter.credential"));
props.setProperty("twitter.identity",
checkNotNull(System.getProperty("test.twitter.identity"), "test.twitter.identity"));
props.setProperty("twitter.credential",
checkNotNull(System.getProperty("test.twitter.credential"), "test.twitter.credential"));
}
private void addCredentialsForBlobStores(Properties props) {
for (String provider : blobstores) {
props.setProperty(provider + ".identity", checkNotNull(System.getProperty(provider + ".identity"), provider
+ ".identity"));
props.setProperty(provider + ".credential", checkNotNull(System.getProperty(provider + ".credential"),
provider + ".credential"));
props.setProperty(provider + ".identity",
checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"));
props.setProperty(provider + ".credential",
checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider + ".credential"));
}
}

View File

@ -79,7 +79,7 @@ public class GuiceServletConfig extends GuiceServletContextListener {
// shared across all blobstores and used to retrieve tweets
try {
twitterClient = new TwitterFactory().getInstance(props.getProperty("twitter.identity"), props
.getProperty("credential"));
.getProperty("twitter.credential"));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("properties for twitter not configured properly in " + props.toString(), e);
}

View File

@ -27,9 +27,9 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
@ -57,8 +57,8 @@ import com.google.common.collect.Maps;
import com.google.inject.Module;
/**
* Starts up the Google App Engine for Java Development environment and deploys
* an application which tests accesses twitter and blobstores.
* Starts up the Google App Engine for Java Development environment and deploys an application which
* tests accesses twitter and blobstores.
*
* @author Adrian Cole
*/
@ -75,11 +75,12 @@ public class TweetStoreLiveTest {
private static final Properties props = new Properties();
@BeforeTest
void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException, TwitterException {
void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException,
TwitterException {
container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER),
PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(PROPERTY_TWEETSTORE_CONTAINER,
checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(GuiceServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores));
@ -98,8 +99,8 @@ public class TweetStoreLiveTest {
contexts.put(provider, factory.createContext(provider, wiring, props));
}
Twitter client = new TwitterFactory().getInstance(props.getProperty("twitter.identity"), props
.getProperty("twitter.credential"));
Twitter client = new TwitterFactory().getInstance(props.getProperty("twitter.identity"),
props.getProperty("twitter.credential"));
StoreTweetsController controller = new StoreTweetsController(contexts, container, client);
ResponseList<Status> statuses = client.getMentions();
@ -148,17 +149,17 @@ public class TweetStoreLiveTest {
}
private void addConfigurationForTwitter(Properties props) {
props.setProperty("twitter.identity", checkNotNull(System.getProperty("twitter.identity"), "twitter.identity"));
props.setProperty("twitter.credential", checkNotNull(System.getProperty("twitter.credential"),
"twitter.credential"));
props.setProperty("twitter.identity", checkNotNull(System.getProperty("test.twitter.identity"), "test.twitter.identity"));
props.setProperty("twitter.credential",
checkNotNull(System.getProperty("test.twitter.credential"), "test.twitter.credential"));
}
private void addCredentialsForBlobStores(Properties props) {
for (String provider : blobstores) {
props.setProperty(provider + ".identity", checkNotNull(System.getProperty(provider + ".identity"), provider
+ ".identity"));
props.setProperty(provider + ".credential", checkNotNull(System.getProperty(provider + ".credential"),
provider + ".credential"));
props.setProperty(provider + ".identity",
checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"));
props.setProperty(provider + ".credential",
checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider + ".credential"));
}
}

View File

@ -27,6 +27,6 @@ package org.jclouds.filesystem.reference;
public class FilesystemConstants {
/** Specify the base directory where provider starts its file operations - must exists */
public static final String PROPERTY_BASEDIR = "FileSystemAsyncBlobStore-basedir";
public static final String PROPERTY_BASEDIR = "jclouds.filesystem.basedir";
}

View File

@ -335,12 +335,12 @@ public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy
* @return the resulting string
*/
protected String buildPathStartingFromBaseDir(String...pathTokens) {
String normalizedToken = removeFileSeparatorFromBorders(normalize(baseDirectory));
String normalizedToken = removeFileSeparatorFromBorders(normalize(baseDirectory), true);
StringBuilder completePath = new StringBuilder(normalizedToken);
if(pathTokens!=null && pathTokens.length>0) {
for(int i=0; i<pathTokens.length; i++) {
if(pathTokens[i]!=null) {
normalizedToken = removeFileSeparatorFromBorders(normalize(pathTokens[i]));
normalizedToken = removeFileSeparatorFromBorders(normalize(pathTokens[i]), false);
completePath.append(File.separator).append(normalizedToken);
}
}
@ -367,16 +367,19 @@ public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy
* Remove leading and trailing {@link File.separator} character from the
* string.
* @param pathToBeCleaned
* @param remove only trailing separator char from path
* @return
*/
private String removeFileSeparatorFromBorders(String pathToBeCleaned) {
private String removeFileSeparatorFromBorders(String pathToBeCleaned, boolean onlyTrailing) {
if (null == pathToBeCleaned || pathToBeCleaned.equals("")) return pathToBeCleaned;
int beginIndex = 0;
int endIndex = pathToBeCleaned.length();
//search for separator chars
if (!onlyTrailing) {
if (pathToBeCleaned.substring(0, 1).equals(File.separator)) beginIndex = 1;
}
if (pathToBeCleaned.substring(pathToBeCleaned.length() - 1).equals(File.separator)) endIndex--;
return pathToBeCleaned.substring(beginIndex, endIndex);

View File

@ -185,16 +185,8 @@ public class FilesystemAsyncBlobStoreTest {
/**
* Test of list method, of class FilesystemAsyncBlobStore.
*/
public void testList_NoOptionSingleContainer() throws IOException {
// Testing list for a not existing container
try {
blobStore.list(CONTAINER_NAME);
fail("Found a not existing container");
} catch(ContainerNotFoundException e) {
}
public void testList_NoOptionSingleContainer()
throws IOException {
blobStore.createContainerInLocation(null, CONTAINER_NAME);
// Testing list for an empty container
checkForContainerContent(CONTAINER_NAME, null);
@ -268,6 +260,29 @@ public class FilesystemAsyncBlobStoreTest {
}
public void testList_Subdirectory()
throws IOException {
blobStore.createContainerInLocation(null, CONTAINER_NAME);
// Testing list for an empty container
checkForContainerContent(CONTAINER_NAME, null);
//creates blobs in first container
Set<String> blobsExpected = TestUtils.createBlobsInContainer(
CONTAINER_NAME,
new String[] {
"bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg",
"4rrr.jpg",
"rrr" + File.separator + "sss" + File.separator + "788.jpg",
"rrr" + File.separator + "wert.kpg" }
);
//remove not expected values
blobsExpected.remove("bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg");
blobsExpected.remove("4rrr.jpg");
checkForContainerContent(CONTAINER_NAME, "rrr", blobsExpected);
}
/**
* TODO
* Should throws an exception?
@ -809,12 +824,17 @@ public class FilesystemAsyncBlobStoreTest {
* @param expectedBlobKeys
*/
private void checkForContainerContent(final String containerName, Set<String> expectedBlobKeys) {
checkForContainerContent(containerName, null, expectedBlobKeys);
}
private void checkForContainerContent(final String containerName, String inDirectory, Set<String> expectedBlobKeys) {
ListContainerOptions options = ListContainerOptions.Builder.recursive();
if (null != inDirectory && !"".equals(inDirectory)) options.inDirectory(inDirectory);
PageSet<? extends StorageMetadata> blobsRetrieved = blobStore.list(containerName, options);
//nothing expected
if (null == expectedBlobKeys) {
if (null == expectedBlobKeys || 0 == expectedBlobKeys.size()) {
assertTrue(blobsRetrieved.isEmpty(), "Wrong blob number retrieved in the containter [" + containerName + "]");
return;
}

View File

@ -417,6 +417,38 @@ public class FilesystemStorageStrategyImplTest {
}
public void testGetFileForBlobKey_AbsolutePath()
throws IOException {
String absoluteBasePath = (new File(getAbsoluteDirectory(), "basedir")).getAbsolutePath() + FS;
String absoluteContainerPath = absoluteBasePath + CONTAINER_NAME + FS;
//create storageStrategy with an absolute path
FilesystemStorageStrategy storageStrategyAbsolute = new FilesystemStorageStrategyImpl(
new Blob.Factory() {
@Override
public Blob create(MutableBlobMetadata metadata) {
return new BlobImpl(metadata != null ? metadata : new MutableBlobMetadataImpl());
}
},
absoluteBasePath,
new FilesystemContainerNameValidatorImpl(),
new FilesystemBlobKeyValidatorImpl());
TestUtils.cleanDirectoryContent(absoluteContainerPath);
String blobKey;
File fileForPayload;
blobKey = TestUtils.createRandomBlobKey("getFileForBlobKey-", ".img");
fileForPayload = storageStrategyAbsolute.getFileForBlobKey(CONTAINER_NAME, blobKey);
assertNotNull(fileForPayload, "Result File object is null");
assertEquals(fileForPayload.getAbsolutePath(), absoluteContainerPath + blobKey, "Wrong file path");
blobKey = TestUtils.createRandomBlobKey("asd" + FS + "vmad" + FS + "andsnf" + FS + "getFileForBlobKey-", ".img");
fileForPayload = storageStrategyAbsolute.getFileForBlobKey(CONTAINER_NAME, blobKey);
assertEquals(fileForPayload.getAbsolutePath(), absoluteContainerPath + blobKey, "Wrong file path");
}
public void testBlobExists() throws IOException {
String[] sourceBlobKeys = new String[]{
TestUtils.createRandomBlobKey("blobExists-", ".jpg"),
@ -530,5 +562,16 @@ public class FilesystemStorageStrategyImplTest {
//---------------------------------------------------------- Private methods
/**
* Calculates an absolute directory path that depends on operative system
* @return
*/
private String getAbsoluteDirectory() throws IOException {
File tempFile = File.createTempFile("prefix", "suffix");
String tempAbsolutePath = tempFile.getParent();
return tempAbsolutePath;
}
}

View File

@ -40,7 +40,7 @@
</scm>
<properties>
<!-- when instances are hung, open a ticket and add here -->
<jclouds.compute.blacklist.nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist.nodes>
<jclouds.compute.blacklist-nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist-nodes>
<test.gogrid.endpoint>https://api.gogrid.com/api</test.gogrid.endpoint>
<test.gogrid.apiversion>1.5</test.gogrid.apiversion>
<test.gogrid.identity>FIXME</test.gogrid.identity>
@ -119,8 +119,8 @@
<value>${test.gogrid.credential}</value>
</property>
<property>
<name>jclouds.compute.blacklist.nodes</name>
<value>${jclouds.compute.blacklist.nodes}</value>
<name>jclouds.compute.blacklist-nodes</name>
<value>${jclouds.compute.blacklist-nodes}</value>
</property>
</systemProperties>
</configuration>

View File

@ -19,6 +19,7 @@
package org.jclouds.gogrid.compute.suppliers;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -34,6 +35,7 @@ import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.gogrid.GoGridClient;
import org.jclouds.gogrid.domain.ServerImage;
import org.jclouds.logging.Logger;
@ -56,9 +58,12 @@ public class GoGridImageSupplier implements Supplier<Set<? extends Image>> {
private final GoGridClient sync;
private final PopulateDefaultLoginCredentialsForImageStrategy authenticator;
private final Map<OsFamily, Map<String, String>> osVersionMap;
@Inject
GoGridImageSupplier(final GoGridClient sync, PopulateDefaultLoginCredentialsForImageStrategy authenticator) {
GoGridImageSupplier(GoGridClient sync, PopulateDefaultLoginCredentialsForImageStrategy authenticator,
Map<OsFamily, Map<String, String>> osVersionMap) {
this.osVersionMap = osVersionMap;
this.sync = sync;
this.authenticator = authenticator;
}
@ -85,10 +90,13 @@ public class GoGridImageSupplier implements Supplier<Set<? extends Image>> {
OsFamily osFamily = null;
String osName = from.getOs().getName();
String osArch = from.getArchitecture().getDescription();
String osVersion = parseVersion(osName);
String osVersion = null;
String osDescription = from.getOs().getDescription();
boolean is64Bit = (from.getOs().getName().indexOf("64") != -1 || from.getDescription().indexOf("64") != -1);
if (osName.startsWith("Windows")) {
osFamily = OsFamily.WINDOWS;
} else {
Matcher matcher = GOGRID_OS_PATTERN.matcher(from.getName());
if (matcher.find()) {
try {
@ -97,17 +105,13 @@ public class GoGridImageSupplier implements Supplier<Set<? extends Image>> {
logger.debug("<< didn't match os(%s)", from.getName());
}
}
// TODO determine DC images are in
OperatingSystem os = new OperatingSystem(osFamily, osName, osVersion, osArch, osDescription, is64Bit);
return os;
}
static String parseVersion(String name) {
Matcher matcher = GOGRID_VERSION_PATTERN.matcher(name);
Matcher matcher = GOGRID_VERSION_PATTERN.matcher(osName);
if (matcher.find()) {
return matcher.group(1);
osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(1), osVersionMap);
}
return null;
// TODO determine DC images are in
return new OperatingSystem(osFamily, osName, osVersion, osArch, osDescription, is64Bit);
}
}

View File

@ -53,23 +53,17 @@ public class GoGridErrorHandler implements HttpErrorHandler {
try {
Exception exception = new HttpResponseException(command, response);
Set<ErrorResponse> errors = parseErrorsFromContentOrNull(response);
if (errors != null)
exception = new GoGridResponseException(command, response, errors);
switch (response.getStatusCode()) {
case 400:
if (Iterables.get(errors, 0).getMessage()
.indexOf("No object found") != -1) {
exception = new ResourceNotFoundException(Iterables.get(errors,
0).getMessage(), exception);
if (Iterables.get(errors, 0).getMessage().indexOf("No object found") != -1) {
exception = new ResourceNotFoundException(Iterables.get(errors, 0).getMessage(), exception);
break;
}
case 403:
exception = new AuthorizationException(command.getRequest(),
errors != null ? errors.toString() : response.getStatusLine());
exception = new AuthorizationException(exception.getMessage(), exception);
break;
default:
exception = errors != null ? new GoGridResponseException(command,
response, errors) : new HttpResponseException(command,
response);
}
command.setException(exception);
} finally {

View File

@ -0,0 +1,72 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.gogrid.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "gogrid.GoGridTemplateBuilderLiveTest")
public class GoGridTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public GoGridTemplateBuilderLiveTest() {
provider = "gogrid";
}
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return new Predicate<OsFamilyVersion64Bit>() {
@Override
public boolean apply(OsFamilyVersion64Bit input) {
return ((input.family == OsFamily.RHEL && !input.version.equals("5.4")) || //
(input.family == OsFamily.CENTOS && input.version.matches("5.[54]")) || //
(input.family == OsFamily.CENTOS && input.is64Bit && input.version.equals("5.4")) || //
(input.family == OsFamily.UBUNTU) || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008 SP2") || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008 R2"))));
}
};
}
@Test
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "5.3");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.CENTOS);
assertEquals(getCores(defaultTemplate.getHardware()), 0.5d);
}
}

View File

@ -521,6 +521,10 @@ pageTracker._trackPageview();
<artifactId>maven-install-plugin</artifactId>
<version>2.3</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.1</version>
</plugin>
</plugins>
</pluginManagement>
</build>

View File

@ -38,7 +38,7 @@
<test.rackspace.credential>FIXME</test.rackspace.credential>
<test.initializer>org.jclouds.rackspace.cloudfiles.blobstore.integration.CloudFilesTestInitializer</test.initializer>
<!-- when instances are hung, open a ticket and add here -->
<jclouds.compute.blacklist.nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist.nodes>
<jclouds.compute.blacklist-nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist-nodes>
<test.cloudfiles.endpoint>${test.rackspace.endpoint}</test.cloudfiles.endpoint>
<test.cloudfiles.apiversion>${test.rackspace.apiversion}</test.cloudfiles.apiversion>
<test.cloudfiles.identity>${test.rackspace.identity}</test.cloudfiles.identity>
@ -151,8 +151,8 @@
<value>${test.cloudservers.credential}</value>
</property>
<property>
<name>jclouds.compute.blacklist.nodes</name>
<value>${jclouds.compute.blacklist.nodes}</value>
<name>jclouds.compute.blacklist-nodes</name>
<value>${jclouds.compute.blacklist-nodes}</value>
</property>
<property>
<name>test.initializer</name>

View File

@ -57,7 +57,7 @@ public class ParseCloudFilesErrorFromHttpResponse implements HttpErrorHandler {
exception = content != null ? new HttpResponseException(command, response, content) : exception;
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(command.getRequest(), content, exception);
exception = new AuthorizationException(exception.getMessage(), exception);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {

View File

@ -19,14 +19,9 @@
package org.jclouds.rackspace.cloudservers.compute.config;
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.BaseComputeService;
import com.google.inject.Injector;
/**
* Configures the {@link CloudServersComputeServiceContext}; requires {@link BaseComputeService}
* bound.
@ -43,8 +38,4 @@ public class CloudServersComputeServiceContextModule extends BaseComputeServiceC
super.configure();
}
@Override
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
return template.osFamily(UBUNTU).imageNameMatches(".*10\\.?04.*");
}
}

View File

@ -19,16 +19,19 @@
package org.jclouds.rackspace.cloudservers.compute.functions;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
@ -40,12 +43,21 @@ import com.google.common.base.Function;
@Singleton
public class CloudServersImageToOperatingSystem implements
Function<org.jclouds.rackspace.cloudservers.domain.Image, OperatingSystem> {
public static final Pattern RACKSPACE_PATTERN = Pattern.compile("(([^ ]*) ([0-9.]+) ?.*)");
public static final Pattern DEFAULT_PATTERN = Pattern.compile("(([^ ]*) ([0-9.]+) ?.*)");
// Windows Server 2008 R2 x64
public static final Pattern WINDOWS_PATTERN = Pattern.compile("Windows (.*) (x[86][64])");
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Map<OsFamily, Map<String, String>> osVersionMap;
@Inject
public CloudServersImageToOperatingSystem(Map<OsFamily, Map<String, String>> osVersionMap) {
this.osVersionMap = osVersionMap;
}
public OperatingSystem apply(final org.jclouds.rackspace.cloudservers.domain.Image from) {
OsFamily osFamily = null;
String osName = null;
@ -53,21 +65,28 @@ public class CloudServersImageToOperatingSystem implements
String osVersion = null;
String osDescription = from.getName();
boolean is64Bit = true;
Matcher matcher = RACKSPACE_PATTERN.matcher(from.getName());
if (from.getName().indexOf("Red Hat EL") != -1) {
osFamily = OsFamily.RHEL;
} else if (from.getName().indexOf("Oracle EL") != -1) {
osFamily = OsFamily.OEL;
} else if (from.getName().indexOf("Windows") != -1) {
osFamily = OsFamily.WINDOWS;
Matcher matcher = WINDOWS_PATTERN.matcher(from.getName());
if (matcher.find()) {
osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(1), osVersionMap);
is64Bit = matcher.group(2).equals("x64");
}
} else {
Matcher matcher = DEFAULT_PATTERN.matcher(from.getName());
if (matcher.find()) {
try {
osFamily = OsFamily.fromValue(matcher.group(2).toLowerCase());
} catch (IllegalArgumentException e) {
logger.debug("<< didn't match os(%s)", matcher.group(2));
}
osVersion = matcher.group(3);
}
OperatingSystem os = new OperatingSystem(osFamily, osName, osVersion, osArch, osDescription, is64Bit);
return os;
osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(3), osVersionMap);
}
}
return new OperatingSystem(osFamily, osName, osVersion, osArch, osDescription, is64Bit);
}
}

View File

@ -52,9 +52,10 @@ public class ParseCloudServersErrorFromHttpResponse implements HttpErrorHandler
Exception exception = new HttpResponseException(command, response);
try {
String content = parseErrorFromContentOrNull(command, response);
exception = content != null ? new HttpResponseException(command, response, content) : exception;
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(command.getRequest(), content);
exception = new AuthorizationException(exception.getMessage(), exception);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {

View File

@ -52,7 +52,7 @@ public class CloudServersComputeServiceLiveTest extends BaseComputeServiceLiveTe
public void testTemplateBuilder() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "9.10");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), "DFW1");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
@ -82,4 +82,21 @@ public class CloudServersComputeServiceLiveTest extends BaseComputeServiceLiveTe
super.testSuspendResume();
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
@Override
public void testGetNodesWithDetails() throws Exception {
super.testGetNodesWithDetails();
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
@Override
public void testListNodes() throws Exception {
super.testListNodes();
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
@Override
public void testDestroyNodes() {
super.testDestroyNodes();
}
}

View File

@ -0,0 +1,57 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.rackspace.cloudservers.compute;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.OsFamily;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "cloudservers.CloudServersTemplateBuilderLiveTest")
public class CloudServersTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public CloudServersTemplateBuilderLiveTest() {
provider = "cloudservers";
}
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return new Predicate<OsFamilyVersion64Bit>() {
@Override
public boolean apply(OsFamilyVersion64Bit input) {
return (input.family != OsFamily.WINDOWS && !input.is64Bit) || //
input.family == OsFamily.RHEL || //
(input.family == OsFamily.UBUNTU && input.version.equals("11.04")) || //
(input.family == OsFamily.CENTOS && input.version.matches("5.[23]")) || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008")) || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008 R2") && !input.is64Bit);
}
};
}
}

View File

@ -23,14 +23,20 @@ import static org.testng.Assert.assertEquals;
import java.net.UnknownHostException;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystemBuilder;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule;
import org.jclouds.rackspace.cloudservers.functions.ParseImageFromJsonResponseTest;
import org.testng.annotations.Test;
import com.google.inject.Guice;
/**
* @author Adrian Cole
*/
@ -52,7 +58,9 @@ public class CloudServersImageToImageTest {
public static Image convertImage() {
org.jclouds.rackspace.cloudservers.domain.Image image = ParseImageFromJsonResponseTest.parseImage();
CloudServersImageToImage parser = new CloudServersImageToImage(new CloudServersImageToOperatingSystem());
CloudServersImageToImage parser = new CloudServersImageToImage(new CloudServersImageToOperatingSystem(new BaseComputeServiceContextModule() {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(new GsonModule())
.getInstance(Json.class))));
return parser.apply(image);
}

View File

@ -40,8 +40,8 @@
</scm>
<properties>
<!-- when instances are hung, open a ticket and add here -->
<jclouds.compute.blacklist.nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist.nodes>
<test.rimuhosting.endpoint>https://rimuhosting.com/r</test.rimuhosting.endpoint>
<jclouds.compute.blacklist-nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist-nodes>
<test.rimuhosting.endpoint>https://api.rimuhosting.com/r</test.rimuhosting.endpoint>
<test.rimuhosting.apiversion>1.0</test.rimuhosting.apiversion>
<test.rimuhosting.identity>FIXME</test.rimuhosting.identity>
</properties>
@ -114,8 +114,8 @@
<value>${test.rimuhosting.identity}</value>
</property>
<property>
<name>jclouds.compute.blacklist.nodes</name>
<value>${jclouds.compute.blacklist.nodes}</value>
<name>jclouds.compute.blacklist-nodes</name>
<value>${jclouds.compute.blacklist-nodes}</value>
</property>
</systemProperties>
</configuration>

View File

@ -39,6 +39,7 @@ import org.jclouds.rest.annotations.MatrixParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rimuhosting.miro.binder.CreateServerOptions;
import org.jclouds.rimuhosting.miro.binder.RimuHostingRebootJsonBinder;
import org.jclouds.rimuhosting.miro.domain.Image;
@ -66,6 +67,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* @see <a href="http://apidocs.rimuhosting.com" />
*/
@RequestFilters(RimuHostingAuthentication.class)
@VirtualHost
public interface RimuHostingAsyncClient {
/**
@ -74,7 +76,6 @@ public interface RimuHostingAsyncClient {
@GET
@Path("/distributions")
@ResponseParser(ParseImagesFromJsonResponse.class)
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ParseRimuHostingException.class)
ListenableFuture<Set<Image>> getImageList();
@ -86,7 +87,6 @@ public interface RimuHostingAsyncClient {
@Path("/orders")
@ResponseParser(ParseServersFromJsonResponse.class)
@MatrixParams(keys = "include_inactive", values = "N")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ParseRimuHostingException.class)
ListenableFuture<Set<Server>> getServerList();

View File

@ -37,7 +37,7 @@ public class RimuHostingPropertiesBuilder extends PropertiesBuilder {
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_API_VERSION, "TODO");
properties.setProperty(PROPERTY_ENDPOINT, "https://rimuhosting.com/r");
properties.setProperty(PROPERTY_ENDPOINT, "https://api.rimuhosting.com/r");
properties.setProperty(PROPERTY_RIMUHOSTING_DEFAULT_DC, "DCDALLAS");
return properties;
}

View File

@ -19,9 +19,6 @@
package org.jclouds.rimuhosting.miro.compute.config;
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.TemplateBuilder;
@ -45,7 +42,7 @@ public class RimuHostingComputeServiceContextModule extends BaseComputeServiceCo
@Override
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
return template.hardwareId("MIRO1B").osFamily(UBUNTU).os64Bit(false).osVersionMatches("9.10");
return super.provideTemplate(injector, template).hardwareId("MIRO4B");
}
}

View File

@ -64,8 +64,8 @@ public class ParseRimuHostingException implements Function<Exception, Object> {
RimuHostingResponse firstResponse = Iterables.get(responseMap.values(), 0);
String errorClass = firstResponse.getErrorInfo().getErrorClass();
if (errorClass.equals("PermissionException"))
throw new AuthorizationException(responseException.getCommand().getRequest(),
firstResponse.getErrorInfo().getErrorMessage());
throw new AuthorizationException(
firstResponse.getErrorInfo().getErrorMessage(), responseException);
throw new RuntimeException(firstResponse.getErrorInfo().getErrorMessage(), e);
}
}

View File

@ -51,13 +51,13 @@ public class RimuHostingAsyncClientTest extends RestClientTest<RimuHostingAsyncC
Method method = RimuHostingAsyncClient.class.getMethod("createServer", String.class, String.class, String.class,
CreateServerOptions[].class);
GeneratedHttpRequest<RimuHostingAsyncClient> httpRequest = processor.createRequest(method, "test.ivan.api.com",
"lenny", "MIRO1B");
"lenny", "MIRO4B");
assertRequestLineEquals(httpRequest, "POST https://rimuhosting.com/r/orders/new-vps HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertRequestLineEquals(httpRequest, "POST https://api.rimuhosting.com/r/orders/new-vps HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nHost: api.rimuhosting.com\n");
assertPayloadEquals(
httpRequest,
"{\"request\":{\"instantiation_options\":{\"distro\":\"lenny\",\"domain_name\":\"test.ivan.api.com\"},\"pricing_plan_code\":\"MIRO1B\",\"meta_data\":[]}}",
"{\"request\":{\"instantiation_options\":{\"distro\":\"lenny\",\"domain_name\":\"test.ivan.api.com\"},\"pricing_plan_code\":\"MIRO4B\",\"meta_data\":[]}}",
"application/json", false);
assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);

View File

@ -115,7 +115,7 @@ public class RimuHostingClientLiveTest {
@Test
public void testLifeCycle() {
// Get the first image, we dont really care what it is in this test.
NewServerResponse serverResponse = connection.createServer("test.ivan.api.com", "lenny", "MIRO1B");
NewServerResponse serverResponse = connection.createServer("test.ivan.api.com", "lenny", "MIRO4B");
Server server = serverResponse.getServer();
// Now we have the server, lets restart it
assertNotNull(server.getId());

View File

@ -48,10 +48,10 @@ public class RimuHostingComputeServiceLiveTest extends BaseComputeServiceLiveTes
public void testTemplateBuilder() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), false);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "9.10");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), "DCDALLAS");
assertEquals(defaultTemplate.getHardware().getProviderId(), "MIRO1B");
assertEquals(defaultTemplate.getHardware().getProviderId(), "MIRO4B");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}

View File

@ -0,0 +1,53 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.rimuhosting.miro.compute;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.OsFamily;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "rimuhosting.RimuHostingTemplateBuilderLiveTest")
public class RimuHostingTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public RimuHostingTemplateBuilderLiveTest() {
provider = "rimuhosting";
}
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return new Predicate<OsFamilyVersion64Bit>() {
@Override
public boolean apply(OsFamilyVersion64Bit input) {
return input.family != OsFamily.UBUNTU || //
Float.parseFloat(input.version) > 10.04 || //
(!(input.is64Bit) && Float.parseFloat(input.version) < 8.10);
}
};
}
}

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2010 Cloud Conscious, LLC <info@cloudconscious.com>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.html
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.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-elastichosts</artifactId>
<name>jclouds ElasticHosts core</name>
<description>jclouds components to access ElasticHosts</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/elastichosts</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/elastichosts</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/elastichosts</url>
</scm>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
<repository>
<id>jclouds-googlecode-deploy</id>
<url>http://jclouds.googlecode.com/svn/repo</url>
</repository>
<repository>
<id>jclouds-rimu-snapshots-nexus</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<!-- when instances are hung, open a ticket and add here -->
<jclouds.compute.blacklist-nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist-nodes>
<test.elastichosts.endpoint>https://api.cloudsigma.com</test.elastichosts.endpoint>
<test.elastichosts.apiversion>1.0</test.elastichosts.apiversion>
<test.elastichosts.identity>FIXME</test.elastichosts.identity>
<test.elastichosts.credential>FIXME</test.elastichosts.credential>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>test.elastichosts.endpoint</name>
<value>${test.elastichosts.endpoint}</value>
</property>
<property>
<name>test.elastichosts.apiversion</name>
<value>${test.elastichosts.apiversion}</value>
</property>
<property>
<name>test.elastichosts.identity</name>
<value>${test.elastichosts.identity}</value>
</property>
<property>
<name>test.elastichosts.credential</name>
<value>${test.elastichosts.credential}</value>
</property>
<property>
<name>jclouds.compute.blacklist-nodes</name>
<value>${jclouds.compute.blacklist-nodes}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,199 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.elastichosts;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.elastichosts.binders.BindCreateDriveRequestToPlainTextString;
import org.jclouds.elastichosts.binders.BindDriveDataToPlainTextString;
import org.jclouds.elastichosts.binders.BindReadDriveOptionsToPath;
import org.jclouds.elastichosts.domain.CreateDriveRequest;
import org.jclouds.elastichosts.domain.DriveData;
import org.jclouds.elastichosts.domain.DriveInfo;
import org.jclouds.elastichosts.domain.ImageConversionType;
import org.jclouds.elastichosts.functions.KeyValuesDelimitedByBlankLinesToDriveInfo;
import org.jclouds.elastichosts.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet;
import org.jclouds.elastichosts.functions.ReturnPayload;
import org.jclouds.elastichosts.functions.SplitNewlines;
import org.jclouds.elastichosts.options.ReadDriveOptions;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.io.Payload;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to ElasticHosts via their REST API.
* <p/>
*
* @see ElasticHostsClient
* @see <a href="TODO: insert URL of provider documentation" />
* @author Adrian Cole
*/
@RequestFilters(BasicAuthentication.class)
@Consumes(MediaType.TEXT_PLAIN)
public interface ElasticHostsAsyncClient {
/**
* @see ElasticHostsClient#listDrives()
*/
@GET
@Path("/drives/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listDrives();
/**
* @see ElasticHostsClient#listStandardDrives()
*/
@GET
@Path("/drives/standard/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listStandardDrives();
/**
* @see ElasticHostsClient#listStandardCds()
*/
@GET
@Path("/drives/standard/cd/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listStandardCds();
/**
* @see ElasticHostsClient#listStandardImages()
*/
@GET
@Path("/drives/standard/img/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listStandardImages();
/**
* @see ElasticHostsClient#listDriveInfo()
*/
@GET
@Path("/drives/info")
@ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class)
ListenableFuture<Set<DriveInfo>> listDriveInfo();
/**
* @see ElasticHostsClient#getDriveInfo
*/
@GET
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/{uuid}/info")
ListenableFuture<DriveInfo> getDriveInfo(@PathParam("uuid") String uuid);
/**
* @see ElasticHostsClient#createDrive
*/
@POST
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/create")
ListenableFuture<DriveInfo> createDrive(
@BinderParam(BindCreateDriveRequestToPlainTextString.class) CreateDriveRequest createDrive);
/**
* @see ElasticHostsClient#setDriveData
*/
@POST
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/{uuid}/set")
ListenableFuture<DriveInfo> setDriveData(@PathParam("uuid") String uuid,
@BinderParam(BindDriveDataToPlainTextString.class) DriveData createDrive);
/**
* @see ElasticHostsClient#destroyDrive
*/
@POST
@Path("/drives/{uuid}/destroy")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> destroyDrive(@PathParam("uuid") String uuid);
/**
* @see ElasticHostsClient#imageDrive(String,String)
*/
@POST
@Path("/drives/{destination}/image/{source}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> imageDrive(@PathParam("source") String source, @PathParam("destination") String destination);
/**
* @see ElasticHostsClient#imageDrive(String,String,ImageConversionType)
*/
@POST
@Path("/drives/{destination}/image/{source}/{conversion}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> imageDrive(@PathParam("source") String source, @PathParam("destination") String destination,
@PathParam("conversion") ImageConversionType conversionType);
/**
* @see ElasticHostsClient#readDrive(String)
*/
@GET
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Path("/drives/{uuid}/read")
@ResponseParser(ReturnPayload.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Payload> readDrive(@PathParam("uuid") String uuid);
/**
* @see ElasticHostsClient#readDrive(String,ReadDriveOptions)
*/
@POST
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Path("/drives/{uuid}/read")
@ResponseParser(ReturnPayload.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Payload> readDrive(@PathParam("uuid") String uuid,
@BinderParam(BindReadDriveOptionsToPath.class) ReadDriveOptions options);
/**
* @see ElasticHostsClient#writeDrive(String, Payload)
*/
@POST
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Path("/drives/{uuid}/write")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> writeDrive(@PathParam("uuid") String uuid, Payload content);
/**
* @see ElasticHostsClient#writeDrive(String, Payload, long)
*/
@POST
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Path("/drives/{uuid}/write/{offset}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> writeDrive(@PathParam("uuid") String uuid, Payload content, @PathParam("offset") long offset);
}

View File

@ -0,0 +1,170 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.elastichosts;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.elastichosts.domain.CreateDriveRequest;
import org.jclouds.elastichosts.domain.DriveData;
import org.jclouds.elastichosts.domain.DriveInfo;
import org.jclouds.elastichosts.domain.ImageConversionType;
import org.jclouds.elastichosts.options.ReadDriveOptions;
import org.jclouds.io.Payload;
/**
* Provides synchronous access to ElasticHosts.
* <p/>
*
* @see ElasticHostsAsyncClient
* @see <a href="TODO: insert URL of ElasticHosts documentation" />
* @author Adrian Cole
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface ElasticHostsClient {
/**
* list of drive uuids in your account
*
* @return or empty set if no drives are found
*/
Set<String> listDrives();
/**
* list of drive uuids that are in the library
*
* @return or empty set if no drives are found
*/
Set<String> listStandardDrives();
/**
* list of cd uuids that are in the library
*
* @return or empty set if no cds are found
*/
Set<String> listStandardCds();
/**
* list of image uuids that are in the library
*
* @return or empty set if no images are found
*/
Set<String> listStandardImages();
/**
* Get all drives info
*
* @return or empty set if no drives are found
*/
Set<DriveInfo> listDriveInfo();
/**
* @param uuid
* what to get
* @return null, if not found
*/
DriveInfo getDriveInfo(String uuid);
/**
* create a new drive
*
* @param createDrive
* required parameters: name, size
* @return newly created drive
*/
DriveInfo createDrive(CreateDriveRequest createDrive);
/**
* set extra drive data
*
* @param uuid
* what drive to change
* @param driveData
* what values to change
* @return new data
*/
DriveInfo setDriveData(String uuid, DriveData driveData);
/**
* Destroy a drive
*
* @param uuid
* what to delete
*/
void destroyDrive(String uuid);
/**
* Image a drive from another drive. The actual imaging process is asynchronous, with progress
* reported via drive info.
*
* @param source
* drive to copy from
* @param destination
* drive to copy to
*/
void imageDrive(String source, String destination);
/**
* @see #imageDrive(String, String)
* @param conversionType
* Supports 'gzip' or 'gunzip' conversions.
*/
void imageDrive(String source, String destination, ImageConversionType conversionType);
/**
* Read binary data from a drive
*
* @param uuid
* drive to read
* @return binary content of the drive.
*/
Payload readDrive(String uuid);
/**
* @see #readDrive(String)
* @param options
* controls offset and size of the request
*/
Payload readDrive(String uuid, ReadDriveOptions options);
/**
* Write binary data to a drive
*
* @param uuid
* drive to write
* @param content
* what to write.
* <ul>
* <li>Binary data (Content-Type: application/octet-stream)</li>
* <li>Supports raw data or Content-Encoding: gzip</li>
* <li>Does not support Transfer-Encoding: chunked</li>
* </ul>
*/
void writeDrive(String uuid, Payload content);
/**
* @see ElasticHostsClient#writeDrive(String, Payload)
* @param offset
* the byte offset in the target drive at which to start writing, not an offset in the
* input stream.
*/
void writeDrive(String uuid, Payload content, long offset);
}

Some files were not shown because too many files have changed in this diff Show More