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

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -64,44 +64,51 @@ 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());
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 path = command.getRequest().getEndpoint().getPath();
Matcher matcher = DIRECTORY_PATH.matcher(path);
case 401:
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 path = command.getRequest().getEndpoint().getPath();
Matcher matcher = DIRECTORY_PATH.matcher(path);
if (matcher.find()) {
exception = new ContainerNotFoundException(matcher.group(1), message);
} else {
matcher = DIRECTORY_KEY_PATH.matcher(path);
if (matcher.find()) {
exception = new ContainerNotFoundException(matcher.group(1), message);
} 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);
}
break;
default:
exception = error != null ? new AtmosStorageResponseException(command, response, error)
: new HttpResponseException(command, response);
}
}
@ -111,17 +118,4 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
}
}
AtmosStorageError parseErrorFromContentOrNull(HttpCommand command, HttpResponse response) {
if (response.getPayload() != null) {
try {
String content = Utils.toStringAndClose(response.getPayload().getInput());
if (content != null && content.indexOf('<') >= 0)
return utils.parseAtmosStorageErrorFromContent(command, response, Utils
.toInputStream(content));
} catch (IOException e) {
logger.warn(e, "exception reading error from response", response);
}
}
return null;
}
}

View File

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

View File

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

View File

@ -26,6 +26,7 @@ import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_CC_AMIs;
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_ELB_ENDPOINT;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_TIMEOUT_NODE_SUSPENDED;
import java.util.Properties;
@ -49,11 +50,15 @@ 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");
properties.setProperty("jclouds.ssh.retryable_messages",
"Auth fail,invalid data,End of IO Stream Read,Connection reset,socket is not established");
"Auth fail,invalid data,End of IO Stream Read,Connection reset,socket is not established");
return properties;
}

View File

@ -24,8 +24,8 @@ import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
import static org.jclouds.util.Utils.checkNotEmpty;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
@ -55,12 +55,13 @@ import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.http.HttpResponseException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
@ -80,23 +81,23 @@ public class EC2ComputeService extends BaseComputeService {
@Inject
protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, ComputeUtils utils, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, ComputeUtils utils, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@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,21 +109,28 @@ public class EC2ComputeService extends BaseComputeService {
void deletePlacementGroup(String region, String tag) {
checkNotEmpty(tag, "tag");
String group = String.format("jclouds#%s#%s", tag, region);
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));
placementGroupMap.remove(new RegionAndName(region, tag));
logger.debug("<< deleted placementGroup(%s)", group);
} catch (AWSResponseException e) {
if (e.getError().getCode().equals("InvalidPlacementGroup.InUse")) {
logger.debug("<< inUse placementGroup(%s)", group);
} else {
throw e;
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));
placementGroupMap.remove(new RegionAndName(region, tag));
logger.debug("<< deleted placementGroup(%s)", group);
} catch (AWSResponseException e) {
if (e.getError().getCode().equals("InvalidPlacementGroup.InUse")) {
logger.debug("<< inUse placementGroup(%s)", group);
} else {
throw e;
}
}
}
} catch (HttpResponseException e) {
// Eucalyptus does not support placement groups yet.
if (!(e.getResponse().getStatusCode() == 400 && context.getProviderSpecificContext().getProvider()
.equals("eucalyptus")))
throw e;
}
}

View File

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

View File

@ -21,8 +21,8 @@ package org.jclouds.aws.ec2.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseOsFamilyOrNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseVersionOrReturnEmptyString;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher;
@ -42,6 +42,7 @@ import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
@ -72,32 +73,35 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
// amzn-ami-us-east-1/amzn-ami-0.9.7-beta.x86_64.manifest.xml
// amzn-ami-us-east-1/amzn-ami-0.9.7-beta.i386.manifest.xml
public static final Pattern AMZN_PATTERN = Pattern
.compile(".*/amzn-ami-(.*)\\.(i386|x86_64)(-ebs|\\.manifest.xml)?");
.compile(".*/amzn-ami-(.*)\\.(i386|x86_64)(-ebs|\\.manifest.xml)?");
public static final Pattern CANONICAL_PATTERN = Pattern.compile(".*/([^-]*)-([^-]*)-.*-(.*)(\\.manifest.xml)?");
// ex rightscale-us-east/CentOS_5.4_x64_v4.4.10.manifest.xml
public static final Pattern RIGHTSCALE_PATTERN = Pattern
.compile("[^/]*/([^_]*)_([^_]*)_[^vV]*[vV](.*)(\\.manifest.xml)?");
.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
@ -111,12 +115,13 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
builder.id(from.getRegion() + "/" + from.getId());
builder.description(from.getDescription() != null ? from.getDescription() : from.getImageLocation());
builder.userMetadata(ImmutableMap.<String, String> of("owner", from.getImageOwnerId(), "rootDeviceType", from
.getRootDeviceType().toString()));
.getRootDeviceType().toString()));
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) {
@ -152,7 +157,7 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
} catch (NoSuchElementException e) {
System.err.printf("unknown region %s for image %s; not in %s", from.getRegion(), from.getId(), locations);
builder.location(new LocationImpl(LocationScope.REGION, from.getRegion(), from.getRegion(), defaultLocation
.get().getParent()));
.get().getParent()));
}
builder.operatingSystem(new OperatingSystem(osFamily, osName, osVersion, osArch, osDescription, is64Bit));
return builder.build();
@ -165,7 +170,7 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
*/
private Matcher getMatcherAndFind(String manifest) {
for (Pattern pattern : new Pattern[] { AMZN_PATTERN, NEBULA_PATTERN, CANONICAL_PATTERN, RIGHTIMAGE_PATTERN,
RIGHTSCALE_PATTERN }) {
RIGHTSCALE_PATTERN }) {
Matcher matcher = pattern.matcher(manifest);
if (matcher.find())
return matcher;

View File

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

View File

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

View File

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

View File

@ -72,8 +72,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
String message = null;
if (response.getPayload() != null) {
String contentType = response.getPayload().getContentMetadata().getContentType();
if (contentType != null
&& (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)) {
if (contentType != null && (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)) {
error = utils.parseAWSErrorFromContent(request, response);
if (error != null) {
message = error.getMessage();
@ -82,40 +81,42 @@ 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))
exception = new IllegalStateException(message, exception);
else if (error != null && error.getCode() != null && error.getCode().equals("AuthFailure"))
exception = new AuthorizationException(command.getRequest(), message);
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);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
String container = request.getEndpoint().getHost();
String key = request.getEndpoint().getPath();
if (key == null || key.equals("/"))
exception = new ContainerNotFoundException(container, message);
else
exception = new KeyNotFoundException(container, key, message);
}
break;
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))
exception = new IllegalStateException(message, exception);
else if (error != null && error.getCode() != null && error.getCode().equals("AuthFailure"))
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(exception.getMessage(), exception);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
String container = request.getEndpoint().getHost();
String key = request.getEndpoint().getPath();
if (key == null || key.equals("/"))
exception = new ContainerNotFoundException(container, message);
else
exception = new KeyNotFoundException(container, key, message);
}
break;
case 409:
exception = new IllegalStateException(message, exception);
}
} finally {
releasePayload(response);

View File

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

View File

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

View File

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

View File

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

View File

@ -77,7 +77,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public void testImagesResolveCorrectly() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getId(), defaultTemplate.getImage().getLocation().getId() + "/"
+ defaultTemplate.getImage().getProviderId());
+ defaultTemplate.getImage().getProviderId());
Template byId = client.templateBuilder().imageId(defaultTemplate.getImage().getId()).build();
assertEquals(byId.getImage(), defaultTemplate.getImage());
}
@ -98,13 +98,13 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsAndLogin() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
.getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
.getInstanceServices();
String tag = this.tag + "optionsandlogin";
@ -141,17 +141,17 @@ 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,
"jclouds#" + tag + "#" + instance.getRegion()));
"jclouds#" + tag + "#" + instance.getRegion()));
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));
@ -168,11 +168,11 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assertEquals(instance.getMonitoringState(), MonitoringState.ENABLED);
RestContext<CloudWatchClient, CloudWatchAsyncClient> monitoringContext = new RestContextFactory().createContext(
"cloudwatch", identity, credential, ImmutableSet.<Module> of(new Log4JLoggingModule()));
"cloudwatch", identity, credential, ImmutableSet.<Module> of(new Log4JLoggingModule()));
try {
Set<Datapoint> datapoints = monitoringContext.getApi().getMetricStatisticsInRegion(instance.getRegion(),
"CPUUtilization", before, new Date(), 60, "Average");
"CPUUtilization", before, new Date(), 60, "Average");
assert datapoints != null;
} finally {
monitoringContext.close();
@ -182,13 +182,13 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsNoKeyPair() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
.getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
.getInstanceServices();
String tag = this.tag + "optionsnokey";
@ -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 {
@ -242,13 +242,13 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
return;
}
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
.getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
.getInstanceServices();
String tag = this.tag + "optionswithsubnetid";
@ -295,12 +295,12 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
private RunningInstance getInstance(InstanceClient instanceClient, String id) {
RunningInstance instance = Iterables.getOnlyElement(Iterables.getOnlyElement(instanceClient
.describeInstancesInRegion(null, id)));
.describeInstancesInRegion(null, id)));
return instance;
}
private void cleanupExtendedStuff(SecurityGroupClient securityGroupClient, KeyPairClient keyPairClient, String tag)
throws InterruptedException {
throws InterruptedException {
try {
for (SecurityGroup group : securityGroupClient.describeSecurityGroupsInRegion(null))
if (group.getName().startsWith("jclouds#" + tag) || group.getName().equals(tag)) {

View File

@ -19,24 +19,24 @@
package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Properties;
import org.jclouds.Constants;
import org.jclouds.aws.ec2.domain.InstanceType;
import org.jclouds.aws.ec2.reference.EC2Constants;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
@ -45,147 +45,106 @@ 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)
.osVersionMatches("10.10").imageDescriptionMatches("ubuntu-images").osFamily(OsFamily.UBUNTU).build();
Template template = context.getComputeService().templateBuilder().hardwareId(InstanceType.M1_SMALL)
.osVersionMatches("10.10").imageDescriptionMatches("ubuntu-images").osFamily(OsFamily.UBUNTU).build();
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(), "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);
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().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")
.hardwareId(InstanceType.M2_2XLARGE).build();
Template template = context.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5")
.hardwareId(InstanceType.M2_2XLARGE).build();
System.out.println(template.getHardware());
assert (template.getImage().getProviderId().startsWith("ami-")) : template;
assertEquals(template.getImage().getOperatingSystem().getVersion(), "5.4");
assertEquals(template.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(template.getImage().getOperatingSystem().getFamily(), OsFamily.CENTOS);
assertEquals(template.getImage().getVersion(), "4.4.10");
assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");
assertEquals(template.getLocation().getId(), "us-east-1");
assertEquals(getCores(template.getHardware()), 4.0d);
assertEquals(template.getHardware().getId(), InstanceType.M2_2XLARGE);
System.out.println(template.getHardware());
assert (template.getImage().getProviderId().startsWith("ami-")) : template;
assertEquals(template.getImage().getOperatingSystem().getVersion(), "5.4");
assertEquals(template.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(template.getImage().getOperatingSystem().getFamily(), OsFamily.CENTOS);
assertEquals(template.getImage().getVersion(), "4.4.10");
assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");
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();
assert (defaultTemplate.getImage().getProviderId().startsWith("ami-")) : defaultTemplate;
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "0.9.9-beta");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.AMZN_LINUX);
assertEquals(defaultTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
assertEquals(defaultTemplate.getLocation().getId(), "us-east-1");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
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);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.AMZN_LINUX);
assertEquals(defaultTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
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");
assertEquals(microTemplate.getImage().getOperatingSystem().is64Bit(), false);
assertEquals(microTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(microTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
assertEquals(microTemplate.getLocation().getId(), "us-east-1");
assertEquals(getCores(microTemplate.getHardware()), 1.0d);
assert (microTemplate.getImage().getProviderId().startsWith("ami-")) : microTemplate;
assertEquals(microTemplate.getImage().getOperatingSystem().getVersion(), "9.10");
assertEquals(microTemplate.getImage().getOperatingSystem().is64Bit(), false);
assertEquals(microTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(microTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
assertEquals(microTemplate.getLocation().getId(), "us-east-1");
assertEquals(getCores(microTemplate.getHardware()), 1.0d);
} finally {
if (newContext != null)
newContext.close();
}
}
@Test
public void testTemplateBuilderWithNoOwnersParsesImageOnDemand() throws IOException {
ComputeServiceContext newContext = null;
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
// set owners to nothing
overrides.setProperty(EC2Constants.PROPERTY_EC2_AMI_OWNERS, "");
newContext = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides);
assertEquals(newContext.getComputeService().listImages().size(), 0);
assertEquals(context.getComputeService().listImages().size(), 0);
Template template = newContext.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5").build();
Template template = context.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5").build();
System.out.println(template.getHardware());
assert (template.getImage().getProviderId().startsWith("ami-")) : template;
assertEquals(template.getImage().getOperatingSystem().getVersion(), "5.4");
@ -199,11 +158,11 @@ public class EC2TemplateBuilderLiveTest {
// is 64bit
// ensure we cache the new image for next time
assertEquals(newContext.getComputeService().listImages().size(), 1);
assertEquals(context.getComputeService().listImages().size(), 1);
} finally {
if (newContext != null)
newContext.close();
if (context != null)
context.close();
}
}

View File

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

View File

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

View File

@ -27,6 +27,7 @@ import static org.easymock.classextension.EasyMock.verify;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
import static org.testng.Assert.assertEquals;
import java.util.NoSuchElementException;
import java.util.Set;
import org.jclouds.aws.ec2.EC2Client;
@ -44,7 +45,7 @@ import com.google.common.collect.ImmutableSet;
@Test(groups = "unit", testName = "ec2.RegionAndIdToImageTest")
public class RegionAndIdToImageTest {
@SuppressWarnings({ "unchecked"})
@SuppressWarnings({ "unchecked" })
@Test
public void testApply() {
@ -54,10 +55,10 @@ public class RegionAndIdToImageTest {
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);
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set)images);
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set) images);
expect(parser.apply(ec2Image)).andReturn(image);
replay(caller);
@ -76,7 +77,7 @@ public class RegionAndIdToImageTest {
}
@SuppressWarnings({ "unchecked"})
@SuppressWarnings({ "unchecked" })
@Test
public void testApplyNotFound() {
@ -86,10 +87,10 @@ public class RegionAndIdToImageTest {
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);
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set)images);
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set) images);
expect(parser.apply(ec2Image)).andThrow(new ResourceNotFoundException());
replay(caller);
@ -107,4 +108,36 @@ public class RegionAndIdToImageTest {
verify(client);
}
@SuppressWarnings({ "unchecked" })
@Test
public void testApplyNoSuchElementException() {
ImageParser parser = createMock(ImageParser.class);
EC2Client caller = createMock(EC2Client.class);
AMIClient client = createMock(AMIClient.class);
org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class);
Image image = createNiceMock(Image.class);
Set<? extends org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set) images);
expect(parser.apply(ec2Image)).andThrow(new NoSuchElementException());
replay(caller);
replay(image);
replay(parser);
replay(client);
RegionAndIdToImage function = new RegionAndIdToImage(parser, caller);
assertEquals(function.apply(new RegionAndName("region", "ami")), null);
verify(caller);
verify(image);
verify(parser);
verify(client);
}
}

View File

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

View File

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

View File

@ -30,7 +30,6 @@ import java.util.SortedSet;
import java.util.concurrent.TimeUnit;
import org.jclouds.Constants;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
@ -44,6 +43,7 @@ import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -71,13 +71,12 @@ public class ElasticBlockStoreClientLiveTest {
protected String endpoint;
protected String apiversion;
@BeforeClass
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint");
apiversion = checkNotNull(System.getProperty("test." + provider + ".apiversion"), "test." + provider
+ ".apiversion");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -85,9 +84,12 @@ public class ElasticBlockStoreClientLiveTest {
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
overrides.setProperty(provider + ".credential", credential);
overrides.setProperty(provider + ".endpoint", endpoint);
overrides.setProperty(provider + ".apiversion", apiversion);
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,15 +97,15 @@ 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();
}
@Test
void testDescribeVolumes() {
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
Region.AP_SOUTHEAST_1)) {
Region.AP_SOUTHEAST_1)) {
SortedSet<Volume> allResults = Sets.newTreeSet(client.describeVolumesInRegion(region));
assertNotNull(allResults);
if (allResults.size() >= 1) {
@ -136,11 +138,11 @@ public class ElasticBlockStoreClientLiveTest {
void testCreateSnapshotInRegion() {
Snapshot snapshot = client.createSnapshotInRegion(null, volumeId);
Predicate<Snapshot> snapshotted = new RetryablePredicate<Snapshot>(new SnapshotCompleted(client), 600, 10,
TimeUnit.SECONDS);
TimeUnit.SECONDS);
assert snapshotted.apply(snapshot);
Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(snapshot.getRegion(),
snapshotIds(snapshot.getId())));
snapshotIds(snapshot.getId())));
assertEquals(result.getProgress(), 100);
this.snapshot = result;
@ -152,7 +154,7 @@ public class ElasticBlockStoreClientLiveTest {
assertNotNull(volume);
Predicate<Volume> availabile = new RetryablePredicate<Volume>(new VolumeAvailable(client), 600, 10,
TimeUnit.SECONDS);
TimeUnit.SECONDS);
assert availabile.apply(volume);
Volume result = Iterables.getOnlyElement(client.describeVolumesInRegion(snapshot.getRegion(), volume.getId()));
@ -166,12 +168,12 @@ 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,
TimeUnit.SECONDS);
TimeUnit.SECONDS);
assert availabile.apply(volume);
Volume result = Iterables.getOnlyElement(client.describeVolumesInRegion(snapshot.getRegion(), volume.getId()));
@ -197,13 +199,13 @@ public class ElasticBlockStoreClientLiveTest {
@Test
void testDescribeSnapshots() {
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
Region.AP_SOUTHEAST_1)) {
Region.AP_SOUTHEAST_1)) {
SortedSet<Snapshot> allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region));
assertNotNull(allResults);
if (allResults.size() >= 1) {
Snapshot snapshot = allResults.last();
Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(region, snapshotIds(snapshot
.getId())));
Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(region,
snapshotIds(snapshot.getId())));
assertNotNull(result);
assertEquals(result, snapshot);
}
@ -246,12 +248,7 @@ public class ElasticBlockStoreClientLiveTest {
@Test(dependsOnMethods = "testGetCreateVolumePermissionForSnapshot")
void testDeleteSnapshotInRegion() {
client.deleteSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
try {
client.describeSnapshotsInRegion(snapshot.getRegion(), snapshotIds(snapshot.getId()));
assert false : "shoud have exception";
} catch (AWSResponseException e) {
assertEquals(e.getError().getCode(), "InvalidSnapshot.NotFound");
}
assert client.describeSnapshotsInRegion(snapshot.getRegion(), snapshotIds(snapshot.getId())).size() == 0;
}
@AfterTest

View File

@ -56,7 +56,9 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -85,13 +87,12 @@ public class PlacementGroupClientLiveTest {
protected String endpoint;
protected String apiversion;
@BeforeClass
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint");
apiversion = checkNotNull(System.getProperty("test." + provider + ".apiversion"), "test." + provider
+ ".apiversion");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -99,9 +100,12 @@ public class PlacementGroupClientLiveTest {
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
overrides.setProperty(provider + ".credential", credential);
overrides.setProperty(provider + ".endpoint", endpoint);
overrides.setProperty(provider + ".apiversion", apiversion);
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,14 +113,14 @@ 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());
availableTester = new RetryablePredicate<PlacementGroup>(new PlacementGroupAvailable(client), 60, 1,
TimeUnit.SECONDS);
TimeUnit.SECONDS);
deletedTester = new RetryablePredicate<PlacementGroup>(new PlacementGroupDeleted(client), 60, 1, TimeUnit.SECONDS);
}
@ -125,12 +129,12 @@ public class PlacementGroupClientLiveTest {
void testDescribe() {
for (String region : newArrayList(Region.US_EAST_1)) {
SortedSet<PlacementGroup> allResults = newTreeSet(client.getPlacementGroupServices()
.describePlacementGroupsInRegion(region));
.describePlacementGroupsInRegion(region));
assertNotNull(allResults);
if (allResults.size() >= 1) {
PlacementGroup group = allResults.last();
SortedSet<PlacementGroup> result = newTreeSet(client.getPlacementGroupServices()
.describePlacementGroupsInRegion(region, group.getName()));
.describePlacementGroupsInRegion(region, group.getName()));
assertNotNull(result);
PlacementGroup compare = result.last();
assertEquals(compare, group);
@ -159,7 +163,7 @@ public class PlacementGroupClientLiveTest {
private void verifyPlacementGroup(String groupName) {
assert availableTester.apply(new PlacementGroup(Region.US_EAST_1, groupName, "cluster", State.PENDING)) : group;
Set<PlacementGroup> oneResult = client.getPlacementGroupServices().describePlacementGroupsInRegion(null,
groupName);
groupName);
assertNotNull(oneResult);
assertEquals(oneResult.size(), 1);
group = oneResult.iterator().next();
@ -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>() {
@ -194,17 +199,19 @@ public class PlacementGroupClientLiveTest {
assertEquals(template.getImage().getId(), "us-east-1/ami-7ea24a17");
template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey(keyPair.get("public"))
.runScript(buildScript(template.getImage().getOperatingSystem()));
.runScript(buildScript(template.getImage().getOperatingSystem()));
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);
NodeMetadata node = getOnlyElement(nodes);
getOnlyElement(getOnlyElement(client.getInstanceServices().describeInstancesInRegion(null,
node.getProviderId())));
node.getProviderId())));
} catch (RunNodesException e) {
System.err.println(e.getNodeErrors().keySet());

View File

@ -68,6 +68,12 @@ public class ParseAWSErrorFromXmlContentTest {
assertCodeMakes("GET", URI.create("https://amazonaws.com/foo"), 400, "",
"<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() {

View File

@ -39,17 +39,17 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.AccessControlList.CanonicalUserGrantee;
import org.jclouds.aws.s3.domain.AccessControlList.EmailAddressGrantee;
import org.jclouds.aws.s3.domain.AccessControlList.Grant;
import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI;
import org.jclouds.aws.s3.domain.AccessControlList.Permission;
import org.jclouds.aws.s3.domain.BucketLogging;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.CannedAccessPolicy;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.Payer;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.AccessControlList.CanonicalUserGrantee;
import org.jclouds.aws.s3.domain.AccessControlList.EmailAddressGrantee;
import org.jclouds.aws.s3.domain.AccessControlList.Grant;
import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI;
import org.jclouds.aws.s3.domain.AccessControlList.Permission;
import org.jclouds.aws.s3.internal.StubS3AsyncClient;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.util.Utils;
@ -90,7 +90,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
}
public void testPrivateAclIsDefaultForBucket() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
IOException {
String bucketName = getContainerName();
try {
AccessControlList acl = getApi().getBucketACL(bucketName);
@ -105,7 +105,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
}
public void testUpdateBucketACL() throws InterruptedException, ExecutionException, TimeoutException, IOException,
Exception {
Exception {
String bucketName = getContainerName();
try {
// Confirm the bucket is private
@ -221,9 +221,9 @@ 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),
Permission.FULL_CONTROL)));
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 {
@ -334,7 +334,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
}
public void testListBucketDelimiter() throws InterruptedException, ExecutionException, TimeoutException,
UnsupportedEncodingException {
UnsupportedEncodingException {
String bucketName = getContainerName();
try {
String prefix = "apps";
@ -352,7 +352,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
}
public void testListBucketPrefix() throws InterruptedException, ExecutionException, TimeoutException,
UnsupportedEncodingException {
UnsupportedEncodingException {
String bucketName = getContainerName();
try {
String prefix = "apps";
@ -370,7 +370,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
}
public void testListBucketMaxResults() throws InterruptedException, ExecutionException, TimeoutException,
UnsupportedEncodingException {
UnsupportedEncodingException {
String bucketName = getContainerName();
try {
addAlphabetUnderRoot(bucketName);

View File

@ -68,10 +68,9 @@ public class SQSClientLiveTest {
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");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -79,9 +78,12 @@ public class SQSClientLiveTest {
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
overrides.setProperty(provider + ".credential", credential);
overrides.setProperty(provider + ".endpoint", endpoint);
overrides.setProperty(provider + ".apiversion", apiversion);
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,14 +92,14 @@ public class SQSClientLiveTest {
setupCredentials();
Properties overrides = setupProperties();
context = new RestContextFactory().createContext(provider, ImmutableSet.<Module> of(new Log4JLoggingModule()),
overrides);
overrides);
this.client = context.getApi();
}
@Test
void testListQueuesInRegion() throws InterruptedException {
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
Region.AP_SOUTHEAST_1)) {
Region.AP_SOUTHEAST_1)) {
SortedSet<Queue> allResults = Sets.newTreeSet(client.listQueuesInRegion(region));
assertNotNull(allResults);
if (allResults.size() >= 1) {
@ -114,7 +116,7 @@ public class SQSClientLiveTest {
String queueName = PREFIX + "1";
for (final String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
Region.AP_SOUTHEAST_1)) {
Region.AP_SOUTHEAST_1)) {
try {
SortedSet<Queue> result = Sets.newTreeSet(client.listQueuesInRegion(region, queuePrefix(queueName)));
if (result.size() >= 1) {
@ -182,7 +184,7 @@ public class SQSClientLiveTest {
assertion.run();
if (i > 0)
System.err.printf("%d attempts and %dms asserting %s%n", i + 1, System.currentTimeMillis() - start,
assertion.getClass().getSimpleName());
assertion.getClass().getSimpleName());
return;
} catch (AssertionError e) {
error = e;

View File

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

View File

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

View File

@ -68,44 +68,53 @@ 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)) {
AzureStorageError error = utils.parseAzureStorageErrorFromContent(command, response, response
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);
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) {
}
}
}
message = message != null ? message : String.format("%s -> %s", command.getRequest().getRequestLine(),
response.getStatusLine());
response.getStatusLine());
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(command.getRequest(), message);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
String path = command.getRequest().getEndpoint().getPath();
Matcher matcher = CONTAINER_PATH.matcher(path);
case 401:
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);
if (matcher.find()) {
exception = new ContainerNotFoundException(matcher.group(1), message);
} else {
matcher = CONTAINER_KEY_PATH.matcher(path);
if (matcher.find()) {
exception = new ContainerNotFoundException(matcher.group(1), message);
} else {
matcher = CONTAINER_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;
case 411:
exception = new IllegalArgumentException(message);
break;
}
break;
case 411:
exception = new IllegalArgumentException(message);
break;
}
} finally {
releasePayload(response);

View File

@ -28,6 +28,7 @@ import static org.easymock.classextension.EasyMock.verify;
import java.net.URI;
import org.easymock.IArgumentMatcher;
import org.jclouds.azure.storage.AzureStorageResponseException;
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
@ -49,14 +50,33 @@ public class ParseAzureErrorFromXmlContentTest {
@Test
public void test411WithTextHtmlIllegalArgumentException() {
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);
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) {
String content, Class<? extends Exception> expected) {
ParseAzureStorageErrorFromXmlContent function = Guice.createInjector(new SaxParserModule(), new AbstractModule() {
@ -70,7 +90,7 @@ public class ParseAzureErrorFromXmlContentTest {
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = new HttpRequest(method, uri);
HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Utils
.toInputStream(content)));
.toInputStream(content)));
response.getPayload().getContentMetadata().setContentType(contentType);
expect(command.getRequest()).andReturn(request).atLeastOnce();

View File

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

View File

@ -137,7 +137,7 @@ public interface ComputeService {
* default, equivalent to {@code templateBuilder().any().options(templateOptions)}.
*/
Set<? extends NodeMetadata> runNodesWithTag(String tag, int count, TemplateOptions templateOptions)
throws RunNodesException;
throws RunNodesException;
/**
* Like {@link ComputeService#runNodesWithTag(String,int,TemplateOptions)}, except that the
@ -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);
@ -224,7 +239,7 @@ public interface ComputeService {
* @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String)
*/
Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript)
throws RunScriptOnNodesException;
throws RunScriptOnNodesException;
/**
* Run the script on all nodes with the specific tag.
@ -243,6 +258,6 @@ public interface ComputeService {
* @see org.jclouds.io.Payloads
*/
Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
Payload runScript, RunScriptOptions options) throws RunScriptOnNodesException;
Payload runScript, RunScriptOptions options) throws RunScriptOnNodesException;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -20,6 +20,8 @@
package org.jclouds.compute.stub.config;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject;
@ -46,6 +48,7 @@ import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
/**
*
@ -60,12 +63,13 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
private final String privateIpPrefix;
private final String passwordPrefix;
private final String providerName;
private final Map<OsFamily, Map<String, String>> osToVersionMap;
@Inject
public StubComputeServiceAdapter(ConcurrentMap<String, NodeMetadata> nodes, Supplier<Location> location,
@Named("NODE_ID") Provider<Integer> idProvider, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PASSWORD_PREFIX") String passwordPrefix,
@org.jclouds.rest.annotations.Provider String providerName) {
@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, Map<OsFamily, Map<String, String>> osToVersionMap) {
this.nodes = nodes;
this.location = location;
this.idProvider = idProvider;
@ -73,11 +77,12 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
this.privateIpPrefix = privateIpPrefix;
this.passwordPrefix = passwordPrefix;
this.providerName = providerName;
this.osToVersionMap = osToVersionMap;
}
@Override
public NodeMetadata runNodeWithTagAndNameAndStoreCredentials(String tag, String name, Template template,
Map<String, Credentials> credentialStore) {
Map<String, Credentials> credentialStore) {
NodeMetadataBuilder builder = new NodeMetadataBuilder();
String id = idProvider.get() + "";
builder.ids(id);
@ -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
@ -134,9 +138,9 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
public Iterable<Location> listLocations() {
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
Location region = new LocationImpl(LocationScope.REGION, providerName + "region", providerName + "region",
provider);
provider);
return ImmutableSet.<Location> of(new LocationImpl(LocationScope.ZONE, providerName + "zone", providerName
+ "zone", region));
+ "zone", region));
}
@Override

View File

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

View File

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

View File

@ -161,8 +161,8 @@ public abstract class BaseComputeServiceLiveTest {
if (context != null)
context.close();
Properties props = setupProperties();
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet.of(new Log4JLoggingModule(),
getSshModule()), props);
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()), props);
client = context.getComputeService();
}
@ -173,8 +173,8 @@ public abstract class BaseComputeServiceLiveTest {
public void testCorrectAuthException() throws Exception {
ComputeServiceContext context = null;
try {
context = new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA", ImmutableSet
.<Module> of(new Log4JLoggingModule()));
context = new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA",
ImmutableSet.<Module> of(new Log4JLoggingModule()));
context.getComputeService().listNodes();
} catch (AuthorizationException e) {
throw e;
@ -217,7 +217,7 @@ public abstract class BaseComputeServiceLiveTest {
OperatingSystem os = get(nodes, 0).getOperatingSystem();
try {
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, os, new Credentials(
good.identity, "romeo"));
good.identity, "romeo"));
assert false : "shouldn't pass with a bad password\n" + responses;
} catch (RunScriptOnNodesException e) {
assert getRootCause(e).getMessage().contains("Auth fail") : e;
@ -276,7 +276,7 @@ public abstract class BaseComputeServiceLiveTest {
template = buildTemplate(client.templateBuilder());
template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey(keyPair.get("public"))
.runScript(buildScript(template.getImage().getOperatingSystem()));
.runScript(buildScript(template.getImage().getOperatingSystem()));
}
protected void checkImageIdMatchesTemplate(NodeMetadata node) {
@ -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) {
@ -320,10 +320,11 @@ public abstract class BaseComputeServiceLiveTest {
}
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String tag, OperatingSystem os,
Credentials creds) throws RunScriptOnNodesException {
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,16 +354,16 @@ 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))),
new Function<NodeMetadata, String>() {
Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex(
filter(client.listNodesDetailsMatching(all()), and(withTag(tag), not(TERMINATED))),
new Function<NodeMetadata, String>() {
@Override
public String apply(NodeMetadata from) {
return from.getId();
}
@Override
public String apply(NodeMetadata from) {
return from.getId();
}
}));
}));
for (NodeMetadata node : nodes) {
metadataMap.remove(node.getId());
NodeMetadata metadata = client.getNodeMetadata(node.getId());
@ -372,15 +373,16 @@ 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());
}
protected void assertNodeZero(Collection<? extends NodeMetadata> metadataSet) {
assert metadataSet.size() == 0 : String.format("nodes left in set: [%s] which didn't match set: [%s]",
metadataSet, nodes);
metadataSet, nodes);
}
@Test(enabled = true, dependsOnMethods = "testGet")
@ -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();
@ -462,11 +468,11 @@ public abstract class BaseComputeServiceLiveTest {
}
template = client.templateBuilder().options(blockOnComplete(false).blockOnPort(8080, 600).inboundPorts(22, 8080))
.build();
.build();
// note this is a dependency on the template resolution
template.getOptions().runScript(
RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage()
.getOperatingSystem()));
RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage()
.getOperatingSystem()));
try {
NodeMetadata node = getOnlyElement(client.runNodesWithTag(tag, 1, template));
@ -500,26 +506,26 @@ public abstract class BaseComputeServiceLiveTest {
assert location != location.getParent() : location;
assert location.getScope() != null : location;
switch (location.getScope()) {
case PROVIDER:
assertProvider(location);
break;
case REGION:
assertProvider(location.getParent());
break;
case ZONE:
Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider
if (provider == null)
provider = location.getParent();
assertProvider(provider);
break;
case HOST:
Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider
if (provider2 == null)
provider2 = location.getParent().getParent();
assertProvider(provider2);
break;
case PROVIDER:
assertProvider(location);
break;
case REGION:
assertProvider(location.getParent());
break;
case ZONE:
Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider
if (provider == null)
provider = location.getParent();
assertProvider(provider);
break;
case HOST:
Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider
if (provider2 == null)
provider2 = location.getParent().getParent();
assertProvider(provider2);
break;
}
}
}
@ -607,7 +613,7 @@ public abstract class BaseComputeServiceLiveTest {
assertEquals(hello.getOutput().trim(), "hello");
ExecResponse exec = ssh.exec("java -version");
assert exec.getError().indexOf("1.6") != -1 || exec.getOutput().indexOf("1.6") != -1 : exec + "\n"
+ ssh.exec("cat /tmp/bootstrap/stdout.log /tmp/bootstrap/stderr.log");
+ ssh.exec("cat /tmp/bootstrap/stdout.log /tmp/bootstrap/stderr.log");
} finally {
if (ssh != null)
ssh.disconnect();

View File

@ -0,0 +1,173 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.jclouds.Constants;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.Guice;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
@Test(groups = "integration,live", testName = "compute.BaseTemplateBuilderLiveTest")
public abstract class BaseTemplateBuilderLiveTest {
protected String provider;
protected String identity;
protected String credential;
protected String endpoint;
protected String apiversion;
protected ComputeServiceContext context;
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
Properties overrides = new Properties();
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}
@BeforeClass
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException, IOException {
setupCredentials();
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), setupProperties());
}
@DataProvider(name = "osSupported")
public Object[][] osSupported() {
return convertToArray(Sets.filter(provideAllOperatingSystems(),
Predicates.not(defineUnsupportedOperatingSystems())));
}
protected Object[][] convertToArray(Set<OsFamilyVersion64Bit> supportedOperatingSystems) {
Object[][] returnVal = new Object[supportedOperatingSystems.size()][1];
int i = 0;
for (OsFamilyVersion64Bit config : supportedOperatingSystems)
returnVal[i++][0] = config;
return returnVal;
}
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return Predicates.alwaysFalse();
}
@DataProvider(name = "osNotSupported")
public Object[][] osNotSupported() {
return convertToArray(Sets.filter(provideAllOperatingSystems(), defineUnsupportedOperatingSystems()));
}
protected Set<OsFamilyVersion64Bit> provideAllOperatingSystems() {
Map<OsFamily, Map<String, String>> map = new BaseComputeServiceContextModule() {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(new GsonModule())
.getInstance(Json.class));
Set<OsFamilyVersion64Bit> supportedOperatingSystems = Sets.newHashSet();
for (Entry<OsFamily, Map<String, String>> osVersions : map.entrySet()) {
for (String version : Sets.newHashSet(osVersions.getValue().values())) {
supportedOperatingSystems.add(new OsFamilyVersion64Bit(osVersions.getKey(), version, false));
supportedOperatingSystems.add(new OsFamilyVersion64Bit(osVersions.getKey(), version, true));
}
}
return supportedOperatingSystems;
}
@Test(dataProvider = "osSupported")
public void testTemplateBuilderCanFind(OsFamilyVersion64Bit matrix) throws InterruptedException {
Template template = context.getComputeService().templateBuilder().osFamily(matrix.family)
.osVersionMatches("^" + matrix.version + "$").os64Bit(matrix.is64Bit).build();
assertEquals(template.getImage().getOperatingSystem().getVersion(), matrix.version);
assertEquals(template.getImage().getOperatingSystem().is64Bit(), matrix.is64Bit);
assertEquals(template.getImage().getOperatingSystem().getFamily(), matrix.family);
}
@Test(dataProvider = "osNotSupported", expectedExceptions = NoSuchElementException.class)
public void testTemplateBuilderCannotFind(OsFamilyVersion64Bit matrix) throws InterruptedException {
context.getComputeService().templateBuilder().osFamily(matrix.family)
.osVersionMatches("^" + matrix.version + "$").os64Bit(matrix.is64Bit).build();
}
@Test
public void testTemplateBuilderCanUseImageId() {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
Template template = context.getComputeService().templateBuilder().imageId(defaultTemplate.getImage().getId())
.build();
assertEquals(template.getImage(), defaultTemplate.getImage());
}
@Test
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
@AfterTest
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
context.close();
}
}

View File

@ -0,0 +1,70 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.compute;
import org.jclouds.compute.domain.OsFamily;
public class OsFamilyVersion64Bit {
public final OsFamily family;
public final String version;
public final boolean is64Bit;
public OsFamilyVersion64Bit(OsFamily family, String version, boolean is64Bit) {
this.family = family;
this.version = version;
this.is64Bit = is64Bit;
}
@Override
public String toString() {
return "OsFamilyVersion64Bit [family=" + family + ", version=" + version + ", is64Bit=" + is64Bit + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((family == null) ? 0 : family.hashCode());
result = prime * result + (is64Bit ? 1231 : 1237);
result = prime * result + ((version == null) ? 0 : version.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OsFamilyVersion64Bit other = (OsFamilyVersion64Bit) obj;
if (family != other.family)
return false;
if (is64Bit != other.is64Bit)
return false;
if (version == null) {
if (other.version != null)
return false;
} else if (!version.equals(other.version))
return false;
return true;
}
}

View File

@ -24,7 +24,6 @@ import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.reportMatcher;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import java.io.FileNotFoundException;
@ -38,8 +37,6 @@ import java.util.concurrent.TimeoutException;
import org.easymock.IArgumentMatcher;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.io.Payload;
import org.jclouds.net.IPSocket;
@ -50,7 +47,6 @@ import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException;
import org.jclouds.util.Utils;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Throwables;
@ -63,15 +59,13 @@ import com.google.inject.Module;
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true, testName = "stub.StubComputeServiceIntegrationTest")
@Test(groups = "live", testName = "stub.StubComputeServiceIntegrationTest")
public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTest {
private static final ExecResponse EXEC_GOOD = new ExecResponse("", "", 0);
private static final ExecResponse EXEC_BAD = new ExecResponse("", "", 1);
@BeforeClass
@Override
public void setServiceDefaults() {
public StubComputeServiceIntegrationTest() {
provider = "stub";
}
@ -79,15 +73,6 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
public void testCorrectAuthException() throws Exception {
}
@Test
public void testTemplateBuilder() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().getArch(), "X86_64");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), provider + "zone");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
protected void buildSocketTester() {
SocketOpen socketOpen = createMock(SocketOpen.class);
@ -121,48 +106,48 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
SshClient client5 = createMock(SshClient.class);
expect(factory.create(new IPSocket("144.175.1.1", 22), new Credentials("root", "password1"))).andReturn(
client1);
client1);
runScriptAndService(client1, 1);
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "password2"))).andReturn(
client2).times(2);
client2).times(2);
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "romeo"))).andThrow(
new SshException("Auth fail"));
new SshException("Auth fail"));
client2.connect();
try {
runScript(client2, "runScriptWithCreds", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class
.getResourceAsStream("/runscript.sh")), 2);
.getResourceAsStream("/runscript.sh")), 2);
} catch (IOException e) {
Throwables.propagate(e);
}
client2.disconnect();
expect(factory.create(new IPSocket("144.175.1.3", 22), new Credentials("root", "password3"))).andReturn(
client3).times(2);
client3).times(2);
expect(factory.create(new IPSocket("144.175.1.4", 22), new Credentials("root", "password4"))).andReturn(
client4).times(2);
client4).times(2);
expect(factory.create(new IPSocket("144.175.1.5", 22), new Credentials("root", "password5"))).andReturn(
client5).times(2);
client5).times(2);
runScriptAndInstallSsh(client3, "bootstrap", 3);
runScriptAndInstallSsh(client4, "bootstrap", 4);
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);
@ -184,7 +169,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
try {
runScript(client, "jboss", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class
.getResourceAsStream("/initscript_with_jboss.sh")), nodeId);
.getResourceAsStream("/initscript_with_jboss.sh")), nodeId);
} catch (IOException e) {
Throwables.propagate(e);
}
@ -198,7 +183,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
try {
runScript(client, scriptName, Utils.toStringAndClose(StubComputeServiceIntegrationTest.class
.getResourceAsStream("/initscript_with_java.sh")), nodeId);
.getResourceAsStream("/initscript_with_java.sh")), nodeId);
} catch (IOException e) {
Throwables.propagate(e);
}
@ -251,7 +236,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
public void testAssignability() throws Exception {
@SuppressWarnings("unused")
RestContext<ConcurrentMap<String, NodeMetadata>, ConcurrentMap<String, NodeMetadata>> stubContext = new ComputeServiceContextFactory()
.createContext(provider, identity, credential).getProviderSpecificContext();
.createContext(provider, identity, credential).getProviderSpecificContext();
}
private static class PayloadEquals implements IArgumentMatcher, Serializable {
@ -298,7 +283,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
return false;
PayloadEquals other = (PayloadEquals) o;
return this.expected == null && other.expected == null || this.expected != null
&& this.expected.equals(other.expected);
&& this.expected.equals(other.expected);
}
@Override
@ -321,6 +306,11 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
super.testImagesCache();
}
@Override
public void testCompareSizes() throws Exception {
super.testCompareSizes();
}
@Test(enabled = true, dependsOnMethods = { "testImagesCache" })
public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception {
super.testAScriptExecutionAfterBootWithBasicTemplate();

View File

@ -0,0 +1,41 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.compute;
import org.testng.annotations.Test;
/**
*
*
* @author Adrian Cole
*/
@Test(groups = { "integration", "live" }, testName = "stub.StubTemplateBuilderIntegrationTest")
public class StubTemplateBuilderIntegrationTest extends BaseTemplateBuilderLiveTest {
public StubTemplateBuilderIntegrationTest() {
provider = "stub";
}
@Override
protected void setupCredentials() {
identity = "stub";
credential = "stub";
}
}

View File

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

View File

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

View File

@ -35,6 +35,7 @@ import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.concurrent.Timeout;
import org.jclouds.http.HttpResponseException;
import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
@ -57,7 +58,7 @@ public class SyncProxy implements InvocationHandler {
@SuppressWarnings("unchecked")
public static <T> T proxy(Class<T> clazz, SyncProxy proxy) throws IllegalArgumentException, SecurityException,
NoSuchMethodException {
NoSuchMethodException {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] { clazz }, proxy);
}
@ -72,8 +73,8 @@ public class SyncProxy implements InvocationHandler {
@Inject
public SyncProxy(Class<?> declaring, Object async,
@Named("sync") ConcurrentMap<ClassMethodArgs, Object> delegateMap, Map<Class<?>, Class<?>> sync2Async)
throws SecurityException, NoSuchMethodException {
@Named("sync") ConcurrentMap<ClassMethodArgs, Object> delegateMap, Map<Class<?>, Class<?>> sync2Async)
throws SecurityException, NoSuchMethodException {
this.delegateMap = delegateMap;
this.delegate = async;
this.declaring = declaring;
@ -92,7 +93,7 @@ public class SyncProxy implements InvocationHandler {
Method delegatedMethod = delegate.getClass().getMethod(method.getName(), method.getParameterTypes());
if (!Arrays.equals(delegatedMethod.getExceptionTypes(), method.getExceptionTypes()))
throw new IllegalArgumentException(String.format(
"method %s has different typed exceptions than delegated method %s", method, delegatedMethod));
"method %s has different typed exceptions than delegated method %s", method, delegatedMethod));
if (delegatedMethod.getReturnType().isAssignableFrom(ListenableFuture.class)) {
if (method.isAnnotationPresent(Timeout.class)) {
Timeout methodTimeout = method.getAnnotation(Timeout.class);
@ -124,7 +125,7 @@ public class SyncProxy implements InvocationHandler {
} else if (method.isAnnotationPresent(Delegate.class)) {
Class<?> asyncClass = sync2Async.get(method.getReturnType());
checkState(asyncClass != null, "please configure corresponding async class for " + method.getReturnType()
+ " in your RestClientModule");
+ " in your RestClientModule");
Object returnVal = delegateMap.get(new ClassMethodArgs(asyncClass, method, args));
return returnVal;
} else if (syncMethodMap.containsKey(method)) {
@ -132,7 +133,7 @@ public class SyncProxy implements InvocationHandler {
} else {
try {
return ((ListenableFuture<?>) methodMap.get(method).invoke(delegate, args)).get(timeoutMap.get(method),
TimeUnit.NANOSECONDS);
TimeUnit.NANOSECONDS);
} catch (ProvisionException e) {
throw throwTypedExceptionOrCause(method.getExceptionTypes(), e);
} catch (ExecutionException e) {
@ -143,6 +144,7 @@ public class SyncProxy implements InvocationHandler {
}
}
// Note this needs to be kept up-to-date with all top-level exceptions jclouds works against
@SuppressWarnings("unchecked")
public static Exception throwTypedExceptionOrCause(Class[] exceptionTypes, Exception exception) throws Exception {
for (Class type : exceptionTypes) {
@ -154,6 +156,7 @@ public class SyncProxy implements InvocationHandler {
Throwables.propagateIfInstanceOf(exception, IllegalStateException.class);
Throwables.propagateIfInstanceOf(exception, AuthorizationException.class);
Throwables.propagateIfInstanceOf(exception, ResourceNotFoundException.class);
Throwables.propagateIfInstanceOf(exception, HttpResponseException.class);
Throwables.throwCause(exception, true);
return exception;
}

View File

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

View File

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

View File

@ -26,12 +26,10 @@ import static com.google.common.io.Closeables.closeQuietly;
import java.io.InputStream;
import java.io.StringReader;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.logging.Logger;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.Utils;
@ -41,6 +39,7 @@ import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
/**
* This object will parse the body of an HttpResponse and return the result of type <T> back to the
@ -52,8 +51,6 @@ public class ParseSax<T> implements Function<HttpResponse, T>, InvocationContext
private final XMLReader parser;
private final HandlerWithResult<T> handler;
@Resource
protected Logger logger = Logger.NULL;
private HttpRequest request;
public static interface Factory {
@ -71,7 +68,7 @@ public class ParseSax<T> implements Function<HttpResponse, T>, InvocationContext
checkNotNull(from, "http response");
checkNotNull(from.getPayload(), "payload in " + from);
} catch (NullPointerException e) {
return addRequestDetailsToException(e);
return addDetailsAndPropagate(from, e);
}
if (from.getStatusCode() >= 300)
return convertStreamToStringAndParse(from);
@ -82,7 +79,7 @@ public class ParseSax<T> implements Function<HttpResponse, T>, InvocationContext
try {
return parse(Utils.toStringAndClose(from.getPayload().getInput()));
} catch (Exception e) {
return addRequestDetailsToException(e);
return addDetailsAndPropagate(from, e);
}
}
@ -91,7 +88,7 @@ public class ParseSax<T> implements Function<HttpResponse, T>, InvocationContext
checkNotNull(from, "xml string");
checkArgument(from.indexOf('<') >= 0, String.format("not an xml document [%s] ", from));
} catch (RuntimeException e) {
return addRequestDetailsToException(e);
return addDetailsAndPropagate(null, e);
}
return parse(new InputSource(new StringReader(from)));
}
@ -113,31 +110,39 @@ public class ParseSax<T> implements Function<HttpResponse, T>, InvocationContext
parser.parse(from);
return getHandler().getResult();
} catch (Exception e) {
return addRequestDetailsToException(e);
return addDetailsAndPropagate(null, e);
}
}
private T addRequestDetailsToException(Exception e) {
String exceptionMessage = e.getMessage();
public T addDetailsAndPropagate(HttpResponse response, Exception e) {
StringBuilder message = new StringBuilder();
if (request != null) {
message.append("request: ").append(request.getRequestLine());
}
if (response != null) {
if (message.length() != 0)
message.append("; ");
message.append("response: ").append(response.getStatusLine());
}
if (e instanceof SAXParseException) {
SAXParseException parseException = (SAXParseException) e;
String systemId = parseException.getSystemId();
if (systemId == null) {
systemId = "";
}
exceptionMessage = String.format("Error on line %d of document %s: %s", systemId, parseException
.getLineNumber(), parseException.getMessage());
if (message.length() != 0)
message.append("; ");
message.append(String.format("error at %d:%d in document %s", parseException.getColumnNumber(),
parseException.getLineNumber(), systemId));
}
if (request != null) {
StringBuilder message = new StringBuilder();
message.append("Error parsing input for ").append(request.getRequestLine()).append(": ");
message.append(exceptionMessage);
logger.error(e, message.toString());
if (message.length() != 0) {
message.append("; cause: ").append(e.toString());
throw new RuntimeException(message.toString(), e);
} else {
logger.error(e, exceptionMessage.toString());
throw new RuntimeException(exceptionMessage.toString(), e);
Throwables.propagate(e);
return null;
}
}
public HandlerWithResult<T> getHandler() {

View File

@ -19,8 +19,8 @@
package org.jclouds.http.handlers;
import static org.jclouds.http.HttpUtils.changePathTo;
import static org.jclouds.http.HttpUtils.changeSchemeHostAndPortTo;
import static java.util.Collections.singletonList;
import static javax.ws.rs.core.HttpHeaders.HOST;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import java.net.URI;
@ -58,8 +58,7 @@ public class RedirectionRetryHandler implements HttpRetryHandler {
protected final Provider<UriBuilder> uriBuilderProvider;
@Inject
protected RedirectionRetryHandler(Provider<UriBuilder> uriBuilderProvider,
BackoffLimitedRetryHandler backoffHandler) {
protected RedirectionRetryHandler(Provider<UriBuilder> uriBuilderProvider, BackoffLimitedRetryHandler backoffHandler) {
this.backoffHandler = backoffHandler;
this.uriBuilderProvider = uriBuilderProvider;
}
@ -67,25 +66,36 @@ 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 {
return backoffHandler.shouldRetryRequest(command, response);
}
} else {
changeSchemeHostAndPortTo(command.getRequest(), redirectionUrl.getScheme(),
redirectionUrl.getHost(), redirectionUrl.getPort(), uriBuilderProvider.get());
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()));
}
if (redirectionUrl.getPort() != command.getRequest().getEndpoint().getPort())
builder.port(redirectionUrl.getPort());
if (redirectionUrl.getQuery() != null)
builder.replaceQuery(redirectionUrl.getQuery());
command.getRequest().setEndpoint(builder.build());
return true;
} else {
return false;
}
}
}
}

View File

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

View File

@ -38,8 +38,8 @@ import org.jclouds.json.internal.GsonWrapper;
import com.google.common.collect.Maps;
import com.google.common.primitives.Bytes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JcloudsCompactFormatter;
import com.google.gson.JcloudsGsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
@ -64,9 +64,9 @@ public class GsonModule extends AbstractModule {
@Provides
@Singleton
Gson provideGson(JsonBallAdapter jsonObjectAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
ByteArrayAdapter byteArrayAdapter, JsonAdapterBindings bindings) throws SecurityException,
NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
GsonBuilder builder = new GsonBuilder();
ByteArrayAdapter byteArrayAdapter, JsonAdapterBindings bindings) throws ClassNotFoundException, Exception {
JcloudsGsonBuilder builder = new JcloudsGsonBuilder();
builder.registerTypeAdapter(JsonBall.class, jsonObjectAdapter);
builder.registerTypeAdapter(Date.class, adapter);
builder.registerTypeAdapter(new TypeToken<List<Byte>>() {
@ -105,7 +105,7 @@ public class GsonModule extends AbstractModule {
@Override
public List<Byte> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
return Bytes.asList(CryptoStreams.hex(json.getAsString()));
}
@ -121,7 +121,7 @@ public class GsonModule extends AbstractModule {
@Override
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
return CryptoStreams.hex(json.getAsString());
}
@ -145,7 +145,7 @@ public class GsonModule extends AbstractModule {
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
try {
return dateService.iso8601DateParse(toParse);
@ -170,7 +170,7 @@ public class GsonModule extends AbstractModule {
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
Date toReturn = dateService.cDateParse(toParse);
return toReturn;
@ -191,7 +191,7 @@ public class GsonModule extends AbstractModule {
}
public JsonBall deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
return new JsonBall(json.toString());
}
@ -205,7 +205,7 @@ public class GsonModule extends AbstractModule {
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
long toParse = json.getAsJsonPrimitive().getAsLong();
if (toParse == -1)
return null;

View File

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

View File

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

View File

@ -1,123 +1,126 @@
#
#
# Copyright (C) 2009 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.
# ====================================================================
#
azurequeue.contextbuilder=org.jclouds.azure.storage.AzureStorageContextBuilder
azurequeue.sync=org.jclouds.azure.storage.queue.AzureQueueClient
azurequeue.async=org.jclouds.azure.storage.queue.AzureQueueAsyncClient
azurequeue.propertiesbuilder=org.jclouds.azure.storage.AzureStoragePropertiesBuilder
azurequeue.endpoint=https://{identity}.queue.core.windows.net
azureblob.contextbuilder=org.jclouds.azure.storage.blob.AzureBlobContextBuilder
azureblob.propertiesbuilder=org.jclouds.azure.storage.AzureStoragePropertiesBuilder
azureblob.endpoint=https://{identity}.blob.core.windows.net
pcs.contextbuilder=org.jclouds.mezeo.pcs2.PCSContextBuilder
pcs.apiVersion=unknown
sdn.contextbuilder=org.jclouds.nirvanix.sdn.SDNContextBuilder
sdn.propertiesbuilder=org.jclouds.nirvanix.sdn.SDNPropertiesBuilder
sqs.contextbuilder=org.jclouds.aws.sqs.SQSContextBuilder
sqs.propertiesbuilder=org.jclouds.aws.sqs.SQSPropertiesBuilder
elb.contextbuilder=org.jclouds.aws.elb.ELBContextBuilder
elb.propertiesbuilder=org.jclouds.aws.elb.ELBPropertiesBuilder
cloudwatch.contextbuilder=org.jclouds.aws.cloudwatch.CloudWatchContextBuilder
cloudwatch.propertiesbuilder=org.jclouds.aws.cloudwatch.CloudWatchPropertiesBuilder
s3.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder
s3.propertiesbuilder=org.jclouds.aws.s3.S3PropertiesBuilder
ec2.contextbuilder=org.jclouds.aws.ec2.EC2ContextBuilder
ec2.propertiesbuilder=org.jclouds.aws.ec2.EC2PropertiesBuilder
rimuhosting.contextbuilder=org.jclouds.rimuhosting.miro.RimuHostingContextBuilder
rimuhosting.propertiesbuilder=org.jclouds.rimuhosting.miro.RimuHostingPropertiesBuilder
slicehost.contextbuilder=org.jclouds.slicehost.SlicehostContextBuilder
slicehost.propertiesbuilder=org.jclouds.slicehost.SlicehostPropertiesBuilder
trmk-vcloudexpress.contextbuilder=org.jclouds.vcloud.terremark.TerremarkVCloudExpressContextBuilder
trmk-vcloudexpress.propertiesbuilder=org.jclouds.vcloud.terremark.TerremarkVCloudExpressPropertiesBuilder
trmk-ecloud.contextbuilder=org.jclouds.vcloud.terremark.TerremarkECloudContextBuilder
trmk-ecloud.propertiesbuilder=org.jclouds.vcloud.terremark.TerremarkECloudPropertiesBuilder
chef.contextbuilder=org.jclouds.chef.ChefContextBuilder
chef.propertiesbuilder=org.jclouds.chef.ChefPropertiesBuilder
transientchef.contextbuilder=org.jclouds.chef.test.TransientChefContextBuilder
transientchef.propertiesbuilder=org.jclouds.chef.ChefPropertiesBuilder
opscodeplatform.contextbuilder=org.jclouds.opscodeplatform.OpscodePlatformContextBuilder
opscodeplatform.propertiesbuilder=org.jclouds.opscodeplatform.OpscodePlatformPropertiesBuilder
vcloud.contextbuilder=org.jclouds.vcloud.VCloudContextBuilder
vcloud.propertiesbuilder=org.jclouds.vcloud.VCloudPropertiesBuilder
vcloudexpress.contextbuilder=org.jclouds.vcloud.VCloudExpressContextBuilder
vcloudexpress.propertiesbuilder=org.jclouds.vcloud.VCloudExpressPropertiesBuilder
eucalyptus.contextbuilder=org.jclouds.aws.ec2.EC2ContextBuilder
eucalyptus.propertiesbuilder=org.jclouds.aws.ec2.EucalyptusPropertiesBuilder
nova.contextbuilder=org.jclouds.aws.ec2.EC2ContextBuilder
nova.propertiesbuilder=org.jclouds.aws.ec2.NovaPropertiesBuilder
cloudservers.contextbuilder=org.jclouds.rackspace.cloudservers.CloudServersContextBuilder
cloudservers.propertiesbuilder=org.jclouds.rackspace.RackspacePropertiesBuilder
bluelock-vcdirector.contextbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudDirectorContextBuilder
bluelock-vcdirector.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudDirectorPropertiesBuilder
gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder
gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder
ibmdev.propertiesbuilder=org.jclouds.ibmdev.IBMDeveloperCloudPropertiesBuilder
ibmdev.contextbuilder=org.jclouds.ibmdev.IBMDeveloperCloudContextBuilder
stub.contextbuilder=org.jclouds.compute.stub.StubComputeServiceContextBuilder
# example of where to change your endpoint
# bluelock.endpoint=https://express3.bluelock.com/api
atmosonline.contextbuilder=org.jclouds.atmosonline.saas.AtmosStorageContextBuilder
atmosonline.endpoint=https://accesspoint.atmosonline.com
atmosonline.apiversion=1.3.0
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
cloudfiles.contextbuilder=org.jclouds.rackspace.cloudfiles.CloudFilesContextBuilder
cloudfiles.propertiesbuilder=org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder
walrus.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder
walrus.propertiesbuilder=org.jclouds.aws.s3.WalrusPropertiesBuilder
googlestorage.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder
googlestorage.propertiesbuilder=org.jclouds.aws.s3.GoogleStoragePropertiesBuilder
transient.contextbuilder=org.jclouds.blobstore.TransientBlobStoreContextBuilder
transient.propertiesbuilder=org.jclouds.blobstore.TransientBlobStorePropertiesBuilder
filesystem.contextbuilder=org.jclouds.filesystem.FilesystemBlobStoreContextBuilder
filesystem.propertiesbuilder=org.jclouds.filesystem.FilesystemBlobStorePropertiesBuilder
#
#
# Copyright (C) 2009 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.
# ====================================================================
#
azurequeue.contextbuilder=org.jclouds.azure.storage.AzureStorageContextBuilder
azurequeue.sync=org.jclouds.azure.storage.queue.AzureQueueClient
azurequeue.async=org.jclouds.azure.storage.queue.AzureQueueAsyncClient
azurequeue.propertiesbuilder=org.jclouds.azure.storage.AzureStoragePropertiesBuilder
azurequeue.endpoint=https://{identity}.queue.core.windows.net
azureblob.contextbuilder=org.jclouds.azure.storage.blob.AzureBlobContextBuilder
azureblob.propertiesbuilder=org.jclouds.azure.storage.AzureStoragePropertiesBuilder
azureblob.endpoint=https://{identity}.blob.core.windows.net
pcs.contextbuilder=org.jclouds.mezeo.pcs2.PCSContextBuilder
pcs.apiVersion=unknown
sdn.contextbuilder=org.jclouds.nirvanix.sdn.SDNContextBuilder
sdn.propertiesbuilder=org.jclouds.nirvanix.sdn.SDNPropertiesBuilder
sqs.contextbuilder=org.jclouds.aws.sqs.SQSContextBuilder
sqs.propertiesbuilder=org.jclouds.aws.sqs.SQSPropertiesBuilder
elb.contextbuilder=org.jclouds.aws.elb.ELBContextBuilder
elb.propertiesbuilder=org.jclouds.aws.elb.ELBPropertiesBuilder
cloudwatch.contextbuilder=org.jclouds.aws.cloudwatch.CloudWatchContextBuilder
cloudwatch.propertiesbuilder=org.jclouds.aws.cloudwatch.CloudWatchPropertiesBuilder
s3.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder
s3.propertiesbuilder=org.jclouds.aws.s3.S3PropertiesBuilder
ec2.contextbuilder=org.jclouds.aws.ec2.EC2ContextBuilder
ec2.propertiesbuilder=org.jclouds.aws.ec2.EC2PropertiesBuilder
rimuhosting.contextbuilder=org.jclouds.rimuhosting.miro.RimuHostingContextBuilder
rimuhosting.propertiesbuilder=org.jclouds.rimuhosting.miro.RimuHostingPropertiesBuilder
slicehost.contextbuilder=org.jclouds.slicehost.SlicehostContextBuilder
slicehost.propertiesbuilder=org.jclouds.slicehost.SlicehostPropertiesBuilder
trmk-vcloudexpress.contextbuilder=org.jclouds.vcloud.terremark.TerremarkVCloudExpressContextBuilder
trmk-vcloudexpress.propertiesbuilder=org.jclouds.vcloud.terremark.TerremarkVCloudExpressPropertiesBuilder
trmk-ecloud.contextbuilder=org.jclouds.vcloud.terremark.TerremarkECloudContextBuilder
trmk-ecloud.propertiesbuilder=org.jclouds.vcloud.terremark.TerremarkECloudPropertiesBuilder
chef.contextbuilder=org.jclouds.chef.ChefContextBuilder
chef.propertiesbuilder=org.jclouds.chef.ChefPropertiesBuilder
transientchef.contextbuilder=org.jclouds.chef.test.TransientChefContextBuilder
transientchef.propertiesbuilder=org.jclouds.chef.ChefPropertiesBuilder
opscodeplatform.contextbuilder=org.jclouds.opscodeplatform.OpscodePlatformContextBuilder
opscodeplatform.propertiesbuilder=org.jclouds.opscodeplatform.OpscodePlatformPropertiesBuilder
vcloud.contextbuilder=org.jclouds.vcloud.VCloudContextBuilder
vcloud.propertiesbuilder=org.jclouds.vcloud.VCloudPropertiesBuilder
vcloudexpress.contextbuilder=org.jclouds.vcloud.VCloudExpressContextBuilder
vcloudexpress.propertiesbuilder=org.jclouds.vcloud.VCloudExpressPropertiesBuilder
eucalyptus.contextbuilder=org.jclouds.aws.ec2.EC2ContextBuilder
eucalyptus.propertiesbuilder=org.jclouds.aws.ec2.EucalyptusPropertiesBuilder
nova.contextbuilder=org.jclouds.aws.ec2.EC2ContextBuilder
nova.propertiesbuilder=org.jclouds.aws.ec2.NovaPropertiesBuilder
cloudservers.contextbuilder=org.jclouds.rackspace.cloudservers.CloudServersContextBuilder
cloudservers.propertiesbuilder=org.jclouds.rackspace.RackspacePropertiesBuilder
bluelock-vcdirector.contextbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudDirectorContextBuilder
bluelock-vcdirector.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudDirectorPropertiesBuilder
gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder
gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder
ibmdev.propertiesbuilder=org.jclouds.ibmdev.IBMDeveloperCloudPropertiesBuilder
ibmdev.contextbuilder=org.jclouds.ibmdev.IBMDeveloperCloudContextBuilder
stub.contextbuilder=org.jclouds.compute.stub.StubComputeServiceContextBuilder
# example of where to change your endpoint
# bluelock.endpoint=https://express3.bluelock.com/api
atmosonline.contextbuilder=org.jclouds.atmosonline.saas.AtmosStorageContextBuilder
atmosonline.endpoint=https://accesspoint.atmosonline.com
atmosonline.apiversion=1.3.0
synaptic.contextbuilder=org.jclouds.atmosonline.saas.AtmosStorageContextBuilder
synaptic.endpoint=https://storage.synaptic.att.com
synaptic.apiversion=1.3.0
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
walrus.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder
walrus.propertiesbuilder=org.jclouds.aws.s3.WalrusPropertiesBuilder
googlestorage.contextbuilder=org.jclouds.aws.s3.S3ContextBuilder
googlestorage.propertiesbuilder=org.jclouds.aws.s3.GoogleStoragePropertiesBuilder
transient.contextbuilder=org.jclouds.blobstore.TransientBlobStoreContextBuilder
transient.propertiesbuilder=org.jclouds.blobstore.TransientBlobStorePropertiesBuilder
filesystem.contextbuilder=org.jclouds.filesystem.FilesystemBlobStoreContextBuilder
filesystem.propertiesbuilder=org.jclouds.filesystem.FilesystemBlobStorePropertiesBuilder

View File

@ -0,0 +1,141 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.http.functions;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import org.xml.sax.Locator;
import org.xml.sax.SAXParseException;
public class ParseSaxTest extends BaseHandlerTest {
public static class TestHandler extends ParseSax.HandlerWithResult<String> {
@Override
public String getResult() {
return "";
}
}
ParseSax<String> createParser() {
return factory.create(injector.getInstance(TestHandler.class));
}
@Test
public void testAddDetailsAndPropagateOkWhenRequestWithNoDataAndRuntimeExceptionThrowsOriginalException()
throws ExecutionException, InterruptedException, TimeoutException, IOException {
ParseSax<String> parser = createParser();
Exception input = new RuntimeException("foo");
try {
parser.addDetailsAndPropagate(null, input);
} catch (RuntimeException e) {
assertEquals(e, input);
}
}
@Test
public void testAddDetailsAndPropagateOkWhenRequestWithNoDataAndExceptionPropagates() throws ExecutionException,
InterruptedException, TimeoutException, IOException {
ParseSax<String> parser = createParser();
Exception input = new Exception("foo");
try {
parser.addDetailsAndPropagate(null, input);
} catch (RuntimeException e) {
assertEquals(e.getMessage(), "java.lang.Exception: foo");
assertEquals(e.getCause(), input);
}
}
@Test
public void testAddDetailsAndPropagateOkWhenRequestIsNotNullAndResponseIsNull() throws ExecutionException,
InterruptedException, TimeoutException, IOException {
ParseSax<String> parser = createParser();
HttpRequest request = new HttpRequest("GET", URI.create("http://foohost"));
Exception input = new Exception("foo");
try {
parser.setContext(request);
parser.addDetailsAndPropagate(null, input);
} catch (RuntimeException e) {
assertEquals(e.getMessage(), "request: GET http://foohost HTTP/1.1; cause: java.lang.Exception: foo");
assertEquals(e.getCause(), input);
}
}
@Test
public void testAddDetailsAndPropagateOkWithValidRequestResponse() throws ExecutionException, InterruptedException,
TimeoutException, IOException {
ParseSax<String> parser = createParser();
HttpRequest request = new HttpRequest("GET", URI.create("http://foohost"));
HttpResponse response = new HttpResponse(304, "Not Modified", null);
Exception input = new Exception("foo");
try {
parser.setContext(request);
parser.addDetailsAndPropagate(response, input);
} catch (RuntimeException e) {
assertEquals(e.getMessage(), "request: GET http://foohost HTTP/1.1; response: HTTP/1.1 304 Not Modified; cause: java.lang.Exception: foo");
assertEquals(e.getCause(), input);
}
}
@Test
public void testAddDetailsAndPropagateOkWithValidRequestResponseWithSAXParseException() throws ExecutionException,
InterruptedException, TimeoutException, IOException {
ParseSax<String> parser = createParser();
HttpRequest request = new HttpRequest("GET", URI.create("http://foohost"));
HttpResponse response = new HttpResponse(304, "Not Modified", null);
Locator locator = createMock(Locator.class);
expect(locator.getColumnNumber()).andReturn(1);
expect(locator.getLineNumber()).andReturn(1);
expect(locator.getPublicId()).andReturn("publicId");
expect(locator.getSystemId()).andReturn("systemId");
replay(locator);
Exception input = new SAXParseException("foo", locator);
verify(locator);
try {
parser.setContext(request);
parser.addDetailsAndPropagate(response, input);
} catch (RuntimeException e) {
assertEquals(e.getMessage(),
"request: GET http://foohost HTTP/1.1; response: HTTP/1.1 304 Not Modified; error at 1:1 in document systemId; cause: org.xml.sax.SAXParseException: foo");
assertEquals(e.getCause(), input);
}
}
}

View File

@ -0,0 +1,171 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.http.handlers;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.BaseRestClientTest.MockModule;
import org.jclouds.rest.config.RestModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.inject.Guice;
/**
* Tests behavior of {@code RedirectionRetryHandler}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "http.RedirectionRetryHandlerTest")
public class RedirectionRetryHandlerTest {
@Test
public void test302DoesNotRetry() {
HttpCommand command = createMock(HttpCommand.class);
HttpResponse response = new HttpResponse(302, "HTTP/1.1 302 Found", null);
expect(command.incrementRedirectCount()).andReturn(0);
replay(command);
RedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance(
RedirectionRetryHandler.class);
assert !retry.shouldRetryRequest(command, response);
verify(command);
}
@Test
public void test302DoesNotRetryAfterLimit() {
HttpCommand command = createMock(HttpCommand.class);
HttpResponse response = new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(
HttpHeaders.LOCATION, "/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645"));
expect(command.incrementRedirectCount()).andReturn(5);
replay(command);
RedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance(
RedirectionRetryHandler.class);
assert !retry.shouldRetryRequest(command, response);
verify(command);
}
@Test
public void test302WithPathOnlyHeader() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645")),
new HttpRequest(
"GET",
URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645")));
}
@Test
public void test302ToHttps() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("http://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),//
new HttpRequest("GET", URI
.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")));
}
@Test
public void test302ToDifferentPort() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("http://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"http://services.enterprisecloud.terremark.com:3030/api/v0.8b-ext2.5/org/1906645")),//
new HttpRequest("GET", URI
.create("http://services.enterprisecloud.terremark.com:3030/api/v0.8b-ext2.5/org/1906645")));
}
@Test
public void test302WithHeader() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")), new HttpRequest(
"GET", URI.create("https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")));
}
@Test
public void test302WithHeaderReplacesHostHeader() {
verifyRedirectRoutes(
new HttpRequest("GET",
URI.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645"),
ImmutableMultimap.of(HttpHeaders.HOST, "services.enterprisecloud.terremark.com")),
new HttpResponse(302, "HTTP/1.1 302 Found", null, ImmutableMultimap.of(HttpHeaders.LOCATION,
"https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645")),//
new HttpRequest("GET", URI
.create("https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645"),
ImmutableMultimap.of(HttpHeaders.HOST, "services1.enterprisecloud.terremark.com")));
}
protected void verifyRedirectRoutes(HttpRequest request, HttpResponse response, HttpRequest expected) {
HttpCommand command = createMock(HttpCommand.class);
expect(command.incrementRedirectCount()).andReturn(0);
expect(command.getRequest()).andReturn(request).atLeastOnce();
replay(command);
RedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance(
RedirectionRetryHandler.class);
assert retry.shouldRetryRequest(command, response);
assertEquals(command.getRequest(), expected);
verify(command);
}
}

View File

@ -0,0 +1,78 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.json;
import static org.testng.Assert.assertEquals;
import org.jclouds.json.config.GsonModule;
import org.testng.annotations.Test;
import com.google.gson.JsonParseException;
import com.google.inject.Guice;
@Test
public class JsonTest {
private Json json = Guice.createInjector(new GsonModule()).getInstance(Json.class);
private static class EnumInside {
private static enum Test {
FOO, BAR;
}
private Test enumValue;
}
public void testDeserializeEnum() {
assertEquals(json.fromJson("{enumValue : \"FOO\"}", EnumInside.class).enumValue, EnumInside.Test.FOO);
}
@Test(expectedExceptions = JsonParseException.class)
public void testDeserializeEnumWhenBadValue() {
assertEquals(json.fromJson("{enumValue : \"s\"}", EnumInside.class).enumValue, EnumInside.Test.FOO);
}
private static class EnumInsideWithParser {
private static enum Test {
FOO, BAR, UNRECOGNIZED;
@SuppressWarnings("unused")
public static Test fromValue(String state) {
try {
return valueOf(state);
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
private Test enumValue;
}
public void testDeserializeEnumWithParser() {
assertEquals(json.fromJson("{enumValue : \"FOO\"}", EnumInsideWithParser.class).enumValue,
EnumInsideWithParser.Test.FOO);
}
public void testDeserializeEnumWithParserAndBadValue() {
assertEquals(json.fromJson("{enumValue : \"sd\"}", EnumInsideWithParser.class).enumValue,
EnumInsideWithParser.Test.UNRECOGNIZED);
}
}

View File

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

View File

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

View File

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

View File

@ -1,202 +1,202 @@
/**
*
* 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.demo.tweetstore.config;
import static com.google.appengine.api.labs.taskqueue.TaskOptions.Builder.url;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextFactory;
import org.jclouds.demo.tweetstore.controller.AddTweetsController;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses;
import org.jclouds.gae.config.GoogleAppEngineConfigurationModule;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ServletConfigAware;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleServletHandlerAdapter;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import com.google.appengine.api.labs.taskqueue.Queue;
import com.google.appengine.api.labs.taskqueue.QueueFactory;
import com.google.appengine.api.labs.taskqueue.TaskOptions.Method;
import com.google.appengine.repackaged.com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.io.Closeables;
import com.google.inject.Module;
/**
* Creates servlets (using resources from the {@link SpringAppConfig}) and mappings.
*
* @author Andrew Phillips
* @see SpringAppConfig
*/
@Configuration
public class SpringServletConfig extends LoggingConfig implements ServletConfigAware {
public static final String PROPERTY_BLOBSTORE_CONTEXTS = "blobstore.contexts";
private ServletConfig servletConfig;
private Map<String, BlobStoreContext> providerTypeToBlobStoreMap;
private Twitter twitterClient;
private String container;
@PostConstruct
public void initialize() throws IOException {
BlobStoreContextFactory blobStoreContextFactory = new BlobStoreContextFactory();
Properties props = loadJCloudsProperties();
logger.trace("About to initialize members.");
Module googleModule = new GoogleAppEngineConfigurationModule();
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"));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("properties for twitter not configured properly in " + props.toString(), e);
}
// common namespace for storing tweets
container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER);
// instantiate and store references to all blobstores by provider name
providerTypeToBlobStoreMap = Maps.newHashMap();
for (String hint : Splitter.on(',').split(
checkNotNull(props.getProperty(PROPERTY_BLOBSTORE_CONTEXTS), PROPERTY_BLOBSTORE_CONTEXTS))) {
providerTypeToBlobStoreMap.put(hint, blobStoreContextFactory.createContext(hint, modules, props));
}
// get a queue for submitting store tweet requests
Queue queue = QueueFactory.getQueue("twitter");
// submit a job to store tweets for each configured blobstore
for (String name : providerTypeToBlobStoreMap.keySet()) {
queue.add(url("/store/do").header("context", name).method(Method.GET));
}
logger.trace("Members initialized. Twitter: '%s', container: '%s', provider types: '%s'", twitterClient,
container, providerTypeToBlobStoreMap.keySet());
}
private Properties loadJCloudsProperties() {
logger.trace("About to read properties from '%s'", "/WEB-INF/jclouds.properties");
Properties props = new Properties();
InputStream input = servletConfig.getServletContext().getResourceAsStream("/WEB-INF/jclouds.properties");
try {
props.load(input);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
Closeables.closeQuietly(input);
}
logger.trace("Properties successfully read.");
return props;
}
@Bean
public StoreTweetsController storeTweetsController() {
StoreTweetsController controller = new StoreTweetsController(providerTypeToBlobStoreMap, container, twitterClient);
injectServletConfig(controller);
return controller;
}
@Bean
public AddTweetsController addTweetsController() {
AddTweetsController controller = new AddTweetsController(providerTypeToBlobStoreMap,
serviceToStoredTweetStatuses());
injectServletConfig(controller);
return controller;
}
private void injectServletConfig(Servlet servlet) {
logger.trace("About to inject servlet config '%s'", servletConfig);
try {
servlet.init(checkNotNull(servletConfig));
} catch (ServletException exception) {
throw new BeanCreationException("Unable to instantiate " + servlet, exception);
}
logger.trace("Successfully injected servlet config.");
}
@Bean
ServiceToStoredTweetStatuses serviceToStoredTweetStatuses() {
return new ServiceToStoredTweetStatuses(providerTypeToBlobStoreMap, container);
}
@Bean
public HandlerMapping handlerMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
Map<String, Object> urlMap = Maps.newHashMapWithExpectedSize(2);
urlMap.put("/store/*", storeTweetsController());
urlMap.put("/tweets/*", addTweetsController());
mapping.setUrlMap(urlMap);
/*
* "/store" and "/tweets" are part of the servlet mapping and thus stripped by the mapping if
* using default settings.
*/
mapping.setAlwaysUseFullPath(true);
return mapping;
}
@Bean
public HandlerAdapter servletHandlerAdapter() {
return new SimpleServletHandlerAdapter();
}
@PreDestroy
public void destroy() throws Exception {
logger.trace("About to close contexts.");
for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) {
context.close();
}
logger.trace("Contexts closed.");
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.web.context.ServletConfigAware#setServletConfig(javax.servlet.ServletConfig
* )
*/
@Override
public void setServletConfig(ServletConfig servletConfig) {
this.servletConfig = servletConfig;
}
}
/**
*
* 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.demo.tweetstore.config;
import static com.google.appengine.api.labs.taskqueue.TaskOptions.Builder.url;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextFactory;
import org.jclouds.demo.tweetstore.controller.AddTweetsController;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses;
import org.jclouds.gae.config.GoogleAppEngineConfigurationModule;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ServletConfigAware;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleServletHandlerAdapter;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import com.google.appengine.api.labs.taskqueue.Queue;
import com.google.appengine.api.labs.taskqueue.QueueFactory;
import com.google.appengine.api.labs.taskqueue.TaskOptions.Method;
import com.google.appengine.repackaged.com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.io.Closeables;
import com.google.inject.Module;
/**
* Creates servlets (using resources from the {@link SpringAppConfig}) and mappings.
*
* @author Andrew Phillips
* @see SpringAppConfig
*/
@Configuration
public class SpringServletConfig extends LoggingConfig implements ServletConfigAware {
public static final String PROPERTY_BLOBSTORE_CONTEXTS = "blobstore.contexts";
private ServletConfig servletConfig;
private Map<String, BlobStoreContext> providerTypeToBlobStoreMap;
private Twitter twitterClient;
private String container;
@PostConstruct
public void initialize() throws IOException {
BlobStoreContextFactory blobStoreContextFactory = new BlobStoreContextFactory();
Properties props = loadJCloudsProperties();
logger.trace("About to initialize members.");
Module googleModule = new GoogleAppEngineConfigurationModule();
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("twitter.credential"));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("properties for twitter not configured properly in " + props.toString(), e);
}
// common namespace for storing tweets
container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER);
// instantiate and store references to all blobstores by provider name
providerTypeToBlobStoreMap = Maps.newHashMap();
for (String hint : Splitter.on(',').split(
checkNotNull(props.getProperty(PROPERTY_BLOBSTORE_CONTEXTS), PROPERTY_BLOBSTORE_CONTEXTS))) {
providerTypeToBlobStoreMap.put(hint, blobStoreContextFactory.createContext(hint, modules, props));
}
// get a queue for submitting store tweet requests
Queue queue = QueueFactory.getQueue("twitter");
// submit a job to store tweets for each configured blobstore
for (String name : providerTypeToBlobStoreMap.keySet()) {
queue.add(url("/store/do").header("context", name).method(Method.GET));
}
logger.trace("Members initialized. Twitter: '%s', container: '%s', provider types: '%s'", twitterClient,
container, providerTypeToBlobStoreMap.keySet());
}
private Properties loadJCloudsProperties() {
logger.trace("About to read properties from '%s'", "/WEB-INF/jclouds.properties");
Properties props = new Properties();
InputStream input = servletConfig.getServletContext().getResourceAsStream("/WEB-INF/jclouds.properties");
try {
props.load(input);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
Closeables.closeQuietly(input);
}
logger.trace("Properties successfully read.");
return props;
}
@Bean
public StoreTweetsController storeTweetsController() {
StoreTweetsController controller = new StoreTweetsController(providerTypeToBlobStoreMap, container, twitterClient);
injectServletConfig(controller);
return controller;
}
@Bean
public AddTweetsController addTweetsController() {
AddTweetsController controller = new AddTweetsController(providerTypeToBlobStoreMap,
serviceToStoredTweetStatuses());
injectServletConfig(controller);
return controller;
}
private void injectServletConfig(Servlet servlet) {
logger.trace("About to inject servlet config '%s'", servletConfig);
try {
servlet.init(checkNotNull(servletConfig));
} catch (ServletException exception) {
throw new BeanCreationException("Unable to instantiate " + servlet, exception);
}
logger.trace("Successfully injected servlet config.");
}
@Bean
ServiceToStoredTweetStatuses serviceToStoredTweetStatuses() {
return new ServiceToStoredTweetStatuses(providerTypeToBlobStoreMap, container);
}
@Bean
public HandlerMapping handlerMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
Map<String, Object> urlMap = Maps.newHashMapWithExpectedSize(2);
urlMap.put("/store/*", storeTweetsController());
urlMap.put("/tweets/*", addTweetsController());
mapping.setUrlMap(urlMap);
/*
* "/store" and "/tweets" are part of the servlet mapping and thus stripped by the mapping if
* using default settings.
*/
mapping.setAlwaysUseFullPath(true);
return mapping;
}
@Bean
public HandlerAdapter servletHandlerAdapter() {
return new SimpleServletHandlerAdapter();
}
@PreDestroy
public void destroy() throws Exception {
logger.trace("About to close contexts.");
for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) {
context.close();
}
logger.trace("Contexts closed.");
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.web.context.ServletConfigAware#setServletConfig(javax.servlet.ServletConfig
* )
*/
@Override
public void setServletConfig(ServletConfig servletConfig) {
this.servletConfig = servletConfig;
}
}

