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