1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.fatwire.gst.foundation.url;
17
18 import com.fatwire.cs.core.uri.Assembler;
19 import com.fatwire.cs.core.uri.Util;
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22
23 import java.io.UnsupportedEncodingException;
24 import java.net.URI;
25 import java.net.URISyntaxException;
26 import java.util.*;
27
28
29
30
31
32
33
34
35
36
37 public abstract class LightweightAbstractAssembler implements Assembler {
38
39
40
41 protected static final Log LOG = LogFactory.getLog(LightweightAbstractAssembler.class.getName());
42
43 private static final String CHARSET_lower = "_charset_";
44 private static final String CHARSET_upper = "_CHARSET_";
45
46 private final String encoding;
47
48 private final Map<String, String> properties = new HashMap<String, String>();
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 protected LightweightAbstractAssembler() {
69 String enc = "UTF-8";
70 try {
71 Util.encode("fake string", enc);
72 } catch (UnsupportedEncodingException e) {
73 LOG.warn("UTF-8 encoding not supported by this platform. Using the platform's default encoding as the URL encoding.");
74 enc = null;
75 }
76 this.encoding = enc;
77 }
78
79 public void setProperties(Properties props) {
80 Enumeration<?> en = props.propertyNames();
81 while (en.hasMoreElements()) {
82 String pName = (String) en.nextElement();
83 String pValue = props.getProperty(pName);
84 this.properties.put(pName, pValue);
85 }
86 }
87
88
89
90
91
92
93
94
95
96
97 protected String getProperty(String name, String dephault) {
98 String result = properties.get(name);
99 if (result == null) {
100 result = dephault;
101 }
102 return result;
103 }
104
105
106
107
108
109
110
111
112
113 protected final String encode(String string) {
114 String result;
115 try {
116 if (string == null) {
117 result = null;
118 } else {
119 result = Util.encode(string, encoding);
120 }
121 } catch (UnsupportedEncodingException ex) {
122 String msg = "Unexpected failure encoding string '" + string + "'using an encoding (" + encoding
123 + "). Exception: " + ex;
124 throw new IllegalStateException(msg);
125 }
126 return result;
127 }
128
129
130
131
132
133
134
135
136
137
138
139 protected final String decode(String string) {
140 return decode(string, null);
141 }
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 protected final String decode(String string, String encoding) {
157 String result;
158 if (string == null) {
159 result = null;
160 } else {
161 if (encoding == null) {
162 encoding = this.encoding;
163 }
164 try {
165 result = Util.decode(string, encoding);
166 } catch (IllegalArgumentException iae) {
167 throw new IllegalArgumentException("Failure decoding string '" + string + "' using encoding '"
168 + encoding + "'. (" + iae.getMessage() + ")");
169 } catch (UnsupportedEncodingException ex) {
170
171 throw new IllegalStateException("Unexpected failure decoding string '" + string + "'using encoding '"
172 + encoding + "'. (" + ex + ")");
173 }
174 }
175 return result;
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 protected static final URI constructURI(final String scheme, final String authority, final String path,
203 final String quotedQueryString, final String fragment) throws URISyntaxException {
204
205 StringBuilder bf = new StringBuilder();
206 if (scheme != null) {
207 bf.append(scheme).append(':');
208 }
209 if (authority != null) {
210 bf.append("//").append(authority); // nothing legal to quote until
211
212 }
213
214
215
216
217 if (path != null) {
218 bf.append(new URI(null, null, path, null, null).getRawPath());
219 }
220 if (quotedQueryString != null) {
221 bf.append('?').append(quotedQueryString);
222 }
223
224 if (fragment != null) {
225 bf.append(new URI(null, null, null, null, fragment).toASCIIString());
226 }
227 URI uri = new URI(bf.toString());
228
229 if (LOG.isDebugEnabled()) {
230 LOG.trace("Constructing new URI using the following components: \n" + "scheme=" + scheme + " \n"
231 + "authority=" + authority + " \n" + "path=" + path + " \n" + "query=" + quotedQueryString + " \n"
232 + "fragment=" + fragment);
233
234 LOG.debug("Assembled URI: " + uri.toASCIIString());
235 }
236 return uri;
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 protected final Map<String, String[]> parseQueryString(String qry) {
256 Map<String, String[]> rawPairs = new HashMap<String, String[]>();
257 if (qry == null) {
258 return rawPairs;
259 }
260 int inlen = qry.length();
261 if (inlen == 0) {
262 return rawPairs;
263 }
264
265 if (LOG.isTraceEnabled()) {
266 LOG.trace("Parsing query string: " + qry);
267 }
268
269 int iequal;
270 int iamper;
271 int startAt = 0;
272 boolean bDone = false;
273
274 while (!bDone) {
275 String n;
276 String v;
277 if ((iequal = qry.indexOf("=", startAt)) != -1) {
278
279 iamper = qry.indexOf("&", iequal);
280 n = qry.substring(startAt, iequal);
281 n = n.trim();
282 iequal++;
283 if (iequal >= inlen) {
284 break;
285 }
286
287 if (iamper == -1) {
288 v = qry.substring(iequal);
289 } else {
290 v = qry.substring(iequal, iamper);
291 }
292
293 if (iamper != -1) {
294 startAt = iamper + 1;
295 } else {
296 bDone = true;
297 }
298
299 v = v.trim();
300
301
302 String[] av = rawPairs.get(n);
303 if (av == null) {
304 av = new String[1];
305 av[0] = v;
306 rawPairs.put(n, av);
307 } else {
308
309 String[] newVal = new String[av.length + 1];
310 System.arraycopy(av, 0, newVal, 0, av.length);
311 newVal[av.length] = v;
312 rawPairs.put(n, newVal);
313 }
314 } else {
315 break;
316 }
317 }
318
319
320 String[] _charset_ = rawPairs.get(CHARSET_lower) == null ? rawPairs.get(CHARSET_upper) : rawPairs
321 .get(CHARSET_lower);
322 final String encoding;
323 if (_charset_ == null) {
324 encoding = null;
325 } else {
326 switch (_charset_.length) {
327 case 0:
328 throw new IllegalStateException(
329 "Somehow an empty _charst_ param made it into our map. Impossible...");
330 case 1:
331 encoding = _charset_[0];
332
333 break;
334 default:
335 throw new IllegalStateException("Too many values of _charset_ found in the URL");
336 }
337 }
338
339
340
341 Map<String, String[]> res = new HashMap<String, String[]>(rawPairs.size());
342 for (String rawKey : rawPairs.keySet()) {
343 String key = decode(rawKey, encoding);
344 String[] val = rawPairs.get(rawKey);
345 for (int i = 0; i < val.length; i++) {
346 String rawVal = val[i];
347 val[i] = decode(rawVal, encoding);
348
349 if (LOG.isTraceEnabled()) {
350 StringBuilder bf = new StringBuilder("Parsing query string. Found raw pair [name]=[value]: ");
351 bf.append('[').append(rawKey).append(']').append('=').append('[').append(rawVal).append(']');
352 bf.append(" decoded to: ");
353 bf.append('[').append(key).append(']').append('=').append('[').append(val[i]).append(']');
354 LOG.trace(bf);
355 }
356 }
357 res.put(key, val);
358 }
359
360 return res;
361 }
362
363
364
365
366
367
368
369
370
371
372 protected final String constructQueryString(Map<String, String[]> parameters) {
373 StringBuilder qryStr = new StringBuilder();
374 for (String key : parameters.keySet()) {
375 String[] vals = parameters.get(key);
376 if (vals != null) {
377
378 for (String val : vals) {
379 if (val != null && val.length() > 0) {
380
381 if (qryStr.length() > 0) {
382 qryStr.append('&');
383 }
384
385
386 if (LOG.isTraceEnabled()) {
387 StringBuilder bf = new StringBuilder("About to add [key]=[value] to url [" + key + "]=["
388 + val + "]");
389 bf.append(" after encoding: [").append(encode(key)).append("]=[").append(encode(val))
390 .append("]");
391 LOG.trace(bf);
392
393 }
394 qryStr.append(encode(key)).append('=').append(encode(val));
395 }
396 }
397 }
398 }
399
400
401 if (qryStr.length() > 0) {
402 return qryStr.toString();
403 } else {
404 return null;
405 }
406 }
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422 protected final String[] excludeFromPackedargs(String[] origPackedargsStrings, Collection<String> toExclude) {
423 if (origPackedargsStrings == null) {
424 throw new IllegalArgumentException("OrigPackedArgsStrings must not be null");
425 }
426 if (toExclude == null) {
427 throw new IllegalArgumentException("ToExclude list may not be null");
428 }
429
430 String[] newPackedargsStrings = new String[origPackedargsStrings.length];
431
432 for (int i = 0; i < origPackedargsStrings.length; i++) {
433 Map<String, String[]> oldPacked = parseQueryString(origPackedargsStrings[i]);
434 Map<String, String[]> newPacked = new HashMap<String, String[]>();
435 for (String opK : oldPacked.keySet()) {
436 if (LOG.isTraceEnabled()) {
437 LOG.trace("checking to see if a param should be excluded from packedargs: " + opK);
438 }
439 if (!toExclude.contains(opK)) {
440 newPacked.put(opK, oldPacked.get(opK));
441 }
442 }
443
444 newPackedargsStrings[i] = constructQueryString(newPacked);
445
446 }
447
448 return newPackedargsStrings;
449 }
450 }