View Javadoc

1   /**
2    * Licensed to jclouds, Inc. (jclouds) under one or more
3    * contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  jclouds licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.jclouds.http.utils;
20  
21  import static com.google.common.base.Preconditions.checkNotNull;
22  import static org.jclouds.io.Payloads.newUrlEncodedFormPayload;
23  
24  import java.net.URI;
25  import java.util.Comparator;
26  import java.util.Iterator;
27  import java.util.Map;
28  
29  import org.jclouds.javax.annotation.Nullable;
30  import javax.ws.rs.core.UriBuilder;
31  
32  import org.jclouds.http.HttpRequest;
33  import org.jclouds.util.Strings2;
34  
35  import com.google.common.collect.ImmutableList;
36  import com.google.common.collect.ImmutableMultimap;
37  import com.google.common.collect.ImmutableSet;
38  import com.google.common.collect.ImmutableSortedSet;
39  import com.google.common.collect.LinkedHashMultimap;
40  import com.google.common.collect.LinkedListMultimap;
41  import com.google.common.collect.Multimap;
42  
43  /**
44   * 
45   * @author Adrian Cole
46   */
47  public class ModifyRequest {
48     @SuppressWarnings("unchecked")
49     public static <R extends HttpRequest> R putHeaders(R request, Multimap<String, String> moreHeaders) {
50        return (R) request.toBuilder().headers(
51                 ImmutableMultimap.<String, String> builder().putAll(request.getHeaders()).putAll(moreHeaders).build())
52                 .build();
53     }
54  
55     @SuppressWarnings("unchecked")
56     public static <R extends HttpRequest> R endpoint(R request, URI endpoint) {
57        return (R) checkNotNull(request, "request").toBuilder().endpoint(checkNotNull(endpoint, "endpoint")).build();
58     }
59  
60     @SuppressWarnings("unchecked")
61     public static <R extends HttpRequest> R replaceHeaders(R request, Multimap<String, String> headers) {
62        Multimap<String, String> newHeaders = LinkedHashMultimap.create(checkNotNull(request, "request").getHeaders());
63        for (String header : headers.keySet())
64           newHeaders.replaceValues(header, headers.get(header));
65        return (R) request.toBuilder().headers(newHeaders).build();
66     }
67  
68     public static <R extends HttpRequest> R replaceHeader(R request, String header, String... values) {
69        return replaceHeader(request, header, ImmutableList.copyOf(checkNotNull(values, "values")));
70     }
71  
72     @SuppressWarnings("unchecked")
73     public static <R extends HttpRequest> R replaceHeader(R request, String header, Iterable<String> values) {
74        Multimap<String, String> headers = LinkedHashMultimap.create(checkNotNull(request, "request").getHeaders());
75        headers.replaceValues(checkNotNull(header, "header"), checkNotNull(values, "values"));
76        return (R) request.toBuilder().headers(headers).build();
77     }
78  
79     @SuppressWarnings("unchecked")
80     public static <R extends HttpRequest> R removeHeader(R request, String header) {
81        Multimap<String, String> headers = LinkedHashMultimap.create(checkNotNull(request, "request").getHeaders());
82        headers.removeAll(checkNotNull(header, "header"));
83        return (R) request.toBuilder().headers(headers).build();
84     }
85  
86     public static <R extends HttpRequest> R addQueryParam(R request, String key, Object value, UriBuilder builder) {
87        return addQueryParam(request, key, ImmutableSet.<Object> of(value), builder, request.getSkips());
88     }
89  
90     public static <R extends HttpRequest> R addQueryParam(R request, String key, Iterable<?> values, UriBuilder builder) {
91        return addQueryParam(request, key, values, builder, request.getSkips());
92     }
93  
94     @SuppressWarnings("unchecked")
95     public static <R extends HttpRequest> R addQueryParam(R request, String key, Iterable<?> values, UriBuilder builder,
96              char... skips) {
97        builder.uri(request.getEndpoint());
98        Multimap<String, String> map = parseQueryToMap(request.getEndpoint().getQuery());
99        for (Object o : values)
100          map.put(key, o.toString());
101       builder.replaceQuery(makeQueryLine(map, null, skips));
102       return (R) request.toBuilder().endpoint(builder.build()).build();
103    }
104 
105    public static <R extends HttpRequest> R replaceMatrixParam(R request, String name, Object value, UriBuilder builder) {
106       return replaceMatrixParam(request, name, new Object[] { value }, builder);
107    }
108 
109    @SuppressWarnings("unchecked")
110    public static <R extends HttpRequest> R replaceMatrixParam(R request, String name, Object[] values,
111             UriBuilder builder) {
112       builder.uri(request.getEndpoint());
113       builder.replaceMatrixParam(name, values);
114       return (R) request.toBuilder().endpoint(builder.build()).build();
115    }
116 
117    public static <R extends HttpRequest> R addFormParam(R request, String key, String value) {
118       return addFormParam(request, key, ImmutableSet.<Object> of(value));
119    }
120 
121    @SuppressWarnings("unchecked")
122    public static <R extends HttpRequest> R addFormParam(R request, String key, Iterable<?> values) {
123       Multimap<String, String> map = request.getPayload() != null ? parseQueryToMap(request.getPayload()
124                .getRawContent().toString()) : LinkedHashMultimap.<String, String> create();
125       for (Object o : values)
126          map.put(key, o.toString());
127       return (R) request.toBuilder().payload(newUrlEncodedFormPayload(map)).build();
128    }
129 
130    @SuppressWarnings("unchecked")
131    public static <R extends HttpRequest> R putFormParams(R request, Multimap<String, String> params) {
132       Multimap<String, String> map = request.getPayload() != null ? parseQueryToMap(request.getPayload()
133                .getRawContent().toString()) : LinkedHashMultimap.<String, String> create();
134       map.putAll(params);
135       return (R) request.toBuilder().payload(newUrlEncodedFormPayload(map)).build();
136    }
137 
138    public static Multimap<String, String> parseQueryToMap(String in) {
139       Multimap<String, String> map = LinkedListMultimap.create();
140       if (in == null) {
141       } else if (in.indexOf('&') == -1) {
142          if (in.contains("="))
143             parseKeyValueFromStringToMap(in, map);
144          else
145             map.put(in, null);
146       } else {
147          String[] parts = Strings2.urlDecode(in).split("&");
148          for (String part : parts) {
149             parseKeyValueFromStringToMap(part, map);
150          }
151       }
152       return map;
153    }
154 
155    public static void parseKeyValueFromStringToMap(String stringToParse, Multimap<String, String> map) {
156       // note that '=' can be a valid part of the value
157       int indexOfFirstEquals = stringToParse.indexOf('=');
158       String key = indexOfFirstEquals == -1 ? stringToParse : stringToParse.substring(0, indexOfFirstEquals);
159       String value = indexOfFirstEquals == -1 ? null : stringToParse.substring(indexOfFirstEquals + 1);
160       map.put(key, value);
161    }
162 
163    public static String makeQueryLine(Multimap<String, String> params,
164             @Nullable Comparator<Map.Entry<String, String>> sorter, char... skips) {
165       Iterator<Map.Entry<String, String>> pairs = ((sorter == null) ? params.entries() : ImmutableSortedSet.copyOf(
166                sorter, params.entries())).iterator();
167       StringBuilder formBuilder = new StringBuilder();
168       while (pairs.hasNext()) {
169          Map.Entry<String, String> pair = pairs.next();
170          formBuilder.append(Strings2.urlEncode(pair.getKey(), skips));
171          if (pair.getValue() != null)
172             formBuilder.append("=");
173          if (pair.getValue() != null && !pair.getValue().equals("")) {
174             formBuilder.append(Strings2.urlEncode(pair.getValue(), skips));
175          }
176          if (pairs.hasNext())
177             formBuilder.append("&");
178       }
179       return formBuilder.toString();
180    }
181 }