View File

@ -27,9 +27,9 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
@ -70,16 +70,17 @@ public class TweetStoreLiveTest {
private String container;
private static final String blobs = System.getProperty("jclouds.tweetstore.blobstores",
"cloudfiles,googlestorage,s3,azureblob");
"cloudfiles,googlestorage,s3,azureblob");
private static final Iterable<String> blobstores = Splitter.on(',').split(blobs);
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();
@ -108,7 +109,7 @@ public class TweetStoreLiveTest {
for (BlobStoreContext context : contexts.values()) {
if (context.getBlobStore().containerExists(container)) {
System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext()
.getEndpoint());
.getEndpoint());
context.getBlobStore().deleteContainer(container);
deleted = true;
}
@ -119,7 +120,7 @@ public class TweetStoreLiveTest {
}
for (BlobStoreContext context : contexts.values()) {
System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext()
.getEndpoint());
.getEndpoint());
context.getBlobStore().createContainerInLocation(null, container);
}
if (deleted) {
@ -134,22 +135,23 @@ 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"));
}
}
@BeforeTest
@Parameters( { "warfile", "devappserver.address", "devappserver.port" })
@Parameters({ "warfile", "devappserver.address", "devappserver.port" })
public void startDevAppServer(final String warfile, final String address, final String port) throws Exception {
url = new URL(String.format("http://%s:%s", address, port));
server = new GoogleDevServer();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,72 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "gogrid.GoGridTemplateBuilderLiveTest")
public class GoGridTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public GoGridTemplateBuilderLiveTest() {
provider = "gogrid";
}
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return new Predicate<OsFamilyVersion64Bit>() {
@Override
public boolean apply(OsFamilyVersion64Bit input) {
return ((input.family == OsFamily.RHEL && !input.version.equals("5.4")) || //
(input.family == OsFamily.CENTOS && input.version.matches("5.[54]")) || //
(input.family == OsFamily.CENTOS && input.is64Bit && input.version.equals("5.4")) || //
(input.family == OsFamily.UBUNTU) || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008 SP2") || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008 R2"))));
}
};
}
@Test
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "5.3");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.CENTOS);
assertEquals(getCores(defaultTemplate.getHardware()), 0.5d);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -19,16 +19,19 @@
package org.jclouds.rackspace.cloudservers.compute.functions;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
@ -40,11 +43,20 @@ 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;
@ -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;
}
if (matcher.find()) {
try {
osFamily = OsFamily.fromValue(matcher.group(2).toLowerCase());
} catch (IllegalArgumentException e) {
logger.debug("<< didn't match os(%s)", matcher.group(2));
} 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 = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(3), osVersionMap);
}
osVersion = matcher.group(3);
}
OperatingSystem os = new OperatingSystem(osFamily, osName, osVersion, osArch, osDescription, is64Bit);
return os;
return new OperatingSystem(osFamily, osName, osVersion, osArch, osDescription, is64Bit);
}
}

View File

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

View File

@ -52,7 +52,7 @@ public class CloudServersComputeServiceLiveTest extends BaseComputeServiceLiveTe
public void testTemplateBuilder() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "9.10");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), "DFW1");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
@ -66,7 +66,7 @@ public class CloudServersComputeServiceLiveTest extends BaseComputeServiceLiveTe
public void testAssignability() throws Exception {
@SuppressWarnings("unused")
RestContext<CloudServersClient, CloudServersAsyncClient> tmContext = new ComputeServiceContextFactory()
.createContext(provider, identity, credential).getProviderSpecificContext();
.createContext(provider, identity, credential).getProviderSpecificContext();
}
@Override
@ -82,4 +82,21 @@ public class CloudServersComputeServiceLiveTest extends BaseComputeServiceLiveTe
super.testSuspendResume();
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
@Override
public void testGetNodesWithDetails() throws Exception {
super.testGetNodesWithDetails();
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
@Override
public void testListNodes() throws Exception {
super.testListNodes();
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
@Override
public void testDestroyNodes() {
super.testDestroyNodes();
}
}

View File

@ -0,0 +1,57 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.rackspace.cloudservers.compute;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.OsFamily;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "cloudservers.CloudServersTemplateBuilderLiveTest")
public class CloudServersTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public CloudServersTemplateBuilderLiveTest() {
provider = "cloudservers";
}
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return new Predicate<OsFamilyVersion64Bit>() {
@Override
public boolean apply(OsFamilyVersion64Bit input) {
return (input.family != OsFamily.WINDOWS && !input.is64Bit) || //
input.family == OsFamily.RHEL || //
(input.family == OsFamily.UBUNTU && input.version.equals("11.04")) || //
(input.family == OsFamily.CENTOS && input.version.matches("5.[23]")) || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008")) || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008 R2") && !input.is64Bit);
}
};
}
}

