mirror of https://github.com/apache/jclouds.git
Issue 27: got eucalyptus and walrus working, after refactoring error handling
This commit is contained in:
parent
f5f031685d
commit
41e3ec6709
|
@ -23,8 +23,8 @@ import static org.jclouds.util.Utils.propagateOrNull;
|
|||
import java.net.URI;
|
||||
|
||||
import org.jclouds.blobstore.KeyAlreadyExistsException;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -43,8 +43,10 @@ public class ReturnEndpointIfAlreadyExists implements Function<Exception, URI>,
|
|||
return URI.class.cast(propagateOrNull(from));
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ReturnEndpointIfAlreadyExists setContext(HttpRequest request) {
|
||||
this.endpoint = request == null ? null : request.getEndpoint();
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,8 @@ import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
|||
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
||||
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||
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 java.util.Properties;
|
||||
|
||||
|
@ -36,6 +38,8 @@ public class EC2PropertiesBuilder extends PropertiesBuilder {
|
|||
@Override
|
||||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||
properties.setProperty(PROPERTY_ENDPOINT, "https://ec2.us-east-1.amazonaws.com");
|
||||
properties.setProperty(PROPERTY_API_VERSION, EC2AsyncClient.VERSION);
|
||||
properties.setProperty(PROPERTY_ELB_ENDPOINT,
|
||||
|
|
|
@ -34,7 +34,7 @@ public class EucalyptusPropertiesBuilder extends EC2PropertiesBuilder {
|
|||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_ENDPOINT,
|
||||
"http://ecc.eucalyptus.com:8773/services/Eucalyptus");
|
||||
"http://173.205.188.130:8773/services/Eucalyptus");
|
||||
// TODO
|
||||
// properties.setProperty(PROPERTY_ELB_ENDPOINT,
|
||||
// "https://elasticloadbalancing.us-east-1.amazonaws.com");
|
||||
|
|
|
@ -29,12 +29,13 @@ import org.jclouds.aws.ec2.util.EC2Utils;
|
|||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class AttachmentHandler extends ParseSax.HandlerWithResult<Attachment> {
|
||||
public class AttachmentHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Attachment> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
@Resource
|
||||
|
@ -51,7 +52,7 @@ public class AttachmentHandler extends ParseSax.HandlerWithResult<Attachment> {
|
|||
private Date attachTime;
|
||||
|
||||
public Attachment getResult() {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
return new Attachment(region, volumeId, instanceId, device, attachmentStatus, attachTime);
|
||||
|
|
|
@ -34,8 +34,9 @@ import org.jclouds.aws.ec2.domain.RootDeviceType;
|
|||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
||||
import org.jclouds.http.functions.ParseSax.HandlerForGeneratedRequestWithResult;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -45,15 +46,14 @@ import com.google.common.collect.Sets;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
||||
public abstract class BaseReservationHandler<T> extends HandlerForGeneratedRequestWithResult<T> {
|
||||
|
||||
protected final DateService dateService;
|
||||
|
||||
protected final String defaultRegion;
|
||||
|
||||
@Inject
|
||||
public BaseReservationHandler(DateService dateService,
|
||||
@Region String defaultRegion) {
|
||||
public BaseReservationHandler(DateService dateService, @Region String defaultRegion) {
|
||||
this.dateService = dateService;
|
||||
this.defaultRegion = defaultRegion;
|
||||
}
|
||||
|
@ -90,8 +90,7 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
|||
protected boolean inProductCodes;
|
||||
protected boolean inGroups;
|
||||
private boolean inBlockDeviceMapping;
|
||||
private Map<String, RunningInstance.EbsBlockDevice> ebsBlockDevices = Maps
|
||||
.newHashMap();
|
||||
private Map<String, RunningInstance.EbsBlockDevice> ebsBlockDevices = Maps.newHashMap();
|
||||
|
||||
private String volumeId;
|
||||
private Attachment.Status attachmentStatus;
|
||||
|
@ -101,8 +100,7 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
|||
private String deviceName;
|
||||
private String rootDeviceName;
|
||||
|
||||
public void startElement(String uri, String name, String qName,
|
||||
Attributes attrs) {
|
||||
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
||||
if (qName.equals("instancesSet")) {
|
||||
inInstances = true;
|
||||
} else if (qName.equals("productCodesSet")) {
|
||||
|
@ -194,14 +192,11 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
|||
} else if (qName.equals("volumeId")) {
|
||||
volumeId = currentOrNull();
|
||||
} else if (qName.equals("status")) {
|
||||
attachmentStatus = Attachment.Status.fromValue(currentText.toString()
|
||||
.trim());
|
||||
attachmentStatus = Attachment.Status.fromValue(currentText.toString().trim());
|
||||
} else if (qName.equals("attachTime")) {
|
||||
attachTime = dateService.iso8601DateParse(currentText.toString()
|
||||
.trim());
|
||||
attachTime = dateService.iso8601DateParse(currentText.toString().trim());
|
||||
} else if (qName.equals("deleteOnTermination")) {
|
||||
deleteOnTermination = Boolean.parseBoolean(currentText.toString()
|
||||
.trim());
|
||||
deleteOnTermination = Boolean.parseBoolean(currentText.toString().trim());
|
||||
} else if (qName.equals("rootDeviceName")) {
|
||||
rootDeviceName = currentOrNull();
|
||||
} else if (qName.equals("item")) {
|
||||
|
@ -212,36 +207,34 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
|||
|
||||
protected void inItem() {
|
||||
if (inBlockDeviceMapping) {
|
||||
ebsBlockDevices.put(deviceName, new RunningInstance.EbsBlockDevice(
|
||||
volumeId, attachmentStatus, attachTime, deleteOnTermination));
|
||||
ebsBlockDevices.put(deviceName, new RunningInstance.EbsBlockDevice(volumeId,
|
||||
attachmentStatus, attachTime, deleteOnTermination));
|
||||
this.deviceName = null;
|
||||
this.volumeId = null;
|
||||
this.attachmentStatus = null;
|
||||
this.attachTime = null;
|
||||
this.deleteOnTermination = true;
|
||||
} else if (inInstances && !inProductCodes && !inBlockDeviceMapping) {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
|
||||
// Eucalyptus
|
||||
if (ipAddress == null && dnsName != null
|
||||
&& dnsName.matches(".*[0-9]$")) {
|
||||
if (ipAddress == null && dnsName != null && dnsName.matches(".*[0-9]$")) {
|
||||
ipAddress = dnsName;
|
||||
dnsName = null;
|
||||
}
|
||||
|
||||
if (privateIpAddress == null && privateDnsName != null
|
||||
&& privateDnsName.matches(".*[0-9]$")) {
|
||||
&& privateDnsName.matches(".*[0-9]$")) {
|
||||
privateIpAddress = privateDnsName;
|
||||
privateDnsName = null;
|
||||
}
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
instances.add(new RunningInstance(region, groupIds, amiLaunchIndex,
|
||||
dnsName, imageId, instanceId, instanceState, instanceType,
|
||||
ipAddress, kernelId, keyName, launchTime, monitoring,
|
||||
availabilityZone, platform, privateDnsName, privateIpAddress,
|
||||
productCodes, ramdiskId, reason, subnetId, vpcId,
|
||||
rootDeviceType, rootDeviceName, ebsBlockDevices));
|
||||
instances.add(new RunningInstance(region, groupIds, amiLaunchIndex, dnsName, imageId,
|
||||
instanceId, instanceState, instanceType, ipAddress, kernelId, keyName,
|
||||
launchTime, monitoring, availabilityZone, platform, privateDnsName,
|
||||
privateIpAddress, productCodes, ramdiskId, reason, subnetId, vpcId,
|
||||
rootDeviceType, rootDeviceName, ebsBlockDevices));
|
||||
this.amiLaunchIndex = null;
|
||||
this.dnsName = null;
|
||||
this.imageId = null;
|
||||
|
@ -273,11 +266,11 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
|||
}
|
||||
|
||||
protected Reservation newReservation() {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
Reservation info = new Reservation(region, groupIds, instances, ownerId,
|
||||
requesterId, reservationId);
|
||||
Reservation info = new Reservation(region, groupIds, instances, ownerId, requesterId,
|
||||
reservationId);
|
||||
this.groupIds = Sets.newTreeSet();
|
||||
this.instances = Sets.newTreeSet();
|
||||
this.ownerId = null;
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.jclouds.aws.ec2.domain.Attachment;
|
|||
import org.jclouds.aws.ec2.domain.Volume;
|
||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
@ -43,7 +44,8 @@ import com.google.common.collect.Sets;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class CreateVolumeResponseHandler extends ParseSax.HandlerWithResult<Volume> {
|
||||
public class CreateVolumeResponseHandler extends
|
||||
ParseSax.HandlerForGeneratedRequestWithResult<Volume> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
@Resource
|
||||
|
@ -154,11 +156,11 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerWithResult<Volu
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
public CreateVolumeResponseHandler setContext(HttpRequest request) {
|
||||
super.setContext(request);
|
||||
region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null) {
|
||||
String zone = EC2Utils.findAvailabilityZoneInArgsOrNull(request);
|
||||
String zone = EC2Utils.findAvailabilityZoneInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (zone != null) {
|
||||
region = checkNotNull(availabilityZoneToRegion.get(zone), String.format(
|
||||
"zone %s not in %s", zone, availabilityZoneToRegion));
|
||||
|
@ -166,5 +168,6 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerWithResult<Volu
|
|||
region = defaultRegion;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,9 @@ import javax.inject.Inject;
|
|||
import org.jclouds.aws.Region;
|
||||
import org.jclouds.aws.ec2.domain.PublicIpInstanceIdPair;
|
||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
||||
import org.jclouds.http.functions.ParseSax.HandlerForGeneratedRequestWithResult;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
|
@ -36,7 +37,7 @@ import com.google.common.collect.Sets;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class DescribeAddressesResponseHandler extends
|
||||
HandlerWithResult<Set<PublicIpInstanceIdPair>> {
|
||||
HandlerForGeneratedRequestWithResult<Set<PublicIpInstanceIdPair>> {
|
||||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
@ -59,7 +60,7 @@ public class DescribeAddressesResponseHandler extends
|
|||
} else if (qName.equals("instanceId")) {
|
||||
instanceId = currentOrNull();
|
||||
} else if (qName.equals("item")) {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
pairs.add(new PublicIpInstanceIdPair(region, ipAddress, instanceId));
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.jclouds.aws.ec2.domain.Image.ImageType;
|
|||
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -48,7 +49,8 @@ import com.google.common.collect.Sets;
|
|||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImages.html"
|
||||
* />
|
||||
*/
|
||||
public class DescribeImagesResponseHandler extends ParseSax.HandlerWithResult<Set<Image>> {
|
||||
public class DescribeImagesResponseHandler extends
|
||||
ParseSax.HandlerForGeneratedRequestWithResult<Set<Image>> {
|
||||
|
||||
@Inject
|
||||
public DescribeImagesResponseHandler(@Region String defaultRegion) {
|
||||
|
@ -151,7 +153,7 @@ public class DescribeImagesResponseHandler extends ParseSax.HandlerWithResult<Se
|
|||
this.deleteOnTermination = true;
|
||||
} else if (!inProductCodes) {
|
||||
try {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
contents.add(new Image(region, architecture, this.name, description, imageId,
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.jclouds.aws.Region;
|
|||
import org.jclouds.aws.ec2.domain.KeyPair;
|
||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
|
@ -36,7 +37,8 @@ import com.google.common.collect.Sets;
|
|||
* />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class DescribeKeyPairsResponseHandler extends ParseSax.HandlerWithResult<Set<KeyPair>> {
|
||||
public class DescribeKeyPairsResponseHandler extends
|
||||
ParseSax.HandlerForGeneratedRequestWithResult<Set<KeyPair>> {
|
||||
@Inject
|
||||
@Region
|
||||
String defaultRegion;
|
||||
|
@ -55,7 +57,7 @@ public class DescribeKeyPairsResponseHandler extends ParseSax.HandlerWithResult<
|
|||
if (qName.equals("keyFingerprint")) {
|
||||
this.keyFingerprint = currentText.toString().trim();
|
||||
} else if (qName.equals("item")) {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
keyPairs.add(new KeyPair(region, keyName, keyFingerprint, null));
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.jclouds.aws.ec2.domain.SecurityGroup;
|
|||
import org.jclouds.aws.ec2.domain.UserIdGroupPair;
|
||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
@ -41,7 +42,7 @@ import com.google.common.collect.Sets;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class DescribeSecurityGroupsResponseHandler extends
|
||||
ParseSax.HandlerWithResult<SortedSet<SecurityGroup>> {
|
||||
ParseSax.HandlerForGeneratedRequestWithResult<SortedSet<SecurityGroup>> {
|
||||
@Inject
|
||||
@Region
|
||||
String defaultRegion;
|
||||
|
@ -117,7 +118,7 @@ public class DescribeSecurityGroupsResponseHandler extends
|
|||
this.userId = null;
|
||||
this.userIdGroupName = null;
|
||||
} else if (!inIpPermissions && !inIpRanges && !inGroups) {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
securtyGroups.add(new SecurityGroup(region, groupName, ownerId, groupDescription,
|
||||
|
|
|
@ -23,8 +23,8 @@ import java.util.Set;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Snapshot;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
|
@ -66,8 +66,9 @@ public class DescribeSnapshotsResponseHandler extends ParseSax.HandlerWithResult
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
public DescribeSnapshotsResponseHandler setContext(HttpRequest request) {
|
||||
snapshotHandler.setContext(request);
|
||||
super.setContext(request);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ import java.util.Set;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Volume;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
|
@ -73,8 +73,9 @@ public class DescribeVolumesResponseHandler extends ParseSax.HandlerWithResult<S
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
public DescribeVolumesResponseHandler setContext(HttpRequest request) {
|
||||
volumeHandler.setContext(request);
|
||||
super.setContext(request);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@ import org.jclouds.aws.Region;
|
|||
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||
import org.jclouds.aws.ec2.domain.InstanceStateChange;
|
||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
||||
import org.jclouds.http.functions.ParseSax.HandlerForGeneratedRequestWithResult;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
@ -46,7 +47,8 @@ import com.google.common.collect.Sets;
|
|||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-ItemType-StopInstancesResponseInfoType.html"
|
||||
* />
|
||||
*/
|
||||
public class InstanceStateChangeHandler extends HandlerWithResult<SortedSet<InstanceStateChange>> {
|
||||
public class InstanceStateChangeHandler extends
|
||||
HandlerForGeneratedRequestWithResult<SortedSet<InstanceStateChange>> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
@Inject
|
||||
@Region
|
||||
|
@ -89,7 +91,7 @@ public class InstanceStateChangeHandler extends HandlerWithResult<SortedSet<Inst
|
|||
previousState = InstanceState.fromValue(currentOrNull());
|
||||
}
|
||||
} else if (qName.equals("item")) {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
instances.add(new InstanceStateChange(region, instanceId, shutdownState, previousState));
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.jclouds.aws.Region;
|
|||
import org.jclouds.aws.ec2.domain.KeyPair;
|
||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -32,7 +33,7 @@ import org.jclouds.http.functions.ParseSax;
|
|||
* />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class KeyPairResponseHandler extends ParseSax.HandlerWithResult<KeyPair> {
|
||||
public class KeyPairResponseHandler extends ParseSax.HandlerForGeneratedRequestWithResult<KeyPair> {
|
||||
@Inject
|
||||
@Region
|
||||
String defaultRegion;
|
||||
|
@ -42,7 +43,7 @@ public class KeyPairResponseHandler extends ParseSax.HandlerWithResult<KeyPair>
|
|||
private String keyName;
|
||||
|
||||
public KeyPair getResult() {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
return new KeyPair(region, keyName, keyFingerprint, keyMaterial);
|
||||
|
|
|
@ -28,12 +28,13 @@ import org.jclouds.aws.ec2.domain.Snapshot.Status;
|
|||
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class SnapshotHandler extends ParseSax.HandlerWithResult<Snapshot> {
|
||||
public class SnapshotHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Snapshot> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
protected final DateService dateService;
|
||||
|
@ -56,7 +57,7 @@ public class SnapshotHandler extends ParseSax.HandlerWithResult<Snapshot> {
|
|||
}
|
||||
|
||||
public Snapshot getResult() {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
Snapshot snapshot = new Snapshot(region, id, volumeId, volumeSize, status, startTime,
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.jclouds.aws.elb;
|
|||
|
||||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||
import static org.jclouds.Constants.PROPERTY_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.aws.reference.AWSConstants.PROPERTY_REGIONS;
|
||||
|
||||
import java.util.Properties;
|
||||
|
@ -38,6 +40,8 @@ public class ELBPropertiesBuilder extends PropertiesBuilder {
|
|||
@Override
|
||||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||
properties.setProperty(PROPERTY_API_VERSION, ELBAsyncClient.VERSION);
|
||||
properties.setProperty(PROPERTY_REGIONS, Joiner.on(',').join(Region.US_EAST_1,
|
||||
Region.US_WEST_1, Region.EU_WEST_1, Region.AP_SOUTHEAST_1));
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.jclouds.aws.elb.domain.LoadBalancer.AppCookieStickinessPolicy;
|
|||
import org.jclouds.aws.elb.domain.LoadBalancer.LBCookieStickinessPolicy;
|
||||
import org.jclouds.aws.elb.domain.LoadBalancer.LoadBalancerListener;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
@ -42,7 +43,7 @@ import com.google.common.collect.Sets;
|
|||
* @author Lili Nadar
|
||||
*/
|
||||
public class DescribeLoadBalancersResponseHandler extends
|
||||
ParseSax.HandlerWithResult<Set<LoadBalancer>> {
|
||||
ParseSax.HandlerForGeneratedRequestWithResult<Set<LoadBalancer>> {
|
||||
@Inject
|
||||
public DescribeLoadBalancersResponseHandler(@Region String defaultRegion) {
|
||||
this.defaultRegion = defaultRegion;
|
||||
|
@ -129,7 +130,7 @@ public class DescribeLoadBalancersResponseHandler extends
|
|||
} else if (!(inListenerDescriptions || inAppCookieStickinessPolicies || inInstances
|
||||
|| inLBCookieStickinessPolicies || inAvailabilityZones)) {
|
||||
try {
|
||||
String region = EC2Utils.findRegionInArgsOrNull(request);
|
||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||
if (region == null)
|
||||
region = defaultRegion;
|
||||
|
||||
|
@ -158,9 +159,10 @@ public class DescribeLoadBalancersResponseHandler extends
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
public DescribeLoadBalancersResponseHandler setContext(HttpRequest request) {
|
||||
listenerHandler.setContext(request);
|
||||
super.setContext(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
public class LoadBalancerListenerHandler extends
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.aws.handlers;
|
||||
|
||||
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
|
||||
|
@ -25,10 +27,8 @@ import org.jclouds.Constants;
|
|||
import org.jclouds.aws.domain.AWSError;
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.http.HttpCommand;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
@ -59,20 +59,16 @@ public class AWSClientErrorRetryHandler implements HttpRetryHandler {
|
|||
return false;
|
||||
if (response.getStatusCode() == 400 || response.getStatusCode() == 403
|
||||
|| response.getStatusCode() == 409) {
|
||||
byte[] content = HttpUtils.closeClientButKeepContentStream(response);
|
||||
command.incrementFailureCount();
|
||||
// Content can be null in the case of HEAD requests
|
||||
if (content != null) {
|
||||
try {
|
||||
AWSError error = utils.parseAWSErrorFromContent(command.getRequest(), response,
|
||||
new String(content));
|
||||
if ("RequestTimeout".equals(error.getCode())
|
||||
|| "OperationAborted".equals(error.getCode())
|
||||
|| "SignatureDoesNotMatch".equals(error.getCode())) {
|
||||
return true;
|
||||
}
|
||||
} catch (HttpException e) {
|
||||
logger.warn(e, "error parsing response: %s", new String(content));
|
||||
if (response.getPayload() != null) {
|
||||
closeClientButKeepContentStream(response);
|
||||
AWSError error = utils.parseAWSErrorFromContent(command.getRequest(), response);
|
||||
if (error != null
|
||||
&& ("RequestTimeout".equals(error.getCode())
|
||||
|| "OperationAborted".equals(error.getCode()) || "SignatureDoesNotMatch"
|
||||
.equals(error.getCode()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import javax.ws.rs.core.UriBuilder;
|
|||
import org.jclouds.aws.domain.AWSError;
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.http.HttpCommand;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||
import org.jclouds.http.handlers.RedirectionRetryHandler;
|
||||
|
@ -57,33 +56,26 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
|
|||
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
|
||||
if (response.getFirstHeaderOrNull(HttpHeaders.LOCATION) == null
|
||||
&& (response.getStatusCode() == 301 || response.getStatusCode() == 307)) {
|
||||
byte[] content = closeClientButKeepContentStream(response);
|
||||
if (command.getRequest().getMethod() == HttpMethod.HEAD) {
|
||||
changeToGETRequest(command.getRequest());
|
||||
return true;
|
||||
} else {
|
||||
command.incrementRedirectCount();
|
||||
try {
|
||||
AWSError error = utils.parseAWSErrorFromContent(command.getRequest(), response,
|
||||
new String(content));
|
||||
String host = error.getDetails().get("Endpoint");
|
||||
if (host != null) {
|
||||
if (host.equals(command.getRequest().getEndpoint().getHost())) {
|
||||
// must be an amazon error related to
|
||||
// http://developer.amazonwebservices.com/connect/thread.jspa?messageID=72287𑩟
|
||||
return backoffHandler.shouldRetryRequest(command, response);
|
||||
} else {
|
||||
changeSchemeHostAndPortTo(command.getRequest(), command.getRequest()
|
||||
.getEndpoint().getScheme(), host, command.getRequest().getEndpoint()
|
||||
.getPort(), uriBuilderProvider.get());
|
||||
}
|
||||
return true;
|
||||
closeClientButKeepContentStream(response);
|
||||
AWSError error = utils.parseAWSErrorFromContent(command.getRequest(), response);
|
||||
String host = error.getDetails().get("Endpoint");
|
||||
if (host != null) {
|
||||
if (host.equals(command.getRequest().getEndpoint().getHost())) {
|
||||
// must be an amazon error related to
|
||||
// http://developer.amazonwebservices.com/connect/thread.jspa?messageID=72287𑩟
|
||||
return backoffHandler.shouldRetryRequest(command, response);
|
||||
} else {
|
||||
return false;
|
||||
changeSchemeHostAndPortTo(command.getRequest(), command.getRequest()
|
||||
.getEndpoint().getScheme(), host, command.getRequest().getEndpoint()
|
||||
.getPort(), uriBuilderProvider.get());
|
||||
}
|
||||
} catch (HttpException e) {
|
||||
logger.error(e, "error on redirect for command %s; response %s; retrying...",
|
||||
command, response);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,6 @@ package org.jclouds.aws.handlers;
|
|||
|
||||
import static org.jclouds.http.HttpUtils.releasePayload;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -39,7 +37,6 @@ import org.jclouds.http.HttpResponseException;
|
|||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.jclouds.util.Utils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
|
@ -67,7 +64,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
|
|||
HttpRequest request = command.getRequest();
|
||||
Exception exception = new HttpResponseException(command, response);
|
||||
try {
|
||||
AWSError error = parseErrorFromContentOrNull(request, response);
|
||||
AWSError error = utils.parseAWSErrorFromContent(request, response);
|
||||
exception = error != null ? new AWSResponseException(command, response, error) : exception;
|
||||
switch (response.getStatusCode()) {
|
||||
case 400:
|
||||
|
@ -103,16 +100,4 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
|
|||
}
|
||||
}
|
||||
|
||||
AWSError parseErrorFromContentOrNull(HttpRequest request, HttpResponse response) {
|
||||
if (response.getPayload() != null) {
|
||||
try {
|
||||
String content = Utils.toStringAndClose(response.getPayload().getInput());
|
||||
if (content != null && content.indexOf('<') >= 0)
|
||||
return utils.parseAWSErrorFromContent(request, response, content);
|
||||
} catch (IOException e) {
|
||||
logger.warn(e, "exception reading error from response", response);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -26,5 +26,6 @@ package org.jclouds.aws.reference;
|
|||
public interface AWSConstants {
|
||||
public static final String PROPERTY_REGIONS = "jclouds.aws.regions";
|
||||
public static final String PROPERTY_DEFAULT_REGIONS = "jclouds.aws.default_regions";
|
||||
|
||||
public static final String PROPERTY_AUTH_TAG = "jclouds.aws.auth.tag";
|
||||
public static final String PROPERTY_HEADER_TAG = "jclouds.aws.header.tag";
|
||||
}
|
||||
|
|
34
core/src/main/java/org/jclouds/rest/annotations/HostPrefixParam.java → aws/core/src/main/java/org/jclouds/aws/s3/Bucket.java
Executable file → Normal file
34
core/src/main/java/org/jclouds/rest/annotations/HostPrefixParam.java → aws/core/src/main/java/org/jclouds/aws/s3/Bucket.java
Executable file → Normal file
|
@ -16,34 +16,18 @@
|
|||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rest.annotations;
|
||||
package org.jclouds.aws.s3;
|
||||
|
||||
import static java.lang.annotation.ElementType.PARAMETER;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Prefixes the hostname of the endpoint with the contents of a method parameter,
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* Annotates the parameter that this is a bucket.
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface HostPrefixParam {
|
||||
|
||||
/**
|
||||
* Defines the characters that will be inserted in-between the value of the annotated method
|
||||
* argument and the existing hostname.
|
||||
*
|
||||
* <p />
|
||||
* <ul>
|
||||
* <li>hostname was {@code mydomain.com}</li>
|
||||
* <li>method argument is {@code myhost}</li>
|
||||
* <li>if {@code joinOn} is not set, result is {@code myhostmydomain.com}</li>
|
||||
* <li>if {@code joinOn} is set to {@code .}, result is {@code myhost.mydomain.com}</li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
String value() default ".";
|
||||
}
|
||||
@Target(PARAMETER)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Bucket {
|
||||
}
|
|
@ -1,16 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
|
||||
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_DEFAULT_REGIONS;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_AUTH_TAG;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_HEADER_TAG;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_EXPR;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Builds properties used in Walrus Clients
|
||||
* Builds properties used in Google Storage
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
|
@ -18,9 +35,8 @@ public class GoogleStoragePropertiesBuilder extends S3PropertiesBuilder {
|
|||
@Override
|
||||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_S3_AUTH_TAG, "GOOG1");
|
||||
properties.setProperty(PROPERTY_S3_HEADER_TAG, "goog");
|
||||
properties.setProperty(PROPERTY_S3_SERVICE_EXPR, "\\.commondatastorage\\.googleapis\\.com");
|
||||
properties.setProperty(PROPERTY_AUTH_TAG, "GOOG1");
|
||||
properties.setProperty(PROPERTY_HEADER_TAG, "goog");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,11 @@ import javax.ws.rs.HEAD;
|
|||
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.aws.s3.binders.BindACLToXMLPayload;
|
||||
import org.jclouds.aws.s3.binders.BindAsHostPrefixIfConfigured;
|
||||
import org.jclouds.aws.s3.binders.BindBucketLoggingToXmlPayload;
|
||||
import org.jclouds.aws.s3.binders.BindNoBucketLoggingToXmlPayload;
|
||||
import org.jclouds.aws.s3.binders.BindPayerToXmlPayload;
|
||||
|
@ -73,7 +76,6 @@ import org.jclouds.http.options.GetOptions;
|
|||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.HostPrefixParam;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
import org.jclouds.rest.annotations.ParamValidators;
|
||||
import org.jclouds.rest.annotations.QueryParams;
|
||||
|
@ -98,7 +100,6 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
* @see S3Client
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html" />
|
||||
*/
|
||||
@VirtualHost
|
||||
@SkipEncoding('/')
|
||||
@RequestFilters(RequestAuthorizeSignature.class)
|
||||
@BlobScope(CONTAINER)
|
||||
|
@ -118,7 +119,7 @@ public interface S3AsyncClient {
|
|||
@ExceptionParser(ReturnNullOnKeyNotFound.class)
|
||||
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
|
||||
ListenableFuture<S3Object> getObject(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@PathParam("key") String key, GetOptions... options);
|
||||
|
||||
/**
|
||||
|
@ -129,7 +130,7 @@ public interface S3AsyncClient {
|
|||
@ExceptionParser(ReturnNullOnKeyNotFound.class)
|
||||
@ResponseParser(ParseObjectMetadataFromHeaders.class)
|
||||
ListenableFuture<ObjectMetadata> headObject(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
|
@ -139,7 +140,7 @@ public interface S3AsyncClient {
|
|||
@Path("{key}")
|
||||
@ExceptionParser(ReturnFalseOnKeyNotFound.class)
|
||||
ListenableFuture<Boolean> objectExists(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
|
@ -149,7 +150,7 @@ public interface S3AsyncClient {
|
|||
@Path("{key}")
|
||||
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
||||
ListenableFuture<Void> deleteObject(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
|
@ -159,7 +160,7 @@ public interface S3AsyncClient {
|
|||
@Path("{key}")
|
||||
@ResponseParser(ParseETagHeader.class)
|
||||
ListenableFuture<String> putObject(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectToPayload.class) S3Object object,
|
||||
PutObjectOptions... options);
|
||||
|
||||
|
@ -172,7 +173,7 @@ public interface S3AsyncClient {
|
|||
ListenableFuture<Boolean> putBucketInRegion(
|
||||
// TODO endpoint based on region
|
||||
@BinderParam(BindRegionToXmlPayload.class) @Nullable String region,
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
PutBucketOptions... options);
|
||||
|
||||
/**
|
||||
|
@ -182,7 +183,7 @@ public interface S3AsyncClient {
|
|||
@Path("/")
|
||||
@ExceptionParser(ReturnTrueOn404OrNotFoundFalseIfNotEmpty.class)
|
||||
ListenableFuture<Boolean> deleteBucketIfEmpty(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#bucketExists
|
||||
|
@ -192,7 +193,7 @@ public interface S3AsyncClient {
|
|||
@QueryParams(keys = "max-keys", values = "0")
|
||||
@ExceptionParser(ReturnFalseOnContainerNotFound.class)
|
||||
ListenableFuture<Boolean> bucketExists(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#getBucketLocation
|
||||
|
@ -202,7 +203,7 @@ public interface S3AsyncClient {
|
|||
@Path("/")
|
||||
@XMLResponseParser(LocationConstraintHandler.class)
|
||||
ListenableFuture<String> getBucketLocation(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#getBucketPayer
|
||||
|
@ -212,7 +213,7 @@ public interface S3AsyncClient {
|
|||
@Path("/")
|
||||
@XMLResponseParser(PayerHandler.class)
|
||||
ListenableFuture<Payer> getBucketPayer(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#setBucketPayer
|
||||
|
@ -221,7 +222,7 @@ public interface S3AsyncClient {
|
|||
@QueryParams(keys = "requestPayment")
|
||||
@Path("/")
|
||||
ListenableFuture<Void> setBucketPayer(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@BinderParam(BindPayerToXmlPayload.class) Payer payer);
|
||||
|
||||
/**
|
||||
|
@ -231,7 +232,7 @@ public interface S3AsyncClient {
|
|||
@Path("/")
|
||||
@XMLResponseParser(ListBucketHandler.class)
|
||||
ListenableFuture<ListBucketResponse> listBucket(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
ListBucketOptions... options);
|
||||
|
||||
/**
|
||||
|
@ -240,6 +241,7 @@ public interface S3AsyncClient {
|
|||
@GET
|
||||
@XMLResponseParser(ListAllMyBucketsHandler.class)
|
||||
@Path("/")
|
||||
@VirtualHost
|
||||
ListenableFuture<? extends SortedSet<BucketMetadata>> listOwnedBuckets();
|
||||
|
||||
/**
|
||||
|
@ -252,7 +254,7 @@ public interface S3AsyncClient {
|
|||
ListenableFuture<ObjectMetadata> copyObject(
|
||||
@PathParam("sourceBucket") String sourceBucket,
|
||||
@PathParam("sourceObject") String sourceObject,
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String destinationBucket,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String destinationBucket,
|
||||
@PathParam("destinationObject") String destinationObject, CopyObjectOptions... options);
|
||||
|
||||
/**
|
||||
|
@ -264,7 +266,7 @@ public interface S3AsyncClient {
|
|||
@ExceptionParser(ThrowContainerNotFoundOn404.class)
|
||||
@Path("/")
|
||||
ListenableFuture<AccessControlList> getBucketACL(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#putBucketACL
|
||||
|
@ -273,7 +275,7 @@ public interface S3AsyncClient {
|
|||
@Path("/")
|
||||
@QueryParams(keys = "acl")
|
||||
ListenableFuture<Boolean> putBucketACL(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
|
||||
|
||||
/**
|
||||
|
@ -285,7 +287,7 @@ public interface S3AsyncClient {
|
|||
@XMLResponseParser(AccessControlListHandler.class)
|
||||
@ExceptionParser(ThrowKeyNotFoundOn404.class)
|
||||
ListenableFuture<AccessControlList> getObjectACL(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
|
@ -295,7 +297,7 @@ public interface S3AsyncClient {
|
|||
@QueryParams(keys = "acl")
|
||||
@Path("{key}")
|
||||
ListenableFuture<Boolean> putObjectACL(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@PathParam("key") String key,
|
||||
@BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
|
||||
|
||||
|
@ -308,7 +310,7 @@ public interface S3AsyncClient {
|
|||
@ExceptionParser(ThrowContainerNotFoundOn404.class)
|
||||
@Path("/")
|
||||
ListenableFuture<BucketLogging> getBucketLogging(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#enableBucketLogging
|
||||
|
@ -317,7 +319,7 @@ public interface S3AsyncClient {
|
|||
@Path("/")
|
||||
@QueryParams(keys = "logging")
|
||||
ListenableFuture<Void> enableBucketLogging(
|
||||
@HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
||||
@BinderParam(BindBucketLoggingToXmlPayload.class) BucketLogging logging);
|
||||
|
||||
/**
|
||||
|
@ -326,7 +328,8 @@ public interface S3AsyncClient {
|
|||
@PUT
|
||||
@Path("/")
|
||||
@QueryParams(keys = "logging")
|
||||
@Produces(MediaType.TEXT_XML)
|
||||
ListenableFuture<Void> disableBucketLogging(
|
||||
@BinderParam(BindNoBucketLoggingToXmlPayload.class) @HostPrefixParam @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
@Bucket @BinderParam(BindNoBucketLoggingToXmlPayload.class) @ParamValidators( { BucketNameValidator.class }) String bucketName);
|
||||
|
||||
}
|
||||
|
|
|
@ -21,11 +21,12 @@ package org.jclouds.aws.s3;
|
|||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
||||
import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_DEFAULT_REGIONS;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_AUTH_TAG;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_HEADER_TAG;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_EXPR;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
|
||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.DIRECTORY_SUFFIX_FOLDER;
|
||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_DIRECTORY_SUFFIX;
|
||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||
|
@ -47,9 +48,10 @@ public class S3PropertiesBuilder extends PropertiesBuilder {
|
|||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_API_VERSION, S3AsyncClient.VERSION);
|
||||
properties.setProperty(PROPERTY_S3_AUTH_TAG, "AWS");
|
||||
properties.setProperty(PROPERTY_S3_HEADER_TAG, "amz");
|
||||
properties.setProperty(PROPERTY_S3_SERVICE_EXPR, "\\.s3[^.]*\\.amazonaws\\.com");
|
||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||
properties.setProperty(PROPERTY_S3_SERVICE_PATH, "/");
|
||||
properties.setProperty(PROPERTY_S3_VIRTUAL_HOST_BUCKETS, "true");
|
||||
properties.setProperty(PROPERTY_RELAX_HOSTNAME, "true");
|
||||
addEndpoints(properties);
|
||||
properties.setProperty(PROPERTY_BLOBSTORE_DIRECTORY_SUFFIX, DIRECTORY_SUFFIX_FOLDER);
|
||||
|
@ -90,7 +92,7 @@ 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_S3_HEADER_TAG)));
|
||||
properties.getProperty(PROPERTY_HEADER_TAG)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,29 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
|
||||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_DEFAULT_REGIONS;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
|
@ -16,9 +37,12 @@ public class WalrusPropertiesBuilder extends S3PropertiesBuilder {
|
|||
protected Properties addEndpoints(Properties properties) {
|
||||
properties.setProperty(PROPERTY_REGIONS, "Walrus");
|
||||
properties.setProperty(PROPERTY_DEFAULT_REGIONS, "Walrus");
|
||||
properties.setProperty(PROPERTY_API_VERSION, "Walrus-1.6");
|
||||
properties.setProperty(PROPERTY_ENDPOINT, "http://ecc.eucalyptus.com:8773/services/Walrus");
|
||||
properties.setProperty(PROPERTY_ENDPOINT + ".Walrus",
|
||||
"http://ecc.eucalyptus.com:8773/services/Walrus");
|
||||
properties.setProperty(PROPERTY_S3_SERVICE_PATH, "/services/Walrus");
|
||||
properties.setProperty(PROPERTY_S3_VIRTUAL_HOST_BUCKETS, "false");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3.binders;
|
||||
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
|
||||
import static org.jclouds.http.HttpUtils.urlEncode;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.aws.s3.S3AsyncClient;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.Binder;
|
||||
import org.jclouds.rest.annotations.SkipEncoding;
|
||||
import org.jclouds.rest.binders.BindAsHostPrefix;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BindAsHostPrefixIfConfigured implements Binder {
|
||||
|
||||
private final Provider<UriBuilder> uriBuilderProvider;
|
||||
private final BindAsHostPrefix bindAsHostPrefix;
|
||||
private final boolean isVhostStyle;
|
||||
private final String servicePath;
|
||||
|
||||
@Inject
|
||||
public BindAsHostPrefixIfConfigured(BindAsHostPrefix bindAsHostPrefix,
|
||||
@Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle,
|
||||
@Named(PROPERTY_S3_SERVICE_PATH) String servicePath,
|
||||
Provider<UriBuilder> uriBuilderProvider) {
|
||||
this.bindAsHostPrefix = bindAsHostPrefix;
|
||||
this.isVhostStyle = isVhostStyle;
|
||||
this.servicePath = servicePath;
|
||||
this.uriBuilderProvider = uriBuilderProvider;
|
||||
}
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
if (isVhostStyle) {
|
||||
bindAsHostPrefix.bindToRequest(request, payload);
|
||||
request.getHeaders().replaceValues(HttpHeaders.HOST,
|
||||
ImmutableSet.of(request.getEndpoint().getHost()));
|
||||
} else {
|
||||
UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint());
|
||||
StringBuilder path = new StringBuilder(urlEncode(request.getEndpoint().getPath(),
|
||||
S3AsyncClient.class.getAnnotation(SkipEncoding.class).value()));
|
||||
int indexToInsert = path.indexOf(servicePath);
|
||||
indexToInsert = indexToInsert == -1 ? 0 : indexToInsert;
|
||||
indexToInsert += servicePath.length();
|
||||
path.insert(indexToInsert, "/" + payload.toString());
|
||||
builder.replacePath(path.toString());
|
||||
request.setEndpoint(builder.buildFromEncodedMap(Maps.<String, Object> newHashMap()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.binders;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.Binder;
|
||||
|
@ -30,11 +30,17 @@ import org.jclouds.rest.Binder;
|
|||
*/
|
||||
@Singleton
|
||||
public class BindNoBucketLoggingToXmlPayload implements Binder {
|
||||
private final BindAsHostPrefixIfConfigured bindAsHostPrefixIfConfigured;
|
||||
|
||||
@Inject
|
||||
BindNoBucketLoggingToXmlPayload(BindAsHostPrefixIfConfigured bindAsHostPrefixIfConfigured) {
|
||||
this.bindAsHostPrefixIfConfigured = bindAsHostPrefixIfConfigured;
|
||||
}
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
bindAsHostPrefixIfConfigured.bindToRequest(request, payload);
|
||||
String stringPayload = "<BucketLoggingStatus xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"/>";
|
||||
request.setPayload(stringPayload);
|
||||
request.getPayload().setContentType(MediaType.TEXT_XML);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ public class S3RestClientModule extends AWSRestClientModule<S3Client, S3AsyncCli
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
RequestSigner provideRequestSigner(RequestAuthorizeSignature in) {
|
||||
protected RequestSigner provideRequestSigner(RequestAuthorizeSignature in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ public class S3RestClientModule extends AWSRestClientModule<S3Client, S3AsyncCli
|
|||
@Provides
|
||||
@TimeStamp
|
||||
@Singleton
|
||||
Supplier<String> provideTimeStampCache(@Named(Constants.PROPERTY_SESSION_INTERVAL) long seconds,
|
||||
protected Supplier<String> provideTimeStampCache(@Named(Constants.PROPERTY_SESSION_INTERVAL) long seconds,
|
||||
final DateService dateService) {
|
||||
return new ExpirableSupplier<String>(new Supplier<String>() {
|
||||
public String get() {
|
||||
|
|
|
@ -18,9 +18,17 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.filters;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
|
||||
import static org.jclouds.Constants.PROPERTY_IDENTITY;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
|
||||
import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
@ -34,7 +42,7 @@ import javax.inject.Singleton;
|
|||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.aws.s3.reference.S3Constants;
|
||||
import org.jclouds.aws.s3.Bucket;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.HttpException;
|
||||
|
@ -44,10 +52,13 @@ import org.jclouds.http.HttpUtils;
|
|||
import org.jclouds.http.internal.SignatureWire;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.RequestSigner;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.util.Utils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* Signs the S3 request.
|
||||
|
@ -75,18 +86,21 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
|||
|
||||
private final String authTag;
|
||||
private final String headerTag;
|
||||
private final String srvExpr;
|
||||
private final String servicePath;
|
||||
private final boolean isVhostStyle;
|
||||
|
||||
@Inject
|
||||
public RequestAuthorizeSignature(SignatureWire signatureWire,
|
||||
@Named(S3Constants.PROPERTY_S3_AUTH_TAG) String authTag,
|
||||
@Named(S3Constants.PROPERTY_S3_SERVICE_EXPR) String srvExpr,
|
||||
@Named(S3Constants.PROPERTY_S3_HEADER_TAG) String headerTag,
|
||||
@Named(Constants.PROPERTY_IDENTITY) String accessKey,
|
||||
@Named(Constants.PROPERTY_CREDENTIAL) String secretKey,
|
||||
@Named(PROPERTY_AUTH_TAG) String authTag,
|
||||
@Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle,
|
||||
@Named(PROPERTY_S3_SERVICE_PATH) String servicePath,
|
||||
@Named(PROPERTY_HEADER_TAG) String headerTag,
|
||||
@Named(PROPERTY_IDENTITY) String accessKey,
|
||||
@Named(PROPERTY_CREDENTIAL) String secretKey,
|
||||
@TimeStamp Provider<String> timeStampProvider, EncryptionService encryptionService,
|
||||
HttpUtils utils) {
|
||||
this.srvExpr = srvExpr;
|
||||
this.isVhostStyle = isVhostStyle;
|
||||
this.servicePath = servicePath;
|
||||
this.headerTag = headerTag;
|
||||
this.authTag = authTag;
|
||||
this.signatureWire = signatureWire;
|
||||
|
@ -112,15 +126,15 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
|||
appendPayloadMetadata(request, buffer);
|
||||
appendHttpHeaders(request, buffer);
|
||||
appendAmzHeaders(request, buffer);
|
||||
appendBucketName(request, buffer);
|
||||
if (isVhostStyle)
|
||||
appendBucketName(request, buffer);
|
||||
appendUriPath(request, buffer);
|
||||
if (signatureWire.enabled())
|
||||
signatureWire.output(buffer.toString());
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private void calculateAndReplaceAuthHeader(HttpRequest request, String toSign)
|
||||
throws HttpException {
|
||||
void calculateAndReplaceAuthHeader(HttpRequest request, String toSign) throws HttpException {
|
||||
String signature = sign(toSign);
|
||||
if (signatureWire.enabled())
|
||||
signatureWire.input(Utils.toInputStream(signature));
|
||||
|
@ -139,16 +153,16 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
|||
return signature;
|
||||
}
|
||||
|
||||
private void appendMethod(HttpRequest request, StringBuilder toSign) {
|
||||
void appendMethod(HttpRequest request, StringBuilder toSign) {
|
||||
toSign.append(request.getMethod()).append("\n");
|
||||
}
|
||||
|
||||
private void replaceDateHeader(HttpRequest request) {
|
||||
void replaceDateHeader(HttpRequest request) {
|
||||
request.getHeaders().replaceValues(HttpHeaders.DATE,
|
||||
Collections.singletonList(timeStampProvider.get()));
|
||||
}
|
||||
|
||||
private void appendAmzHeaders(HttpRequest request, StringBuilder toSign) {
|
||||
void appendAmzHeaders(HttpRequest request, StringBuilder toSign) {
|
||||
Set<String> headers = new TreeSet<String>(request.getHeaders().keySet());
|
||||
for (String header : headers) {
|
||||
if (header.startsWith("x-" + headerTag + "-")) {
|
||||
|
@ -162,7 +176,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
|||
}
|
||||
}
|
||||
|
||||
private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
|
||||
void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
|
||||
buffer.append(
|
||||
utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload()
|
||||
.getContentMD5())).append("\n");
|
||||
|
@ -171,19 +185,33 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
|||
.getContentType())).append("\n");
|
||||
}
|
||||
|
||||
private void appendHttpHeaders(HttpRequest request, StringBuilder toSign) {
|
||||
void appendHttpHeaders(HttpRequest request, StringBuilder toSign) {
|
||||
for (String header : firstHeadersToSign)
|
||||
toSign.append(valueOrEmpty(request.getHeaders().get(header))).append("\n");
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void appendBucketName(HttpRequest request, StringBuilder toSign) {
|
||||
String hostHeader = request.getFirstHeaderOrNull(HttpHeaders.HOST);
|
||||
if (hostHeader == null)
|
||||
hostHeader = checkNotNull(request.getEndpoint().getHost(),
|
||||
"request.getEndPoint().getHost()");
|
||||
if (hostHeader.matches(".*" + srvExpr))
|
||||
toSign.append("/").append(hostHeader.replaceAll(srvExpr, ""));
|
||||
void appendBucketName(HttpRequest req, StringBuilder toSign) {
|
||||
checkArgument(req instanceof GeneratedHttpRequest<?>,
|
||||
"this should be a generated http request");
|
||||
GeneratedHttpRequest<?> request = GeneratedHttpRequest.class.cast(req);
|
||||
|
||||
String bucketName = null;
|
||||
|
||||
for (int i = 0; i < request.getJavaMethod().getParameterAnnotations().length; i++) {
|
||||
if (Iterables.any(Arrays.asList(request.getJavaMethod().getParameterAnnotations()[i]),
|
||||
new Predicate<Annotation>() {
|
||||
public boolean apply(Annotation input) {
|
||||
return input.annotationType().equals(Bucket.class);
|
||||
}
|
||||
})) {
|
||||
bucketName = (String) request.getArgs()[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bucketName != null)
|
||||
toSign.append(servicePath).append(bucketName);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
|
|
@ -22,9 +22,9 @@ import javax.inject.Inject;
|
|||
|
||||
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -57,8 +57,10 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
|
|||
return object;
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseObjectFromHeadersAndHttpContent setContext(HttpRequest request) {
|
||||
metadataParser.setContext(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,20 +18,21 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.functions;
|
||||
|
||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import org.jclouds.aws.s3.blobstore.functions.BlobToObjectMetadata;
|
||||
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.util.Utils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
@ -49,13 +50,16 @@ public class ParseObjectMetadataFromHeaders implements
|
|||
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
|
||||
private final BlobToObjectMetadata blobToObjectMetadata;
|
||||
private final EncryptionService encryptionService;
|
||||
private final String userMdPrefix;
|
||||
|
||||
@Inject
|
||||
public ParseObjectMetadataFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
|
||||
BlobToObjectMetadata blobToObjectMetadata, EncryptionService encryptionService) {
|
||||
BlobToObjectMetadata blobToObjectMetadata, EncryptionService encryptionService,
|
||||
@Named(PROPERTY_USER_METADATA_PREFIX) String userMdPrefix) {
|
||||
this.blobMetadataParser = blobMetadataParser;
|
||||
this.blobToObjectMetadata = blobToObjectMetadata;
|
||||
this.encryptionService = encryptionService;
|
||||
this.userMdPrefix = userMdPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,15 +84,17 @@ public class ParseObjectMetadataFromHeaders implements
|
|||
@VisibleForTesting
|
||||
protected void addETagTo(HttpResponse from, MutableObjectMetadata metadata) {
|
||||
if (metadata.getETag() == null) {
|
||||
String eTagHeader = from.getFirstHeaderOrNull(S3Headers.AMZ_MD5);
|
||||
String eTagHeader = from.getFirstHeaderOrNull(userMdPrefix + "object-eTag");
|
||||
if (eTagHeader != null) {
|
||||
metadata.setETag(eTagHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseObjectMetadataFromHeaders setContext(HttpRequest request) {
|
||||
blobMetadataParser.setContext(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -20,11 +20,13 @@ package org.jclouds.aws.s3.options;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
@ -70,11 +72,8 @@ import com.google.common.collect.Multimap;
|
|||
*/
|
||||
public class CopyObjectOptions extends BaseHttpRequestOptions {
|
||||
private final static DateService dateService = new SimpleDateFormatDateService();
|
||||
|
||||
public static final CopyObjectOptions NONE = new CopyObjectOptions();
|
||||
|
||||
private Map<String, String> metadata;
|
||||
|
||||
private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
|
||||
|
||||
private String metadataPrefix;
|
||||
|
@ -84,6 +83,13 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
this.metadataPrefix = metadataPrefix;
|
||||
}
|
||||
|
||||
private String headerTag;
|
||||
|
||||
@Inject
|
||||
public void setHeaderTag(@Named(PROPERTY_HEADER_TAG) String headerTag) {
|
||||
this.headerTag = headerTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default ACL (private) with the specified one.
|
||||
*
|
||||
|
@ -251,15 +257,18 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
|
||||
@Override
|
||||
public Multimap<String, String> buildRequestHeaders() {
|
||||
checkState(headerTag != null, "headerTag should have been injected!");
|
||||
checkState(metadataPrefix != null, "metadataPrefix should have been injected!");
|
||||
Multimap<String, String> returnVal = LinkedHashMultimap.create();
|
||||
returnVal.putAll(headers);
|
||||
for (Entry<String, String> entry : headers.entries()) {
|
||||
returnVal.put(entry.getKey().replace("aws", headerTag), entry.getValue());
|
||||
}
|
||||
if (metadata != null) {
|
||||
for (String key : metadata.keySet()) {
|
||||
returnVal.put(key.startsWith(metadataPrefix) ? key : metadataPrefix + key, metadata
|
||||
.get(key));
|
||||
}
|
||||
returnVal.put("x-amz-metadata-directive", "REPLACE");
|
||||
returnVal.put("x-" + headerTag + "-metadata-directive", "REPLACE");
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
|
|
@ -19,11 +19,21 @@
|
|||
package org.jclouds.aws.s3.options;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.aws.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* Contains options supported in the REST API for the PUT bucket operation. <h2>
|
||||
* Usage</h2> The recommended way to instantiate a PutBucketOptions object is to statically import
|
||||
|
@ -47,6 +57,23 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
|
|||
public class PutBucketOptions extends BaseHttpRequestOptions {
|
||||
private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
|
||||
|
||||
private String headerTag;
|
||||
|
||||
@Inject
|
||||
public void setHeaderTag(@Named(PROPERTY_HEADER_TAG) String headerTag) {
|
||||
this.headerTag = headerTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multimap<String, String> buildRequestHeaders() {
|
||||
checkState(headerTag != null, "headerTag should have been injected!");
|
||||
Multimap<String, String> returnVal = LinkedHashMultimap.create();
|
||||
for (Entry<String, String> entry : headers.entries()) {
|
||||
returnVal.put(entry.getKey().replace("aws", headerTag), entry.getValue());
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default ACL (private) with the specified one.
|
||||
*
|
||||
|
|
|
@ -18,11 +18,20 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.options;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.aws.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import static com.google.common.base.Preconditions.*;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||
|
||||
/**
|
||||
* Contains options supported in the REST API for the PUT object operation.
|
||||
|
@ -50,7 +59,23 @@ public class PutObjectOptions extends BaseHttpRequestOptions {
|
|||
public static final PutObjectOptions NONE = new PutObjectOptions();
|
||||
|
||||
private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
|
||||
|
||||
private String headerTag;
|
||||
|
||||
@Inject
|
||||
public void setHeaderTag(@Named(PROPERTY_HEADER_TAG) String headerTag) {
|
||||
this.headerTag = headerTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multimap<String, String> buildRequestHeaders() {
|
||||
checkState(headerTag != null, "headerTag should have been injected!");
|
||||
Multimap<String, String> returnVal = LinkedHashMultimap.create();
|
||||
for (Entry<String, String> entry : headers.entries()) {
|
||||
returnVal.put(entry.getKey().replace("aws", headerTag), entry.getValue());
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
/**
|
||||
* Override the default ACL (private) with the specified one.
|
||||
*
|
||||
|
|
|
@ -33,10 +33,7 @@ public interface S3Constants {
|
|||
public static final String MARKER = "marker";
|
||||
public static final String MAX_KEYS = "max-keys";
|
||||
public static final String DELIMITER = "delimiter";
|
||||
|
||||
public static final String PROPERTY_S3_SERVICE_EXPR = "jclouds.service.expr";
|
||||
|
||||
public static final String PROPERTY_S3_AUTH_TAG = "jclouds.s3.auth.tag";
|
||||
public static final String PROPERTY_S3_HEADER_TAG = "jclouds.s3.header.tag";
|
||||
public static final String PROPERTY_S3_SERVICE_PATH = "jclouds.s3.service-path";
|
||||
public static final String PROPERTY_S3_VIRTUAL_HOST_BUCKETS = "jclouds.s3.virtual-host-buckets";
|
||||
|
||||
}
|
||||
|
|
|
@ -36,7 +36,5 @@ public interface S3Headers {
|
|||
*/
|
||||
public static final String CANNED_ACL = "x-amz-acl";
|
||||
public static final String AMZ_MD5 = "x-amz-meta-object-eTag";
|
||||
public static final String REQUEST_ID = "x-amz-request-id";
|
||||
public static final String REQUEST_TOKEN = "x-amz-id-2";
|
||||
|
||||
}
|
|
@ -21,20 +21,9 @@ package org.jclouds.aws.s3.util;
|
|||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.domain.AWSError;
|
||||
import org.jclouds.aws.s3.S3Client;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.http.HttpCommand;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.util.Patterns;
|
||||
|
||||
/**
|
||||
|
@ -42,27 +31,8 @@ import org.jclouds.util.Patterns;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class S3Utils {
|
||||
|
||||
@Inject
|
||||
AWSUtils util;
|
||||
|
||||
public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
|
||||
InputStream content) throws HttpException {
|
||||
AWSError error = util.parseAWSErrorFromContent(command.getRequest(), response, content);
|
||||
if (error.getRequestId() == null)
|
||||
error.setRequestId(response.getFirstHeaderOrNull(S3Headers.REQUEST_ID));
|
||||
error.setRequestToken(response.getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN));
|
||||
return error;
|
||||
}
|
||||
|
||||
public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
|
||||
String content) throws HttpException {
|
||||
return parseAWSErrorFromContent(command, response, new ByteArrayInputStream(content
|
||||
.getBytes()));
|
||||
}
|
||||
|
||||
public static final Pattern BUCKET_NAME_PATTERN = Pattern.compile("^[a-z0-9][-_.a-z0-9]+");
|
||||
|
||||
// TODO add validatorparam so that this is actually used
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.jclouds.aws.sqs;
|
|||
|
||||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||
import static org.jclouds.Constants.PROPERTY_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.aws.reference.AWSConstants.PROPERTY_REGIONS;
|
||||
|
||||
import java.util.Properties;
|
||||
|
@ -38,6 +40,8 @@ public class SQSPropertiesBuilder extends PropertiesBuilder {
|
|||
@Override
|
||||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||
properties.setProperty(PROPERTY_API_VERSION, SQSAsyncClient.VERSION);
|
||||
properties.setProperty(PROPERTY_REGIONS, Joiner.on(',').join(Region.US_EAST_1,
|
||||
Region.US_WEST_1, Region.EU_WEST_1, Region.AP_SOUTHEAST_1));
|
||||
|
|
|
@ -18,19 +18,22 @@
|
|||
*/
|
||||
package org.jclouds.aws.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.domain.AWSError;
|
||||
import org.jclouds.aws.xml.ErrorHandler;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.http.functions.ParseSax.Factory;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.RequestSigner;
|
||||
|
||||
/**
|
||||
|
@ -43,27 +46,43 @@ public class AWSUtils {
|
|||
private final RequestSigner signer;
|
||||
private final ParseSax.Factory factory;
|
||||
private final Provider<ErrorHandler> errorHandlerProvider;
|
||||
private final String requestId;
|
||||
private final String requestToken;
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Inject
|
||||
AWSUtils(RequestSigner signer, Factory factory, Provider<ErrorHandler> errorHandlerProvider) {
|
||||
AWSUtils(@Named(PROPERTY_HEADER_TAG) String headerTag, RequestSigner signer, Factory factory,
|
||||
Provider<ErrorHandler> errorHandlerProvider) {
|
||||
this.signer = signer;
|
||||
this.factory = factory;
|
||||
this.errorHandlerProvider = errorHandlerProvider;
|
||||
this.requestId = String.format("x-%s-request-id", headerTag);
|
||||
this.requestToken = String.format("x-%s-id-2", headerTag);
|
||||
}
|
||||
|
||||
public AWSError parseAWSErrorFromContent(HttpRequest request, HttpResponse response,
|
||||
InputStream content) {
|
||||
AWSError error = (AWSError) factory.create(errorHandlerProvider.get()).parse(content);
|
||||
if ("SignatureDoesNotMatch".equals(error.getCode())) {
|
||||
error.setStringSigned(signer.createStringToSign(request));
|
||||
error.setSignature(signer.sign(error.getStringSigned()));
|
||||
public AWSError parseAWSErrorFromContent(HttpRequest request, HttpResponse response) {
|
||||
// HEAD has no content
|
||||
if (response.getPayload() == null)
|
||||
return null;
|
||||
// Eucalyptus and Walrus occasionally return text/plain
|
||||
if (response.getPayload().getContentType() != null
|
||||
&& response.getPayload().getContentType().indexOf("text") != -1)
|
||||
return null;
|
||||
try {
|
||||
AWSError error = (AWSError) factory.create(errorHandlerProvider.get()).setContext(request)
|
||||
.apply(response);
|
||||
if (error.getRequestId() == null)
|
||||
error.setRequestId(response.getFirstHeaderOrNull(requestId));
|
||||
error.setRequestToken(response.getFirstHeaderOrNull(requestToken));
|
||||
if ("SignatureDoesNotMatch".equals(error.getCode())) {
|
||||
error.setStringSigned(signer.createStringToSign(request));
|
||||
error.setSignature(signer.sign(error.getStringSigned()));
|
||||
}
|
||||
return error;
|
||||
} catch (HttpException e) {
|
||||
logger.warn(e, "error parsing error");
|
||||
return null;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
public AWSError parseAWSErrorFromContent(HttpRequest request, HttpResponse response,
|
||||
String content) {
|
||||
return parseAWSErrorFromContent(request, response, new ByteArrayInputStream(content
|
||||
.getBytes()));
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import static org.easymock.EasyMock.reportMatcher;
|
|||
import static org.easymock.classextension.EasyMock.createMock;
|
||||
import static org.easymock.classextension.EasyMock.replay;
|
||||
import static org.easymock.classextension.EasyMock.verify;
|
||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
|
@ -22,6 +23,7 @@ import org.testng.annotations.Test;
|
|||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -57,7 +59,7 @@ public class ParseAWSErrorFromXmlContentTest {
|
|||
@Override
|
||||
protected void configure() {
|
||||
bind(RequestSigner.class).toInstance(createMock(RequestSigner.class));
|
||||
|
||||
bindConstant().annotatedWith(Names.named(PROPERTY_HEADER_TAG)).to("amz");
|
||||
}
|
||||
|
||||
}).getInstance(ParseAWSErrorFromXmlContent.class);
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.aws.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.RestClientTest;
|
||||
import org.jclouds.rest.RestContextFactory;
|
||||
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
public abstract class BaseS3AsyncClientTest extends RestClientTest<S3AsyncClient> {
|
||||
|
||||
protected BlobToObject blobToS3Object;
|
||||
protected RequestAuthorizeSignature filter;
|
||||
|
||||
|
||||
@Override
|
||||
protected void checkFilters(HttpRequest request) {
|
||||
assertEquals(request.getFilters().size(), 1);
|
||||
assertEquals(request.getFilters().get(0).getClass(), RequestAuthorizeSignature.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeLiteral<RestAnnotationProcessor<S3AsyncClient>> createTypeLiteral() {
|
||||
return new TypeLiteral<RestAnnotationProcessor<S3AsyncClient>>() {
|
||||
};
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
@Override
|
||||
protected void setupFactory() throws IOException {
|
||||
super.setupFactory();
|
||||
blobToS3Object = injector.getInstance(BlobToObject.class);
|
||||
filter = injector.getInstance(RequestAuthorizeSignature.class);
|
||||
}
|
||||
|
||||
public BaseS3AsyncClientTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextSpec<?, ?> createContextSpec() {
|
||||
return new RestContextFactory().createContextSpec("s3", "identity", "credential",
|
||||
new Properties());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -23,10 +23,8 @@ import static org.testng.Assert.assertEquals;
|
|||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.aws.domain.Region;
|
||||
import org.jclouds.aws.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.aws.s3.config.S3RestClientModule;
|
||||
import org.jclouds.aws.s3.domain.AccessControlList;
|
||||
import org.jclouds.aws.s3.domain.BucketLogging;
|
||||
|
@ -36,7 +34,6 @@ import org.jclouds.aws.s3.domain.S3Object;
|
|||
import org.jclouds.aws.s3.domain.AccessControlList.EmailAddressGrantee;
|
||||
import org.jclouds.aws.s3.domain.AccessControlList.Grant;
|
||||
import org.jclouds.aws.s3.domain.AccessControlList.Permission;
|
||||
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
|
||||
import org.jclouds.aws.s3.functions.ParseObjectFromHeadersAndHttpContent;
|
||||
import org.jclouds.aws.s3.functions.ParseObjectMetadataFromHeaders;
|
||||
import org.jclouds.aws.s3.functions.ReturnFalseIfBucketAlreadyOwnedByYou;
|
||||
|
@ -61,25 +58,19 @@ import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
|
|||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.functions.ReleasePayloadAndReturn;
|
||||
import org.jclouds.http.functions.ParseETagHeader;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.http.functions.ReleasePayloadAndReturn;
|
||||
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.RestClientTest;
|
||||
import org.jclouds.rest.RestContextFactory;
|
||||
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||
import org.jclouds.util.Utils;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code S3Client}
|
||||
|
@ -87,7 +78,7 @@ import com.google.inject.TypeLiteral;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "s3.S3ClientTest")
|
||||
public class S3AsyncClientTest extends RestClientTest<S3AsyncClient> {
|
||||
public class S3AsyncClientTest extends BaseS3AsyncClientTest {
|
||||
|
||||
public void testAllRegions() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = S3AsyncClient.class.getMethod("putBucketInRegion", String.class,
|
||||
|
@ -228,8 +219,7 @@ public class S3AsyncClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(request,
|
||||
"PUT https://destinationbucket.s3.amazonaws.com/destinationObject HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(
|
||||
request,
|
||||
assertNonPayloadHeadersEqual(request,
|
||||
"Host: destinationbucket.s3.amazonaws.com\nx-amz-copy-source: /sourceBucket/sourceObject\n");
|
||||
assertPayloadEquals(request, null, null, false);
|
||||
|
||||
|
@ -416,8 +406,7 @@ public class S3AsyncClientTest extends RestClientTest<S3AsyncClient> {
|
|||
HttpRequest request = processor.createRequest(method, "EU", "bucket");
|
||||
|
||||
assertRequestLineEquals(request, "PUT https://bucket.s3.amazonaws.com/ HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(request,
|
||||
"Host: bucket.s3.amazonaws.com\n");
|
||||
assertNonPayloadHeadersEqual(request, "Host: bucket.s3.amazonaws.com\n");
|
||||
assertPayloadEquals(
|
||||
request,
|
||||
"<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>",
|
||||
|
@ -434,7 +423,7 @@ public class S3AsyncClientTest extends RestClientTest<S3AsyncClient> {
|
|||
IllegalArgumentException, NoSuchMethodException, IOException {
|
||||
|
||||
Method method = S3AsyncClient.class.getMethod("putObject", String.class, S3Object.class,
|
||||
Array.newInstance(PutObjectOptions.class, 0).getClass());
|
||||
PutObjectOptions[].class);
|
||||
HttpRequest request = processor.createRequest(method, "bucket", blobToS3Object
|
||||
.apply(BindBlobToMultipartFormTest.TEST_BLOB));
|
||||
|
||||
|
@ -522,37 +511,9 @@ public class S3AsyncClientTest extends RestClientTest<S3AsyncClient> {
|
|||
checkFilters(request);
|
||||
}
|
||||
|
||||
BlobToObject blobToS3Object;
|
||||
RequestAuthorizeSignature filter;
|
||||
|
||||
@Override
|
||||
protected void checkFilters(HttpRequest request) {
|
||||
assertEquals(request.getFilters().size(), 1);
|
||||
assertEquals(request.getFilters().get(0).getClass(), RequestAuthorizeSignature.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeLiteral<RestAnnotationProcessor<S3AsyncClient>> createTypeLiteral() {
|
||||
return new TypeLiteral<RestAnnotationProcessor<S3AsyncClient>>() {
|
||||
};
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
@Override
|
||||
protected void setupFactory() throws IOException {
|
||||
super.setupFactory();
|
||||
blobToS3Object = injector.getInstance(BlobToObject.class);
|
||||
filter = injector.getInstance(RequestAuthorizeSignature.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new TestS3RestClientModule();
|
||||
}
|
||||
|
||||
@RequiresHttp
|
||||
@ConfiguresRestClient
|
||||
private static final class TestS3RestClientModule extends S3RestClientModule {
|
||||
protected static final class TestS3RestClientModule extends S3RestClientModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
|
@ -565,9 +526,8 @@ public class S3AsyncClientTest extends RestClientTest<S3AsyncClient> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ContextSpec<?, ?> createContextSpec() {
|
||||
return new RestContextFactory().createContextSpec("s3", "identity", "credential",
|
||||
new Properties());
|
||||
protected Module createModule() {
|
||||
return new TestS3RestClientModule();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3.binders;
|
||||
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.aws.s3.BaseS3AsyncClientTest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code BindAsHostPrefixIfConfigured}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "s3.BindAsHostPrefixIfConfiguredTest")
|
||||
public class BindAsHostPrefixIfConfiguredTest extends BaseS3AsyncClientTest {
|
||||
|
||||
public void testBucket() throws IOException {
|
||||
|
||||
HttpRequest request = new HttpRequest("GET", URI.create("http://euc/services/Walrus"));
|
||||
BindAsHostPrefixIfConfigured binder = injector
|
||||
.getInstance(BindAsHostPrefixIfConfigured.class);
|
||||
|
||||
binder.bindToRequest(request, "bucket");
|
||||
assertEquals(request.getRequestLine(), "GET http://euc/services/Walrus/bucket HTTP/1.1");
|
||||
|
||||
}
|
||||
|
||||
@Test(dataProvider = "objects")
|
||||
public void testObject(String key) throws InterruptedException {
|
||||
|
||||
HttpRequest request = new HttpRequest("GET", URI.create("http://euc/services/Walrus/object"));
|
||||
BindAsHostPrefixIfConfigured binder = injector
|
||||
.getInstance(BindAsHostPrefixIfConfigured.class);
|
||||
|
||||
binder.bindToRequest(request, "bucket");
|
||||
assertEquals(request.getRequestLine(),
|
||||
"GET http://euc/services/Walrus/bucket/object HTTP/1.1");
|
||||
|
||||
}
|
||||
|
||||
@DataProvider(name = "objects")
|
||||
public Object[][] createData() {
|
||||
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" },
|
||||
{ "path/foo" }, { "colon:" }, { "asteri*k" }, { "quote\"" }, { "{great<r}" },
|
||||
{ "lesst>en" }, { "p|pe" } };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties getProperties() {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(PROPERTY_S3_SERVICE_PATH, "/services/Walrus");
|
||||
properties.setProperty(PROPERTY_S3_VIRTUAL_HOST_BUCKETS, "false");
|
||||
return properties;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,8 +23,8 @@ import static org.testng.Assert.assertEquals;
|
|||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.aws.s3.BaseS3AsyncClientTest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,7 @@ import org.testng.annotations.Test;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "s3.BindNoBucketLoggingToXmlPayloadTest")
|
||||
public class BindNoBucketLoggingToXmlPayloadTest extends BaseHandlerTest {
|
||||
public class BindNoBucketLoggingToXmlPayloadTest extends BaseS3AsyncClientTest {
|
||||
|
||||
public void testApplyInputStream() throws IOException {
|
||||
|
||||
|
@ -41,8 +41,7 @@ public class BindNoBucketLoggingToXmlPayloadTest extends BaseHandlerTest {
|
|||
BindNoBucketLoggingToXmlPayload binder = injector
|
||||
.getInstance(BindNoBucketLoggingToXmlPayload.class);
|
||||
|
||||
binder.bindToRequest(request, null);
|
||||
assertEquals(request.getPayload().getContentType(), "text/xml");
|
||||
binder.bindToRequest(request, "bucket");
|
||||
assertEquals(request.getPayload().getRawContent(),
|
||||
"<BucketLoggingStatus xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"/>");
|
||||
|
||||
|
|
|
@ -18,43 +18,33 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.filters;
|
||||
|
||||
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.aws.s3.BaseS3AsyncClientTest;
|
||||
import org.jclouds.aws.s3.S3AsyncClient;
|
||||
import org.jclouds.aws.s3.domain.AccessControlList;
|
||||
import org.jclouds.aws.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.options.PutObjectOptions;
|
||||
import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.logging.config.NullLoggingModule;
|
||||
import org.jclouds.rest.RestContextFactory;
|
||||
import org.jclouds.rest.BaseRestClientTest.MockModule;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
@Test(groups = "unit", testName = "s3.RequestAuthorizeSignatureTest")
|
||||
public class RequestAuthorizeSignatureTest {
|
||||
|
||||
private RequestAuthorizeSignature filter;
|
||||
public class RequestAuthorizeSignatureTest extends BaseS3AsyncClientTest {
|
||||
|
||||
@DataProvider(parallel = true)
|
||||
public Object[][] dataProvider() {
|
||||
return new Object[][] {
|
||||
{ new HttpRequest(HttpMethod.GET, URI.create("http://s3.amazonaws.com:80")) },
|
||||
{ new HttpRequest(
|
||||
HttpMethod.GET,
|
||||
URI
|
||||
.create("http://adriancole.s3int5.s3-external-3.amazonaws.com:80/testObject")) },
|
||||
{ new HttpRequest(HttpMethod.GET, URI.create("http://s3.amazonaws.com:80/?acl"))
|
||||
public Object[][] dataProvider() throws NoSuchMethodException {
|
||||
return new Object[][] { { listOwnedBuckets() }, { putObject() }, { putBucketAcl() }
|
||||
|
||||
} };
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,7 +52,7 @@ public class RequestAuthorizeSignatureTest {
|
|||
* this was once per second. If this timestamp update interval is increased, it could make this
|
||||
* test appear to hang for a long time.
|
||||
*/
|
||||
@Test(threadPoolSize = 3, dataProvider = "dataProvider", timeOut = 3000)
|
||||
@Test(threadPoolSize = 3, dataProvider = "dataProvider", timeOut = 10000)
|
||||
void testIdempotent(HttpRequest request) {
|
||||
filter.filter(request);
|
||||
String signature = request.getFirstHeaderOrNull(HttpHeaders.AUTHORIZATION);
|
||||
|
@ -84,70 +74,69 @@ public class RequestAuthorizeSignatureTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testAppendBucketNameHostHeader() {
|
||||
URI host = URI.create("http://s3.amazonaws.com:80");
|
||||
HttpRequest request = new HttpRequest(HttpMethod.GET, host);
|
||||
request.getHeaders().put(HttpHeaders.HOST, "adriancole.s3int5.s3.amazonaws.com");
|
||||
void testAppendBucketNameHostHeader() throws SecurityException, NoSuchMethodException {
|
||||
HttpRequest request = processor.createRequest(S3AsyncClient.class.getMethod(
|
||||
"getBucketLocation", String.class), "bucket");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
filter.appendBucketName(request, builder);
|
||||
assertEquals(builder.toString(), "/adriancole.s3int5");
|
||||
assertEquals(builder.toString(), "/bucket");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAclQueryString() {
|
||||
URI host = URI.create("http://s3.amazonaws.com:80/?acl");
|
||||
HttpRequest request = new HttpRequest(HttpMethod.GET, host);
|
||||
void testAclQueryString() throws SecurityException, NoSuchMethodException {
|
||||
HttpRequest request = putBucketAcl();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
filter.appendUriPath(request, builder);
|
||||
assertEquals(builder.toString(), "/?acl");
|
||||
}
|
||||
|
||||
private GeneratedHttpRequest<S3AsyncClient> putBucketAcl() throws NoSuchMethodException {
|
||||
return processor.createRequest(S3AsyncClient.class.getMethod("putBucketACL", String.class,
|
||||
AccessControlList.class), "bucket", AccessControlList.fromCannedAccessPolicy(
|
||||
CannedAccessPolicy.PRIVATE, "1234"));
|
||||
}
|
||||
|
||||
// "?acl", "?location", "?logging", or "?torrent"
|
||||
|
||||
@Test
|
||||
void testAppendBucketNameHostHeaderService() {
|
||||
URI host = URI.create("http://s3.amazonaws.com:80");
|
||||
HttpRequest request = new HttpRequest(HttpMethod.GET, host);
|
||||
request.getHeaders().put(HttpHeaders.HOST, "s3.amazonaws.com");
|
||||
void testAppendBucketNameHostHeaderService() throws SecurityException, NoSuchMethodException {
|
||||
HttpRequest request = listOwnedBuckets();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
filter.appendBucketName(request, builder);
|
||||
assertEquals(builder.toString(), "");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHeadersGoLowercase() {
|
||||
URI host = URI.create("http://s3.amazonaws.com:80");
|
||||
HttpRequest request = new HttpRequest(HttpMethod.GET, host);
|
||||
request.getHeaders().put("x-amz-adrian", "s3.amazonaws.com");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
filter.appendBucketName(request, builder);
|
||||
assertEquals(builder.toString(), "");
|
||||
private GeneratedHttpRequest<S3AsyncClient> listOwnedBuckets() throws NoSuchMethodException {
|
||||
return processor.createRequest(S3AsyncClient.class.getMethod("listOwnedBuckets"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAppendBucketNameURIHost() {
|
||||
URI host = URI.create("http://adriancole.s3int5.s3-external-3.amazonaws.com:80");
|
||||
HttpRequest request = new HttpRequest(HttpMethod.GET, host);
|
||||
void testHeadersGoLowercase() throws SecurityException, NoSuchMethodException {
|
||||
HttpRequest request = putObject();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
filter.appendBucketName(request, builder);
|
||||
assertEquals(builder.toString(), "/adriancole.s3int5");
|
||||
filter.appendAmzHeaders(request, builder);
|
||||
assertEquals(builder.toString(), "x-amz-meta-x-amz-adrian:foo\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* before class, as we need to ensure that the filter is threadsafe.
|
||||
*
|
||||
* @throws IOException
|
||||
*
|
||||
*/
|
||||
@BeforeClass
|
||||
protected void createFilter() throws IOException {
|
||||
Properties overrides = new Properties();
|
||||
overrides.setProperty(Constants.PROPERTY_SESSION_INTERVAL, "1");
|
||||
Injector injector = new RestContextFactory().createContextBuilder("s3", "foo", "bar",
|
||||
ImmutableSet.of(new MockModule(), new NullLoggingModule()), overrides)
|
||||
.buildInjector();
|
||||
private HttpRequest putObject() throws NoSuchMethodException {
|
||||
S3Object object = blobToS3Object.apply(BindBlobToMultipartFormTest.TEST_BLOB);
|
||||
|
||||
filter = injector.getInstance(RequestAuthorizeSignature.class);
|
||||
object.getMetadata().getUserMetadata().put("x-amz-Adrian", "foo");
|
||||
HttpRequest request = processor.createRequest(S3AsyncClient.class.getMethod("putObject",
|
||||
String.class, S3Object.class, PutObjectOptions[].class), "bucket", object);
|
||||
return request;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAppendBucketNameURIHost() throws SecurityException, NoSuchMethodException {
|
||||
HttpRequest request = processor.createRequest(S3AsyncClient.class.getMethod(
|
||||
"getBucketLocation", String.class), "bucket");
|
||||
assertEquals(request.getEndpoint().getHost(), "bucket.s3.amazonaws.com");
|
||||
}
|
||||
|
||||
protected Properties getProperties() {
|
||||
Properties overrides= new Properties();
|
||||
overrides.setProperty(PROPERTY_SESSION_INTERVAL, 1 + "");
|
||||
return overrides;
|
||||
}
|
||||
}
|
|
@ -32,7 +32,6 @@ import org.jclouds.aws.s3.blobstore.functions.BlobToObjectMetadata;
|
|||
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
|
||||
import org.jclouds.aws.s3.domain.ObjectMetadata.StorageClass;
|
||||
import org.jclouds.aws.s3.domain.internal.MutableObjectMetadataImpl;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
|
||||
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
|
||||
|
@ -61,7 +60,7 @@ public class ParseObjectMetadataFromHeadersTest {
|
|||
http.getHeaders().put("Content-Disposition", "contentDisposition");
|
||||
http.getHeaders().put(HttpHeaders.CONTENT_ENCODING, "encoding");
|
||||
ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http,
|
||||
"\"abc\""), blobToObjectMetadata, encryptionService);
|
||||
"\"abc\""), blobToObjectMetadata, encryptionService, "x-amz-meta-");
|
||||
MutableObjectMetadata response = parser.apply(http);
|
||||
assertEquals(response, expects);
|
||||
}
|
||||
|
@ -75,9 +74,9 @@ public class ParseObjectMetadataFromHeadersTest {
|
|||
http.getHeaders().put(HttpHeaders.CACHE_CONTROL, "cacheControl");
|
||||
http.getHeaders().put("Content-Disposition", "contentDisposition");
|
||||
http.getHeaders().put(HttpHeaders.CONTENT_ENCODING, "encoding");
|
||||
http.getHeaders().put(S3Headers.AMZ_MD5, "\"abc\"");
|
||||
http.getHeaders().put("x-amz-meta-object-eTag", "\"abc\"");
|
||||
ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http,
|
||||
null), blobToObjectMetadata, encryptionService);
|
||||
null), blobToObjectMetadata, encryptionService, "x-amz-meta-");
|
||||
MutableObjectMetadata response = parser.apply(http);
|
||||
assertEquals(response, expects);
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ public class CopyObjectOptionsTest {
|
|||
void testGoodMetaStatic() {
|
||||
CopyObjectOptions options = overrideMetadataWith(goodMeta);
|
||||
options.setMetadataPrefix("x-amz-meta-");
|
||||
options.setHeaderTag("amz");
|
||||
assertGoodMeta(options);
|
||||
}
|
||||
|
||||
|
@ -92,6 +93,7 @@ public class CopyObjectOptionsTest {
|
|||
@Test
|
||||
void testGoodMeta() {
|
||||
CopyObjectOptions options = new CopyObjectOptions();
|
||||
options.setHeaderTag("amz");
|
||||
options.setMetadataPrefix("x-amz-meta-");
|
||||
options.overrideMetadataWith(goodMeta);
|
||||
assertGoodMeta(options);
|
||||
|
@ -269,6 +271,8 @@ public class CopyObjectOptionsTest {
|
|||
@Test
|
||||
void testBuildRequestHeadersWhenMetadataNull() throws UnsupportedEncodingException {
|
||||
CopyObjectOptions options = new CopyObjectOptions();
|
||||
options.setHeaderTag("amz");
|
||||
|
||||
options.setMetadataPrefix("x-amz-meta-");
|
||||
assert options.buildRequestHeaders() != null;
|
||||
}
|
||||
|
@ -277,6 +281,8 @@ public class CopyObjectOptionsTest {
|
|||
void testBuildRequestHeaders() throws UnsupportedEncodingException {
|
||||
CopyObjectOptions options = ifSourceModifiedSince(now).ifSourceETagDoesntMatch(etag)
|
||||
.overrideMetadataWith(goodMeta);
|
||||
options.setHeaderTag("amz");
|
||||
|
||||
options.setMetadataPrefix("x-amz-meta-");
|
||||
|
||||
Multimap<String, String> headers = options.buildRequestHeaders();
|
||||
|
@ -304,6 +310,8 @@ public class CopyObjectOptionsTest {
|
|||
@Test
|
||||
void testBuildRequestHeadersACL() throws UnsupportedEncodingException {
|
||||
CopyObjectOptions options = overrideAcl(CannedAccessPolicy.AUTHENTICATED_READ);
|
||||
options.setHeaderTag("amz");
|
||||
|
||||
options.setMetadataPrefix("x-amz-meta-");
|
||||
|
||||
Multimap<String, String> headers = options.buildRequestHeaders();
|
||||
|
|
|
@ -52,8 +52,10 @@ public class PutBucketOptionsTest {
|
|||
@Test
|
||||
void testBuildRequestHeaders() throws UnsupportedEncodingException {
|
||||
|
||||
Multimap<String, String> headers = withBucketAcl(CannedAccessPolicy.AUTHENTICATED_READ)
|
||||
.buildRequestHeaders();
|
||||
PutBucketOptions options = withBucketAcl(CannedAccessPolicy.AUTHENTICATED_READ);
|
||||
|
||||
options.setHeaderTag("amz");
|
||||
Multimap<String, String> headers = options.buildRequestHeaders();
|
||||
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
|
||||
CannedAccessPolicy.AUTHENTICATED_READ.toString());
|
||||
}
|
||||
|
|
|
@ -18,44 +18,45 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.options;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import static org.jclouds.aws.s3.options.PutObjectOptions.Builder.withAcl;
|
||||
|
||||
import org.jclouds.aws.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.aws.s3.options.PutObjectOptions;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.jclouds.aws.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* Tests possible uses of PutObjectOptions and PutObjectOptions.Builder.*
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "s3.PutObjectOptionsTest")
|
||||
public class PutObjectOptionsTest {
|
||||
|
||||
@Test
|
||||
public void testAclDefault() {
|
||||
PutObjectOptions options = new PutObjectOptions();
|
||||
assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE);
|
||||
}
|
||||
@Test
|
||||
public void testAclDefault() {
|
||||
PutObjectOptions options = new PutObjectOptions();
|
||||
assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAclStatic() {
|
||||
PutObjectOptions options = withAcl(CannedAccessPolicy.AUTHENTICATED_READ);
|
||||
assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ);
|
||||
}
|
||||
@Test
|
||||
public void testAclStatic() {
|
||||
PutObjectOptions options = withAcl(CannedAccessPolicy.AUTHENTICATED_READ);
|
||||
assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuildRequestHeaders() throws UnsupportedEncodingException {
|
||||
@Test
|
||||
void testBuildRequestHeaders() throws UnsupportedEncodingException {
|
||||
|
||||
Multimap<String, String> headers = withAcl(
|
||||
CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders();
|
||||
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
|
||||
CannedAccessPolicy.AUTHENTICATED_READ.toString());
|
||||
}
|
||||
PutObjectOptions options = withAcl(CannedAccessPolicy.AUTHENTICATED_READ);
|
||||
options.setHeaderTag("amz");
|
||||
|
||||
Multimap<String, String> headers = options.buildRequestHeaders();
|
||||
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
|
||||
CannedAccessPolicy.AUTHENTICATED_READ.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3.util;
|
||||
package org.jclouds.aws.util;
|
||||
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.classextension.EasyMock.createMock;
|
||||
|
@ -28,16 +28,13 @@ import java.io.InputStream;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.aws.domain.AWSError;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.http.HttpCommand;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.Payloads;
|
||||
import org.jclouds.logging.config.NullLoggingModule;
|
||||
import org.jclouds.rest.RestContextFactory;
|
||||
import org.jclouds.rest.BaseRestClientTest.MockModule;
|
||||
import org.jclouds.util.Utils;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
@ -50,10 +47,9 @@ import com.google.inject.Injector;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(sequential = true, groups = { "unit" }, testName = "s3.S3UtilsTest")
|
||||
public class S3UtilsTest {
|
||||
S3Utils utils = null;
|
||||
private HttpResponse response;
|
||||
@Test(sequential = true, groups = { "unit" }, testName = "aws.AWSUtilsTest")
|
||||
public class AWSUtilsTest {
|
||||
AWSUtils utils = null;
|
||||
private HttpCommand command;
|
||||
|
||||
@BeforeTest
|
||||
|
@ -63,10 +59,8 @@ public class S3UtilsTest {
|
|||
ImmutableSet.of(new MockModule(), new NullLoggingModule()), new Properties())
|
||||
.buildInjector();
|
||||
|
||||
utils = injector.getInstance(S3Utils.class);
|
||||
response = new HttpResponse(400, "boa", Payloads.newStringPayload(""));
|
||||
response.getHeaders().put(S3Headers.REQUEST_ID, "requestid");
|
||||
response.getHeaders().put(S3Headers.REQUEST_TOKEN, "requesttoken");
|
||||
utils = injector.getInstance(AWSUtils.class);
|
||||
|
||||
command = createMock(HttpCommand.class);
|
||||
expect(command.getRequest()).andReturn(createMock(HttpRequest.class)).atLeastOnce();
|
||||
replay(command);
|
||||
|
@ -77,14 +71,17 @@ public class S3UtilsTest {
|
|||
utils = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseAWSErrorFromContentHttpCommandHttpResponseInputStream() {
|
||||
InputStream content = getClass().getResourceAsStream("/error.xml");
|
||||
AWSError error = utils.parseAWSErrorFromContent(command, response, content);
|
||||
validate(error);
|
||||
HttpResponse response(InputStream content) {
|
||||
HttpResponse response = new HttpResponse(400, "boa", Payloads.newInputStreamPayload(content));
|
||||
response.getHeaders().put("x-amz-request-id", "requestid");
|
||||
response.getHeaders().put("x-amz-id-2", "requesttoken");
|
||||
return response;
|
||||
}
|
||||
|
||||
private void validate(AWSError error) {
|
||||
@Test
|
||||
public void testParseAWSErrorFromContentHttpCommandHttpResponseInputStream() {
|
||||
AWSError error = utils.parseAWSErrorFromContent(command.getRequest(), response(getClass()
|
||||
.getResourceAsStream("/error.xml")));
|
||||
assertEquals(error.getCode(), "NoSuchKey");
|
||||
assertEquals(error.getMessage(), "The resource you requested does not exist");
|
||||
assertEquals(error.getRequestToken(), "requesttoken");
|
||||
|
@ -92,15 +89,6 @@ public class S3UtilsTest {
|
|||
assertEquals(error.getDetails().get("Resource"), "/mybucket/myfoto.jpg");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseAWSErrorFromContentHttpCommandHttpResponseString() throws HttpException,
|
||||
IOException {
|
||||
InputStream content = getClass().getResourceAsStream("/error.xml");
|
||||
AWSError error = utils.parseAWSErrorFromContent(command, response, Utils
|
||||
.toStringAndClose(content));
|
||||
validate(error);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateBucketName() {
|
||||
// TODO
|
|
@ -144,7 +144,7 @@
|
|||
<category name="jclouds.wire">
|
||||
<priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNCWIRE" />
|
||||
</category>
|
||||
</category><!--
|
||||
|
||||
<category name="jclouds.signature">
|
||||
<priority value="DEBUG" />
|
||||
|
@ -152,7 +152,7 @@
|
|||
</category>
|
||||
|
||||
|
||||
<!-- ======================= -->
|
||||
--><!-- ======================= -->
|
||||
<!-- Setup the Root category -->
|
||||
<!-- ======================= -->
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@ import javax.inject.Singleton;
|
|||
|
||||
import org.jclouds.azure.storage.blob.domain.AzureBlob;
|
||||
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -57,8 +57,10 @@ public class ParseBlobFromHeadersAndHttpContent implements Function<HttpResponse
|
|||
return blob;
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseBlobFromHeadersAndHttpContent setContext(HttpRequest request) {
|
||||
metadataParser.setContext(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -27,9 +27,9 @@ import org.jclouds.azure.storage.blob.blobstore.functions.BlobMetadataToBlobProp
|
|||
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -64,8 +64,10 @@ public class ParseBlobPropertiesFromHeaders implements
|
|||
return to;
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseBlobPropertiesFromHeaders setContext(HttpRequest request) {
|
||||
blobMetadataParser.setContext(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.azure.storage.blob.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -30,6 +32,7 @@ import org.jclouds.azure.storage.blob.domain.internal.MutableContainerProperties
|
|||
import org.jclouds.blobstore.reference.BlobStoreConstants;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
@ -99,8 +102,12 @@ public class ParseContainerPropertiesFromHeaders implements
|
|||
}
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
this.request = request;
|
||||
@Override
|
||||
public ParseContainerPropertiesFromHeaders setContext(HttpRequest request) {
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>,
|
||||
"note this handler requires a GeneratedHttpRequest");
|
||||
this.request = (GeneratedHttpRequest<?>) request;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,11 +18,13 @@
|
|||
*/
|
||||
package org.jclouds.blobstore.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.jclouds.util.Utils.propagateOrNull;
|
||||
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.internal.BlobRuntimeException;
|
||||
import org.jclouds.blobstore.strategy.ClearContainerStrategy;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
@ -64,8 +66,12 @@ public class ClearAndDeleteIfNotEmpty implements Function<Exception, Void>, Invo
|
|||
return Void.class.cast(propagateOrNull(from));
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
this.request = request;
|
||||
@Override
|
||||
public ClearAndDeleteIfNotEmpty setContext(HttpRequest request) {
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>,
|
||||
"note this handler requires a GeneratedHttpRequest");
|
||||
this.request = (GeneratedHttpRequest<?>) request;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ import javax.inject.Inject;
|
|||
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -54,8 +54,10 @@ public class ParseBlobFromHeadersAndHttpContent implements Function<HttpResponse
|
|||
return object;
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseBlobFromHeadersAndHttpContent setContext(HttpRequest request) {
|
||||
metadataParser.setContext(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.blobstore.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||
import static org.jclouds.blobstore.util.BlobStoreUtils.getKeyFor;
|
||||
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
|
||||
|
@ -32,6 +34,7 @@ import javax.ws.rs.core.HttpHeaders;
|
|||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
@ -47,14 +50,18 @@ public class ParseSystemAndUserMetadataFromHeaders implements
|
|||
private final String metadataPrefix;
|
||||
private final DateService dateParser;
|
||||
private final Provider<MutableBlobMetadata> metadataFactory;
|
||||
private final String apiVersion;
|
||||
|
||||
private GeneratedHttpRequest<?> request;
|
||||
|
||||
@Inject
|
||||
public ParseSystemAndUserMetadataFromHeaders(Provider<MutableBlobMetadata> metadataFactory,
|
||||
DateService dateParser, @Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
|
||||
DateService dateParser, @Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix,
|
||||
@Named(PROPERTY_API_VERSION) String apiVersion) {
|
||||
this.metadataFactory = metadataFactory;
|
||||
this.dateParser = dateParser;
|
||||
this.metadataPrefix = metadataPrefix;
|
||||
this.apiVersion = apiVersion;
|
||||
}
|
||||
|
||||
public MutableBlobMetadata apply(HttpResponse from) {
|
||||
|
@ -92,7 +99,13 @@ public class ParseSystemAndUserMetadataFromHeaders implements
|
|||
if (lastModified == null)
|
||||
throw new HttpException(HttpHeaders.LAST_MODIFIED + " header not present in response: "
|
||||
+ from.getStatusLine());
|
||||
metadata.setLastModified(dateParser.rfc822DateParse(lastModified));
|
||||
// Eucalyptus 1.6 returns iso8601 dates
|
||||
if (apiVersion.indexOf("Walrus-1.6") != -1) {
|
||||
metadata.setLastModified(dateParser.iso8601DateParse(lastModified.replace("+0000", "Z")));
|
||||
} else {
|
||||
metadata.setLastModified(dateParser.rfc822DateParse(lastModified));
|
||||
}
|
||||
|
||||
if (metadata.getLastModified() == null)
|
||||
throw new HttpException("could not parse: " + HttpHeaders.LAST_MODIFIED + ": "
|
||||
+ lastModified);
|
||||
|
@ -122,7 +135,10 @@ public class ParseSystemAndUserMetadataFromHeaders implements
|
|||
throw new HttpException(HttpHeaders.CONTENT_TYPE + " not found in headers");
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
this.request = request;
|
||||
public ParseSystemAndUserMetadataFromHeaders setContext(HttpRequest request) {
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>,
|
||||
"note this handler requires a GeneratedHttpRequest");
|
||||
this.request = (GeneratedHttpRequest<?>) request;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -58,7 +58,7 @@ public class ParseBlobMetadataFromHeadersTest {
|
|||
void setUp() {
|
||||
|
||||
parser = new ParseSystemAndUserMetadataFromHeaders(blobMetadataProvider,
|
||||
new SimpleDateFormatDateService(), "prefix");
|
||||
new SimpleDateFormatDateService(), "prefix", "default");
|
||||
|
||||
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
|
||||
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
|
||||
|
|
|
@ -487,8 +487,8 @@ public class HttpUtils {
|
|||
return formBuilder.toString();
|
||||
}
|
||||
|
||||
public void setPayloadPropertiesFromHeaders(Multimap<String, String> headers, HttpMessage request) {
|
||||
Payload payload = request.getPayload();
|
||||
public void setPayloadPropertiesFromHeaders(Multimap<String, String> headers, HttpMessage message) {
|
||||
Payload payload = message.getPayload();
|
||||
boolean chunked = any(headers.entries(), new Predicate<Entry<String, String>>() {
|
||||
@Override
|
||||
public boolean apply(Entry<String, String> input) {
|
||||
|
@ -508,32 +508,32 @@ public class HttpUtils {
|
|||
if (payload != null)
|
||||
payload.setContentType(header.getValue());
|
||||
} else {
|
||||
request.getHeaders().put(header.getKey(), header.getValue());
|
||||
message.getHeaders().put(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
String contentRange = request.getFirstHeaderOrNull("Content-Range");
|
||||
if (contentRange != null) {
|
||||
payload.setContentLength(Long.parseLong(contentRange.substring(0, contentRange
|
||||
.lastIndexOf('/'))));
|
||||
if (message instanceof HttpRequest) {
|
||||
checkArgument(
|
||||
message.getPayload() == null
|
||||
|| message.getFirstHeaderOrNull(CONTENT_TYPE) == null,
|
||||
"configuration error please use request.getPayload().setContentType(value) as opposed to adding a content type header: "
|
||||
+ message);
|
||||
checkArgument(
|
||||
message.getPayload() == null
|
||||
|| message.getFirstHeaderOrNull(CONTENT_LENGTH) == null,
|
||||
"configuration error please use request.getPayload().setContentLength(value) as opposed to adding a content length header: "
|
||||
+ message);
|
||||
checkArgument(message.getPayload() == null
|
||||
|| message.getPayload().getContentLength() != null
|
||||
|| "chunked".equalsIgnoreCase(message.getFirstHeaderOrNull("Transfer-Encoding")),
|
||||
"either chunked encoding must be set on the http request or contentlength set on the payload: "
|
||||
+ message);
|
||||
checkArgument(
|
||||
message.getPayload() == null
|
||||
|| message.getFirstHeaderOrNull("Content-MD5") == null,
|
||||
"configuration error please use request.getPayload().setContentMD5(value) as opposed to adding a content md5 header: "
|
||||
+ message);
|
||||
}
|
||||
|
||||
checkArgument(
|
||||
request.getPayload() == null || request.getFirstHeaderOrNull(CONTENT_TYPE) == null,
|
||||
"configuration error please use request.getPayload().setContentType(value) as opposed to adding a content type header: "
|
||||
+ request);
|
||||
checkArgument(
|
||||
request.getPayload() == null || request.getFirstHeaderOrNull(CONTENT_LENGTH) == null,
|
||||
"configuration error please use request.getPayload().setContentLength(value) as opposed to adding a content length header: "
|
||||
+ request);
|
||||
checkArgument(request.getPayload() == null || request.getPayload().getContentLength() != null
|
||||
|| "chunked".equalsIgnoreCase(request.getFirstHeaderOrNull("Transfer-Encoding")),
|
||||
"either chunked encoding must be set on the http request or contentlength set on the payload: "
|
||||
+ request);
|
||||
checkArgument(
|
||||
request.getPayload() == null || request.getFirstHeaderOrNull("Content-MD5") == null,
|
||||
"configuration error please use request.getPayload().setContentMD5(value) as opposed to adding a content md5 header: "
|
||||
+ request);
|
||||
}
|
||||
|
||||
public static void releasePayload(HttpResponse from) {
|
||||
|
|
|
@ -22,10 +22,10 @@ import static org.jclouds.http.HttpUtils.releasePayload;
|
|||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
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 com.google.common.base.Function;
|
||||
|
||||
|
@ -38,16 +38,16 @@ public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]
|
|||
public static class NoContentMD5Exception extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final GeneratedHttpRequest<?> request;
|
||||
private final HttpRequest request;
|
||||
private final HttpResponse response;
|
||||
|
||||
public NoContentMD5Exception(GeneratedHttpRequest<?> request, HttpResponse response) {
|
||||
public NoContentMD5Exception(HttpRequest request, HttpResponse response) {
|
||||
super(String.format("no MD5 returned from request: %s; response %s", request, response));
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public GeneratedHttpRequest<?> getRequest() {
|
||||
public HttpRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]
|
|||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
private GeneratedHttpRequest<?> request;
|
||||
private HttpRequest request;
|
||||
|
||||
public byte[] apply(HttpResponse from) {
|
||||
releasePayload(from);
|
||||
|
@ -69,8 +69,10 @@ public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]
|
|||
throw new NoContentMD5Exception(request, from);
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseContentMD5FromHeaders setContext(HttpRequest request) {
|
||||
this.request = request;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,40 +18,43 @@
|
|||
*/
|
||||
package org.jclouds.http.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
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.HttpException;
|
||||
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;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.io.Closeables;
|
||||
|
||||
/**
|
||||
* This object will parse the body of an HttpResponse and return the result of
|
||||
* type <T> back to the caller.
|
||||
* This object will parse the body of an HttpResponse and return the result of type <T> back to the
|
||||
* caller.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ParseSax<T> implements Function<HttpResponse, T>,
|
||||
InvocationContext {
|
||||
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 GeneratedHttpRequest<?> request;
|
||||
private HttpRequest request;
|
||||
|
||||
public static interface Factory {
|
||||
<T> ParseSax<T> create(HandlerWithResult<T> handler);
|
||||
|
@ -63,34 +66,67 @@ public class ParseSax<T> implements Function<HttpResponse, T>,
|
|||
this.handler = checkNotNull(handler, "handler");
|
||||
}
|
||||
|
||||
public T apply(HttpResponse from) throws HttpException {
|
||||
public T apply(HttpResponse from) {
|
||||
try {
|
||||
checkNotNull(from, "http response");
|
||||
checkNotNull(from.getPayload(), "payload in " + from);
|
||||
} catch (NullPointerException e) {
|
||||
return addRequestDetailsToException(e);
|
||||
}
|
||||
if (from.getStatusCode() >= 300)
|
||||
return convertStreamToStringAndParse(from);
|
||||
return parse(from.getPayload().getInput());
|
||||
}
|
||||
|
||||
public T parse(InputStream from) throws HttpException {
|
||||
if (from == null)
|
||||
throw new HttpException("No input to parse");
|
||||
private T convertStreamToStringAndParse(HttpResponse from) {
|
||||
try {
|
||||
return parse(Utils.toStringAndClose(from.getPayload().getInput()));
|
||||
} catch (Exception e) {
|
||||
return addRequestDetailsToException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public T parse(String from) {
|
||||
try {
|
||||
checkNotNull(from, "xml string");
|
||||
checkArgument(from.indexOf('<') >= 0, String.format("not an xml document [%s] ",from));
|
||||
} catch (RuntimeException e) {
|
||||
return addRequestDetailsToException(e);
|
||||
}
|
||||
return parse(new InputSource(new StringReader(from)));
|
||||
}
|
||||
|
||||
public T parse(InputStream from) {
|
||||
try {
|
||||
return parse(new InputSource(from));
|
||||
} finally {
|
||||
closeQuietly(from);
|
||||
}
|
||||
}
|
||||
|
||||
public T parse(InputSource from) {
|
||||
try {
|
||||
checkNotNull(from, "xml inputsource");
|
||||
parser.setContentHandler(getHandler());
|
||||
// This method should accept documents with a BOM (Byte-order mark)
|
||||
parser.parse(new InputSource(from));
|
||||
parser.parse(from);
|
||||
return getHandler().getResult();
|
||||
} catch (Exception e) {
|
||||
if (request != null) {
|
||||
return addRequestDetailsToException(e);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append("Error parsing input for ").append(
|
||||
request.getRequestLine()).append(": ");
|
||||
message.append(e.getMessage());
|
||||
logger.error(e, message.toString());
|
||||
throw new HttpException(message.toString(), e);
|
||||
} else {
|
||||
Throwables.propagate(e);
|
||||
assert false : "should have propagated: " + e;
|
||||
return null;
|
||||
}
|
||||
} finally {
|
||||
Closeables.closeQuietly(from);
|
||||
private T addRequestDetailsToException(Exception e) {
|
||||
if (request != null) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append("Error parsing input for ").append(request.getRequestLine()).append(": ");
|
||||
message.append(e.getMessage());
|
||||
logger.error(e, message.toString());
|
||||
throw new HttpException(message.toString(), e);
|
||||
} else {
|
||||
propagate(e);
|
||||
assert false : "should have propagated: " + e;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,26 +135,38 @@ public class ParseSax<T> implements Function<HttpResponse, T>,
|
|||
}
|
||||
|
||||
/**
|
||||
* Handler that produces a useable domain object accessible after parsing
|
||||
* completes.
|
||||
* Handler that produces a useable domain object accessible after parsing completes.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public abstract static class HandlerWithResult<T> extends DefaultHandler
|
||||
implements InvocationContext {
|
||||
protected GeneratedHttpRequest<?> request;
|
||||
public abstract static class HandlerWithResult<T> extends DefaultHandler implements
|
||||
InvocationContext {
|
||||
protected HttpRequest request;
|
||||
|
||||
public abstract T getResult();
|
||||
|
||||
@Override
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
public HandlerWithResult<T> setContext(HttpRequest request) {
|
||||
this.request = request;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class HandlerForGeneratedRequestWithResult<T> extends
|
||||
HandlerWithResult<T> {
|
||||
@Override
|
||||
public HandlerForGeneratedRequestWithResult<T> setContext(HttpRequest request) {
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>,
|
||||
"note this handler requires a GeneratedHttpRequest");
|
||||
super.setContext(request);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
public ParseSax<T> setContext(HttpRequest request) {
|
||||
handler.setContext(request);
|
||||
this.request = request;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,10 +30,10 @@ import javax.ws.rs.core.HttpHeaders;
|
|||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.util.Utils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
@ -52,7 +52,7 @@ public class ParseURIFromListOrLocationHeaderIf20x implements Function<HttpRespo
|
|||
this.uriBuilderProvider = uriBuilderProvider;
|
||||
}
|
||||
|
||||
private GeneratedHttpRequest<?> request;
|
||||
private HttpRequest request;
|
||||
|
||||
public URI apply(HttpResponse from) {
|
||||
if (from.getStatusCode() > 206)
|
||||
|
@ -93,7 +93,9 @@ public class ParseURIFromListOrLocationHeaderIf20x implements Function<HttpRespo
|
|||
}
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseURIFromListOrLocationHeaderIf20x setContext(HttpRequest request) {
|
||||
this.request = request;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ package org.jclouds.rest;
|
|||
|
||||
import javax.ws.rs.PathParam;
|
||||
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
|
||||
/**
|
||||
* Passes generated Http request into this object;
|
||||
|
@ -29,5 +29,5 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public interface InvocationContext {
|
||||
void setContext(GeneratedHttpRequest<?> request);
|
||||
Object setContext(HttpRequest request);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rest.binders;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.net.InternetDomainName.isValid;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.Binder;
|
||||
|
||||
import com.google.common.net.InternetDomainName;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BindAsHostPrefix implements Binder {
|
||||
|
||||
private final Provider<UriBuilder> uriBuilderProvider;
|
||||
|
||||
@Inject
|
||||
public BindAsHostPrefix(Provider<UriBuilder> uriBuilderProvider) {
|
||||
this.uriBuilderProvider = uriBuilderProvider;
|
||||
}
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
checkNotNull(payload, "hostprefix");
|
||||
checkArgument(isValid(request.getEndpoint().getHost()), "this is only valid for hostnames: "
|
||||
+ request);
|
||||
UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint());
|
||||
InternetDomainName name = InternetDomainName.from(request.getEndpoint().getHost()).child(
|
||||
payload.toString());
|
||||
builder.host(name.name());
|
||||
request.setEndpoint(builder.build());
|
||||
}
|
||||
}
|
|
@ -19,7 +19,6 @@
|
|||
package org.jclouds.rest.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.collect.Collections2.filter;
|
||||
import static com.google.common.collect.Collections2.transform;
|
||||
import static com.google.common.collect.Iterables.concat;
|
||||
|
@ -100,7 +99,6 @@ import org.jclouds.rest.annotations.EndpointParam;
|
|||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.FormParams;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.HostPrefixParam;
|
||||
import org.jclouds.rest.annotations.MapBinder;
|
||||
import org.jclouds.rest.annotations.MapPayloadParam;
|
||||
import org.jclouds.rest.annotations.MatrixParams;
|
||||
|
@ -150,7 +148,6 @@ public class RestAnnotationProcessor<T> {
|
|||
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToDecoratorParamAnnotation = createMethodToIndexOfParamToAnnotation(BinderParam.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToHeaderParamAnnotations = createMethodToIndexOfParamToAnnotation(HeaderParam.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToHostPrefixParamAnnotations = createMethodToIndexOfParamToAnnotation(HostPrefixParam.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointAnnotations = createMethodToIndexOfParamToAnnotation(Endpoint.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointParamAnnotations = createMethodToIndexOfParamToAnnotation(EndpointParam.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToMatrixParamAnnotations = createMethodToIndexOfParamToAnnotation(MatrixParam.class);
|
||||
|
@ -299,7 +296,6 @@ public class RestAnnotationProcessor<T> {
|
|||
for (int index = 0; index < method.getParameterTypes().length; index++) {
|
||||
methodToIndexOfParamToDecoratorParamAnnotation.get(method).get(index);
|
||||
methodToIndexOfParamToHeaderParamAnnotations.get(method).get(index);
|
||||
methodToIndexOfParamToHostPrefixParamAnnotations.get(method).get(index);
|
||||
methodToIndexOfParamToMatrixParamAnnotations.get(method).get(index);
|
||||
methodToIndexOfParamToFormParamAnnotations.get(method).get(index);
|
||||
methodToIndexOfParamToQueryParamAnnotations.get(method).get(index);
|
||||
|
@ -385,7 +381,7 @@ public class RestAnnotationProcessor<T> {
|
|||
}
|
||||
String httpMethod = getHttpMethodOrConstantOrThrowException(method);
|
||||
|
||||
UriBuilder builder = addHostPrefixIfPresent(endpoint, method, args);
|
||||
UriBuilder builder = uriBuilderProvider.get().uri(endpoint);
|
||||
|
||||
Multimap<String, String> tokenValues = LinkedHashMultimap.create();
|
||||
|
||||
|
@ -631,26 +627,6 @@ public class RestAnnotationProcessor<T> {
|
|||
return null;
|
||||
}
|
||||
|
||||
private UriBuilder addHostPrefixIfPresent(URI endpoint, Method method, Object... args) {
|
||||
Map<Integer, Set<Annotation>> map = indexWithOnlyOneAnnotation(method, "@HostPrefixParam",
|
||||
methodToIndexOfParamToHostPrefixParamAnnotations);
|
||||
UriBuilder builder = uriBuilderProvider.get().uri(endpoint);
|
||||
if (map.size() == 1) {
|
||||
HostPrefixParam param = (HostPrefixParam) map.values().iterator().next().iterator().next();
|
||||
int index = map.keySet().iterator().next();
|
||||
|
||||
String prefix = checkNotNull(args[index],
|
||||
String.format("argument at index %d on method %s", index, method)).toString();
|
||||
checkArgument(!prefix.equals(""), String.format(
|
||||
"argument at index %d must be a valid hostname for method %s", index, method));
|
||||
String joinOn = param.value();
|
||||
String host = endpoint.getHost();
|
||||
|
||||
builder.host(prefix + joinOn + host);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static final TypeLiteral<ListenableFuture<Boolean>> futureBooleanLiteral = new TypeLiteral<ListenableFuture<Boolean>>() {
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.jclouds.rest;
|
|||
import static org.jclouds.rest.RestContextFactory.createContextBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
|
@ -60,10 +61,13 @@ public abstract class RestClientTest<T> extends BaseRestClientTest {
|
|||
protected void setupFactory() throws IOException {
|
||||
ContextSpec<?, ?> contextSpec = createContextSpec();
|
||||
injector = createContextBuilder(contextSpec,
|
||||
ImmutableSet.of(new MockModule(), new NullLoggingModule(), createModule()))
|
||||
.buildInjector();
|
||||
ImmutableSet.of(new MockModule(), new NullLoggingModule(), createModule()),
|
||||
getProperties()).buildInjector();
|
||||
parserFactory = injector.getInstance(ParseSax.Factory.class);
|
||||
processor = injector.getInstance(Key.get(createTypeLiteral()));
|
||||
}
|
||||
|
||||
protected Properties getProperties() {
|
||||
return new Properties();
|
||||
}
|
||||
}
|
|
@ -109,7 +109,6 @@ import org.jclouds.rest.annotations.Endpoint;
|
|||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
import org.jclouds.rest.annotations.FormParams;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.HostPrefixParam;
|
||||
import org.jclouds.rest.annotations.MapBinder;
|
||||
import org.jclouds.rest.annotations.MapPayloadParam;
|
||||
import org.jclouds.rest.annotations.MatrixParams;
|
||||
|
@ -121,6 +120,7 @@ import org.jclouds.rest.annotations.RequestFilters;
|
|||
import org.jclouds.rest.annotations.ResponseParser;
|
||||
import org.jclouds.rest.annotations.SkipEncoding;
|
||||
import org.jclouds.rest.annotations.VirtualHost;
|
||||
import org.jclouds.rest.binders.BindAsHostPrefix;
|
||||
import org.jclouds.rest.binders.BindMapToMatrixParams;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
import org.jclouds.rest.binders.BindToStringPayload;
|
||||
|
@ -1494,8 +1494,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
|
||||
public HttpRequest request;
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
public ReturnStringIf200Context setContext(HttpRequest request) {
|
||||
this.request = request;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1723,27 +1724,17 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
.singletonList("localhost"));
|
||||
}
|
||||
|
||||
public class TestVirtualHost {
|
||||
public interface TestVirtualHost {
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
@VirtualHost
|
||||
public ListenableFuture<String> get(@PathParam("id") String id, String foo) {
|
||||
return null;
|
||||
}
|
||||
ListenableFuture<String> get(@PathParam("id") String id, String foo);
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
public ListenableFuture<String> getPrefix(@PathParam("id") String id,
|
||||
@HostPrefixParam("") String foo) {
|
||||
return null;
|
||||
}
|
||||
ListenableFuture<String> getPrefix(@PathParam("id") String id,
|
||||
@BinderParam(BindAsHostPrefix.class) String foo);
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
public ListenableFuture<String> getPrefixDot(@PathParam("id") String id,
|
||||
@HostPrefixParam String foo) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1762,17 +1753,6 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
@Test
|
||||
public void testHostPrefix() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestVirtualHost.class.getMethod("getPrefix", String.class, String.class);
|
||||
HttpRequest request = factory(TestVirtualHost.class).createRequest(method,
|
||||
new Object[] { "1", "holy" });
|
||||
assertEquals(request.getEndpoint().getHost(), "holylocalhost");
|
||||
assertEquals(request.getEndpoint().getPath(), "/1");
|
||||
assertEquals(request.getMethod(), HttpMethod.GET);
|
||||
assertEquals(request.getHeaders().size(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHostPrefixDot() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestVirtualHost.class.getMethod("getPrefixDot", String.class, String.class);
|
||||
HttpRequest request = factory(TestVirtualHost.class).createRequest(method,
|
||||
new Object[] { "1", "holy" });
|
||||
assertEquals(request.getEndpoint().getHost(), "holy.localhost");
|
||||
|
@ -1782,15 +1762,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testHostPrefixDotEmpty() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestVirtualHost.class.getMethod("getPrefixDot", String.class, String.class);
|
||||
factory(TestVirtualHost.class).createRequest(method, new Object[] { "1", "" });
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testHostPrefixDotNull() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestVirtualHost.class.getMethod("getPrefixDot", String.class, String.class);
|
||||
factory(TestVirtualHost.class).createRequest(method, new Object[] { "1", null });
|
||||
public void testHostPrefixEmpty() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestVirtualHost.class.getMethod("getPrefix", String.class, String.class);
|
||||
factory(TestVirtualHost.class).createRequest(method, "1", "");
|
||||
}
|
||||
|
||||
public class TestHeaders {
|
||||
|
|
|
@ -18,12 +18,14 @@
|
|||
*/
|
||||
package org.jclouds.mezeo.pcs2.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.functions.ReturnStringIf200;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
|
@ -64,8 +66,12 @@ public class AddMetadataItemIntoMap implements Function<HttpResponse, Void>, Inv
|
|||
return null;
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
this.request = request;
|
||||
@Override
|
||||
public AddMetadataItemIntoMap setContext(HttpRequest request) {
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>,
|
||||
"note this handler requires a GeneratedHttpRequest");
|
||||
this.request = (GeneratedHttpRequest<?>) request;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -22,12 +22,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ContainerCDNMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.reference.CloudFilesHeaders;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -39,7 +39,7 @@ import com.google.common.base.Function;
|
|||
public class ParseContainerCDNMetadataFromHeaders implements
|
||||
Function<HttpResponse, ContainerCDNMetadata>, InvocationContext {
|
||||
|
||||
private GeneratedHttpRequest<?> request;
|
||||
private HttpRequest request;
|
||||
|
||||
/**
|
||||
* parses the http response headers to create a new {@link ContainerCDNMetadata} object.
|
||||
|
@ -60,7 +60,9 @@ public class ParseContainerCDNMetadataFromHeaders implements
|
|||
}
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseContainerCDNMetadataFromHeaders setContext(HttpRequest request) {
|
||||
this.request = request;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -20,11 +20,11 @@ package org.jclouds.rackspace.cloudfiles.functions;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -57,8 +57,9 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
|
|||
return object;
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseObjectFromHeadersAndHttpContent setContext(HttpRequest request) {
|
||||
infoParser.setContext(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -25,11 +25,11 @@ import javax.inject.Inject;
|
|||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ResourceToObjectInfo;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.util.Utils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
@ -68,8 +68,10 @@ public class ParseObjectInfoFromHeaders implements
|
|||
return to;
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
@Override
|
||||
public ParseObjectInfoFromHeaders setContext(HttpRequest request) {
|
||||
blobMetadataParser.setContext(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -33,6 +33,7 @@ import javax.inject.Inject;
|
|||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.ParseJson;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
|
||||
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
|
||||
|
@ -180,7 +181,11 @@ public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<Objec
|
|||
}
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
this.request = request;
|
||||
@Override
|
||||
public ParseObjectInfoListFromJsonResponse setContext(HttpRequest request) {
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>,
|
||||
"note this handler requires a GeneratedHttpRequest");
|
||||
this.request = (GeneratedHttpRequest<?>) request;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import static org.testng.Assert.assertNotNull;
|
|||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.blobstore.reference.BlobStoreConstants;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.Payloads;
|
||||
|
@ -52,6 +53,7 @@ public class ParseObjectInfoFromHeadersTest {
|
|||
bindConstant()
|
||||
.annotatedWith(Names.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to(
|
||||
"sdf");
|
||||
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_API_VERSION)).to("1");
|
||||
}
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue