source: josm/trunk/src/oauth/signpost/http/HttpParameters.java@ 16334

Last change on this file since 16334 was 10831, checked in by Don-vip, 8 years ago

see #13232 - cleanup OAuth signpost code:

  • remove classes unused by JOSM
  • add missing @Override annotations
File size: 9.4 KB
Line 
1/* Copyright (c) 2008, 2009 Netflix, Matthias Kaeppler
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15package oauth.signpost.http;
16
17import java.io.Serializable;
18import java.util.Collection;
19import java.util.Iterator;
20import java.util.List;
21import java.util.Map;
22import java.util.Set;
23import java.util.SortedSet;
24import java.util.TreeMap;
25import java.util.TreeSet;
26
27import oauth.signpost.OAuth;
28
29/**
30 * A multi-map of HTTP request parameters. Each key references a
31 * {@link SortedSet} of parameters collected from the request during message
32 * signing. Parameter values are sorted as per {@linkplain http://oauth.net/core/1.0a/#anchor13}.
33 * Every key/value pair will be percent-encoded upon insertion.
34 * This class has special semantics tailored to being useful for message signing;
35 * it's not a general purpose collection class to handle request parameters.
36 *
37 * @author Matthias Kaeppler
38 */
39@SuppressWarnings("serial")
40public class HttpParameters implements Map<String, SortedSet<String>>, Serializable {
41
42 private TreeMap<String, SortedSet<String>> wrappedMap = new TreeMap<>();
43
44 @Override
45 public SortedSet<String> put(String key, SortedSet<String> value) {
46 return wrappedMap.put(key, value);
47 }
48
49 public SortedSet<String> put(String key, SortedSet<String> values, boolean percentEncode) {
50 if (percentEncode) {
51 remove(key);
52 for (String v : values) {
53 put(key, v, true);
54 }
55 return get(key);
56 } else {
57 return wrappedMap.put(key, values);
58 }
59 }
60
61 /**
62 * Convenience method to add a single value for the parameter specified by
63 * 'key'.
64 *
65 * @param key
66 * the parameter name
67 * @param value
68 * the parameter value
69 * @return the value
70 */
71 public String put(String key, String value) {
72 return put(key, value, false);
73 }
74
75 /**
76 * Convenience method to add a single value for the parameter specified by
77 * 'key'.
78 *
79 * @param key
80 * the parameter name
81 * @param value
82 * the parameter value
83 * @param percentEncode
84 * whether key and value should be percent encoded before being
85 * inserted into the map
86 * @return the value
87 */
88 public String put(String key, String value, boolean percentEncode) {
89 // fix contributed by Bjorn Roche - key should be encoded before wrappedMap.get
90 key = percentEncode ? OAuth.percentEncode(key) : key;
91 SortedSet<String> values = wrappedMap.get(key);
92 if (values == null) {
93 values = new TreeSet<>();
94 wrappedMap.put( key, values);
95 }
96 if (value != null) {
97 value = percentEncode ? OAuth.percentEncode(value) : value;
98 values.add(value);
99 }
100
101 return value;
102 }
103
104 /**
105 * Convenience method to allow for storing null values. {@link #put} doesn't
106 * allow null values, because that would be ambiguous.
107 *
108 * @param key
109 * the parameter name
110 * @param nullString
111 * can be anything, but probably... null?
112 * @return null
113 */
114 public String putNull(String key, String nullString) {
115 return put(key, nullString);
116 }
117
118 @Override
119 public void putAll(Map<? extends String, ? extends SortedSet<String>> m) {
120 wrappedMap.putAll(m);
121 }
122
123 public void putAll(Map<? extends String, ? extends SortedSet<String>> m, boolean percentEncode) {
124 if (percentEncode) {
125 for (String key : m.keySet()) {
126 put(key, m.get(key), true);
127 }
128 } else {
129 wrappedMap.putAll(m);
130 }
131 }
132
133 public void putAll(String[] keyValuePairs, boolean percentEncode) {
134 for (int i = 0; i < keyValuePairs.length - 1; i += 2) {
135 this.put(keyValuePairs[i], keyValuePairs[i + 1], percentEncode);
136 }
137 }
138
139 /**
140 * Convenience method to merge a Map<String, List<String>>.
141 *
142 * @param m
143 * the map
144 */
145 public void putMap(Map<String, List<String>> m) {
146 for (String key : m.keySet()) {
147 SortedSet<String> vals = get(key);
148 if (vals == null) {
149 vals = new TreeSet<>();
150 put(key, vals);
151 }
152 vals.addAll(m.get(key));
153 }
154 }
155
156 @Override
157 public SortedSet<String> get(Object key) {
158 return wrappedMap.get(key);
159 }
160
161 /**
162 * Convenience method for {@link #getFirst(key, false)}.
163 *
164 * @param key
165 * the parameter name (must be percent encoded if it contains unsafe
166 * characters!)
167 * @return the first value found for this parameter
168 */
169 public String getFirst(Object key) {
170 return getFirst(key, false);
171 }
172
173 /**
174 * Returns the first value from the set of all values for the given
175 * parameter name. If the key passed to this method contains special
176 * characters, you MUST first percent encode it using
177 * {@link OAuth#percentEncode(String)}, otherwise the lookup will fail
178 * (that's because upon storing values in this map, keys get
179 * percent-encoded).
180 *
181 * @param key
182 * the parameter name (must be percent encoded if it contains unsafe
183 * characters!)
184 * @param percentDecode
185 * whether the value being retrieved should be percent decoded
186 * @return the first value found for this parameter
187 */
188 public String getFirst(Object key, boolean percentDecode) {
189 SortedSet<String> values = wrappedMap.get(key);
190 if (values == null || values.isEmpty()) {
191 return null;
192 }
193 String value = values.first();
194 return percentDecode ? OAuth.percentDecode(value) : value;
195 }
196
197 /**
198 * Concatenates all values for the given key to a list of key/value pairs
199 * suitable for use in a URL query string.
200 *
201 * @param key
202 * the parameter name
203 * @return the query string
204 */
205 public String getAsQueryString(Object key) {
206 return getAsQueryString(key, true);
207 }
208
209 /**
210 * Concatenates all values for the given key to a list of key/value pairs
211 * suitable for use in a URL query string.
212 *
213 * @param key
214 * the parameter name
215 * @param percentEncode
216 * whether key should be percent encoded before being
217 * used with the map
218 * @return the query string
219 */
220 public String getAsQueryString(Object key, boolean percentEncode) {
221 // fix contributed by Stjepan Rajko - we need the percentEncode parameter
222 // because some places (like SignatureBaseString.normalizeRequestParameters)
223 // need to supply the parameter percent encoded
224
225 StringBuilder sb = new StringBuilder();
226 if(percentEncode)
227 key = OAuth.percentEncode((String) key);
228 Set<String> values = wrappedMap.get(key);
229 if (values == null) {
230 return key + "=";
231 }
232 Iterator<String> iter = values.iterator();
233 while (iter.hasNext()) {
234 sb.append(key + "=" + iter.next());
235 if (iter.hasNext()) {
236 sb.append("&");
237 }
238 }
239 return sb.toString();
240 }
241
242 public String getAsHeaderElement(String key) {
243 String value = getFirst(key);
244 if (value == null) {
245 return null;
246 }
247 return key + "=\"" + value + "\"";
248 }
249
250 @Override
251 public boolean containsKey(Object key) {
252 return wrappedMap.containsKey(key);
253 }
254
255 @Override
256 public boolean containsValue(Object value) {
257 for (Set<String> values : wrappedMap.values()) {
258 if (values.contains(value)) {
259 return true;
260 }
261 }
262 return false;
263 }
264
265 @Override
266 public int size() {
267 int count = 0;
268 for (String key : wrappedMap.keySet()) {
269 count += wrappedMap.get(key).size();
270 }
271 return count;
272 }
273
274 @Override
275 public boolean isEmpty() {
276 return wrappedMap.isEmpty();
277 }
278
279 @Override
280 public void clear() {
281 wrappedMap.clear();
282 }
283
284 @Override
285 public SortedSet<String> remove(Object key) {
286 return wrappedMap.remove(key);
287 }
288
289 @Override
290 public Set<String> keySet() {
291 return wrappedMap.keySet();
292 }
293
294 @Override
295 public Collection<SortedSet<String>> values() {
296 return wrappedMap.values();
297 }
298
299 @Override
300 public Set<Entry<String, SortedSet<String>>> entrySet() {
301 return wrappedMap.entrySet();
302 }
303
304 public HttpParameters getOAuthParameters() {
305 HttpParameters oauthParams = new HttpParameters();
306
307 for (Entry<String, SortedSet<String>> param : this.entrySet()) {
308 String key = param.getKey();
309 if (key.startsWith("oauth_") || key.startsWith("x_oauth_")) {
310 oauthParams.put(key, param.getValue());
311 }
312 }
313
314 return oauthParams;
315 }
316}
Note: See TracBrowser for help on using the repository browser.