View File

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

View File

@ -1,129 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<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>
<artifactId>jclouds-rimuhosting</artifactId>
<name>jclouds RimuHosting core</name>
<description>jclouds components to access RimuHosting</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/rimuhosting</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/rimuhosting</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/rimuhosting</url>
</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>
<test.rimuhosting.apiversion>1.0</test.rimuhosting.apiversion>
<test.rimuhosting.identity>FIXME</test.rimuhosting.identity>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-jsch</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-compute</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.rimuhosting.endpoint</name>
<value>${test.rimuhosting.endpoint}</value>
</property>
<property>
<name>test.rimuhosting.apiversion</name>
<value>${test.rimuhosting.apiversion}</value>
</property>
<property>
<name>test.rimuhosting.identity</name>
<value>${test.rimuhosting.identity}</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>
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<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>
<artifactId>jclouds-rimuhosting</artifactId>
<name>jclouds RimuHosting core</name>
<description>jclouds components to access RimuHosting</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/rimuhosting</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/rimuhosting</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/rimuhosting</url>
</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://api.rimuhosting.com/r</test.rimuhosting.endpoint>
<test.rimuhosting.apiversion>1.0</test.rimuhosting.apiversion>
<test.rimuhosting.identity>FIXME</test.rimuhosting.identity>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-jsch</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-compute</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.rimuhosting.endpoint</name>
<value>${test.rimuhosting.endpoint}</value>
</property>
<property>
<name>test.rimuhosting.apiversion</name>
<value>${test.rimuhosting.apiversion}</value>
</property>
<property>
<name>test.rimuhosting.identity</name>
<value>${test.rimuhosting.identity}</value>
</property>
<property>
<name>jclouds.compute.blacklist-nodes</name>
<value>${jclouds.compute.blacklist-nodes}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,53 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.rimuhosting.miro.compute;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.OsFamily;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "rimuhosting.RimuHostingTemplateBuilderLiveTest")
public class RimuHostingTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public RimuHostingTemplateBuilderLiveTest() {
provider = "rimuhosting";
}
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return new Predicate<OsFamilyVersion64Bit>() {
@Override
public boolean apply(OsFamilyVersion64Bit input) {
return input.family != OsFamily.UBUNTU || //
Float.parseFloat(input.version) > 10.04 || //
(!(input.is64Bit) && Float.parseFloat(input.version) < 8.10);
}
};
}
}

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2010 Cloud Conscious, LLC <info@cloudconscious.com>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.html
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-elastichosts</artifactId>
<name>jclouds ElasticHosts core</name>
<description>jclouds components to access ElasticHosts</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/elastichosts</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/elastichosts</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/elastichosts</url>
</scm>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
<repository>
<id>jclouds-googlecode-deploy</id>
<url>http://jclouds.googlecode.com/svn/repo</url>
</repository>
<repository>
<id>jclouds-rimu-snapshots-nexus</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<!-- when instances are hung, open a ticket and add here -->
<jclouds.compute.blacklist-nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist-nodes>
<test.elastichosts.endpoint>https://api.cloudsigma.com</test.elastichosts.endpoint>
<test.elastichosts.apiversion>1.0</test.elastichosts.apiversion>
<test.elastichosts.identity>FIXME</test.elastichosts.identity>
<test.elastichosts.credential>FIXME</test.elastichosts.credential>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>test.elastichosts.endpoint</name>
<value>${test.elastichosts.endpoint}</value>
</property>
<property>
<name>test.elastichosts.apiversion</name>
<value>${test.elastichosts.apiversion}</value>
</property>
<property>
<name>test.elastichosts.identity</name>
<value>${test.elastichosts.identity}</value>
</property>
<property>
<name>test.elastichosts.credential</name>
<value>${test.elastichosts.credential}</value>
</property>
<property>
<name>jclouds.compute.blacklist-nodes</name>
<value>${jclouds.compute.blacklist-nodes}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,199 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.elastichosts;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.elastichosts.binders.BindCreateDriveRequestToPlainTextString;
import org.jclouds.elastichosts.binders.BindDriveDataToPlainTextString;
import org.jclouds.elastichosts.binders.BindReadDriveOptionsToPath;
import org.jclouds.elastichosts.domain.CreateDriveRequest;
import org.jclouds.elastichosts.domain.DriveData;
import org.jclouds.elastichosts.domain.DriveInfo;
import org.jclouds.elastichosts.domain.ImageConversionType;
import org.jclouds.elastichosts.functions.KeyValuesDelimitedByBlankLinesToDriveInfo;
import org.jclouds.elastichosts.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet;
import org.jclouds.elastichosts.functions.ReturnPayload;
import org.jclouds.elastichosts.functions.SplitNewlines;
import org.jclouds.elastichosts.options.ReadDriveOptions;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.io.Payload;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to ElasticHosts via their REST API.
* <p/>
*
* @see ElasticHostsClient
* @see <a href="TODO: insert URL of provider documentation" />
* @author Adrian Cole
*/
@RequestFilters(BasicAuthentication.class)
@Consumes(MediaType.TEXT_PLAIN)
public interface ElasticHostsAsyncClient {
/**
* @see ElasticHostsClient#listDrives()
*/
@GET
@Path("/drives/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listDrives();
/**
* @see ElasticHostsClient#listStandardDrives()
*/
@GET
@Path("/drives/standard/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listStandardDrives();
/**
* @see ElasticHostsClient#listStandardCds()
*/
@GET
@Path("/drives/standard/cd/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listStandardCds();
/**
* @see ElasticHostsClient#listStandardImages()
*/
@GET
@Path("/drives/standard/img/list")
@ResponseParser(SplitNewlines.class)
ListenableFuture<Set<String>> listStandardImages();
/**
* @see ElasticHostsClient#listDriveInfo()
*/
@GET
@Path("/drives/info")
@ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class)
ListenableFuture<Set<DriveInfo>> listDriveInfo();
/**
* @see ElasticHostsClient#getDriveInfo
*/
@GET
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/{uuid}/info")
ListenableFuture<DriveInfo> getDriveInfo(@PathParam("uuid") String uuid);
/**
* @see ElasticHostsClient#createDrive
*/
@POST
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/create")
ListenableFuture<DriveInfo> createDrive(
@BinderParam(BindCreateDriveRequestToPlainTextString.class) CreateDriveRequest createDrive);
/**
* @see ElasticHostsClient#setDriveData
*/
@POST
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class)
@Path("/drives/{uuid}/set")
ListenableFuture<DriveInfo> setDriveData(@PathParam("uuid") String uuid,
@BinderParam(BindDriveDataToPlainTextString.class) DriveData createDrive);
/**
* @see ElasticHostsClient#destroyDrive
*/
@POST
@Path("/drives/{uuid}/destroy")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> destroyDrive(@PathParam("uuid") String uuid);
/**
* @see ElasticHostsClient#imageDrive(String,String)
*/
@POST
@Path("/drives/{destination}/image/{source}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> imageDrive(@PathParam("source") String source, @PathParam("destination") String destination);
/**
* @see ElasticHostsClient#imageDrive(String,String,ImageConversionType)
*/
@POST
@Path("/drives/{destination}/image/{source}/{conversion}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> imageDrive(@PathParam("source") String source, @PathParam("destination") String destination,
@PathParam("conversion") ImageConversionType conversionType);
/**
* @see ElasticHostsClient#readDrive(String)
*/
@GET
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Path("/drives/{uuid}/read")
@ResponseParser(ReturnPayload.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Payload> readDrive(@PathParam("uuid") String uuid);
/**
* @see ElasticHostsClient#readDrive(String,ReadDriveOptions)
*/
@POST
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Path("/drives/{uuid}/read")
@ResponseParser(ReturnPayload.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Payload> readDrive(@PathParam("uuid") String uuid,
@BinderParam(BindReadDriveOptionsToPath.class) ReadDriveOptions options);
/**
* @see ElasticHostsClient#writeDrive(String, Payload)
*/
@POST
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Path("/drives/{uuid}/write")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> writeDrive(@PathParam("uuid") String uuid, Payload content);
/**
* @see ElasticHostsClient#writeDrive(String, Payload, long)
*/
@POST
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Path("/drives/{uuid}/write/{offset}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> writeDrive(@PathParam("uuid") String uuid, Payload content, @PathParam("offset") long offset);
}

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