1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jclouds.aws.util;
20
21 import static com.google.common.base.Preconditions.checkArgument;
22 import static com.google.common.base.Preconditions.checkNotNull;
23 import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
24
25 import javax.annotation.Resource;
26 import javax.inject.Inject;
27 import javax.inject.Named;
28 import javax.inject.Provider;
29 import javax.inject.Singleton;
30
31 import org.jclouds.aws.domain.AWSError;
32 import org.jclouds.aws.domain.Region;
33 import org.jclouds.aws.xml.ErrorHandler;
34 import org.jclouds.domain.Location;
35 import org.jclouds.domain.LocationScope;
36 import org.jclouds.http.HttpRequest;
37 import org.jclouds.http.HttpResponse;
38 import org.jclouds.http.functions.ParseSax;
39 import org.jclouds.http.functions.ParseSax.Factory;
40 import org.jclouds.http.utils.ModifyRequest;
41 import org.jclouds.logging.Logger;
42 import org.jclouds.rest.RequestSigner;
43 import org.jclouds.rest.internal.GeneratedHttpRequest;
44
45 import com.google.common.base.Function;
46 import com.google.common.collect.ImmutableMultimap;
47 import com.google.common.collect.ImmutableMultimap.Builder;
48
49
50
51
52
53
54 @Singleton
55 public class AWSUtils {
56 @Singleton
57 public static class GetRegionFromLocation implements Function<Location, String> {
58 public String apply(Location location) {
59 String region = location.getScope() == LocationScope.REGION ? location.getId() : location.getParent().getId();
60 return region;
61 }
62 }
63
64 private final RequestSigner signer;
65 private final ParseSax.Factory factory;
66 private final Provider<ErrorHandler> errorHandlerProvider;
67 private final String requestId;
68 private final String requestToken;
69 @Resource
70 protected Logger logger = Logger.NULL;
71
72 @Inject
73 AWSUtils(@Named(PROPERTY_HEADER_TAG) String headerTag, RequestSigner signer, Factory factory,
74 Provider<ErrorHandler> errorHandlerProvider) {
75 this.signer = signer;
76 this.factory = factory;
77 this.errorHandlerProvider = errorHandlerProvider;
78 this.requestId = String.format("x-%s-request-id", headerTag);
79 this.requestToken = String.format("x-%s-id-2", headerTag);
80 }
81
82 public AWSError parseAWSErrorFromContent(HttpRequest request, HttpResponse response) {
83
84 if (response.getPayload() == null)
85 return null;
86
87 if (response.getPayload().getContentMetadata().getContentType() != null
88 && response.getPayload().getContentMetadata().getContentType().indexOf("text/plain") != -1)
89 return null;
90 try {
91 AWSError error = (AWSError) factory.create(errorHandlerProvider.get()).setContext(request).apply(response);
92 if (error.getRequestId() == null)
93 error.setRequestId(response.getFirstHeaderOrNull(requestId));
94 error.setRequestToken(response.getFirstHeaderOrNull(requestToken));
95 if ("SignatureDoesNotMatch".equals(error.getCode())) {
96 error.setStringSigned(signer.createStringToSign(request));
97 error.setSignature(signer.sign(error.getStringSigned()));
98 }
99 return error;
100 } catch (RuntimeException e) {
101 logger.warn(e, "error parsing error");
102 return null;
103 }
104 }
105
106 public static <R extends HttpRequest> R indexStringArrayToFormValuesWithStringFormat(R request, String format,
107 Object input) {
108 checkArgument(checkNotNull(input, "input") instanceof String[], "this binder is only valid for String[] : "
109 + input.getClass());
110 String[] values = (String[]) input;
111 Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
112 for (int i = 0; i < values.length; i++) {
113 builder.put(String.format(format, (i + 1)), checkNotNull(values[i], format.toLowerCase() + "s[" + i + "]"));
114 }
115 ImmutableMultimap<String, String> forms = builder.build();
116 return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms);
117 }
118
119
120 public static boolean isRegion(String regionName) {
121 return Region.DEFAULT_REGIONS.contains(regionName);
122 }
123
124 public static <R extends HttpRequest> R indexIterableToFormValuesWithPrefix(R request, String prefix, Object input) {
125 checkArgument(checkNotNull(input, "input") instanceof Iterable<?>, "this binder is only valid for Iterable<?>: "
126 + input.getClass());
127 Iterable<?> values = (Iterable<?>) input;
128 Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
129 int i = 0;
130 for (Object o : values) {
131 builder.put(prefix + "." + (i++ + 1), checkNotNull(o.toString(), prefix.toLowerCase() + "s[" + i + "]"));
132 }
133 ImmutableMultimap<String, String> forms = builder.build();
134 return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms);
135 }
136
137 public static <R extends HttpRequest> R indexStringArrayToFormValuesWithPrefix(R request, String prefix, Object input) {
138 checkArgument(checkNotNull(input, "input") instanceof String[], "this binder is only valid for String[] : "
139 + input.getClass());
140 String[] values = (String[]) input;
141 Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
142 for (int i = 0; i < values.length; i++) {
143 builder.put(prefix + "." + (i + 1), checkNotNull(values[i], prefix.toLowerCase() + "s[" + i + "]"));
144 }
145 ImmutableMultimap<String, String> forms = builder.build();
146 return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms);
147 }
148
149 public static String getRegionFromLocationOrNull(Location location) {
150 return location.getScope() == LocationScope.ZONE ? location.getParent().getId() : location.getId();
151 }
152
153
154 public static String[] parseHandle(String id) {
155 String[] parts = checkNotNull(id, "id").split("/");
156 return (parts.length == 1) ? new String[] { null, id } : parts;
157 }
158
159 public static String findRegionInArgsOrNull(GeneratedHttpRequest<?> gRequest) {
160 for (Object arg : gRequest.getArgs()) {
161 if (arg instanceof String) {
162 String regionName = (String) arg;
163
164
165 if (isRegion(regionName))
166 return regionName;
167 }
168 }
169 return null;
170 }
171 }