mirror of https://github.com/apache/jclouds.git
Merge branch 'master' of github.com:jclouds/jclouds
This commit is contained in:
commit
8b716a06d8
24
README.txt
24
README.txt
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 + "]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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()));
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 < > 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>>() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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.*");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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")) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue