1 // This file is part of OpenTSDB. 2 // Copyright (C) 2012 The OpenTSDB Authors. 3 // 4 // This program is free software: you can redistribute it and/or modify it 5 // under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 2.1 of the License, or (at your 7 // option) any later version. This program is distributed in the hope that it 8 // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 9 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License for more details. You should have received a copy 11 // of the GNU Lesser General Public License along with this program. If not, 12 // see <http://www.gnu.org/licenses/>. 13 package tsd.client; 14 15 // I (tsuna) originally wrote this code for Netty. Surprisingly, GWT has 16 // nothing to manually parse query string parameters... 17 18 import java.util.ArrayList; 19 import java.util.HashMap; 20 21 /** 22 * Splits an HTTP query string into a path string and key-value parameter pairs. 23 */ 24 public final class QueryString extends HashMap<String, ArrayList<String>> { 25 26 /** 27 * Returns the decoded key-value parameter pairs of the URI. 28 */ decode(final String s)29 public static QueryString decode(final String s) { 30 final QueryString params = new QueryString(); 31 String name = null; 32 int pos = 0; // Beginning of the unprocessed region 33 int i; // End of the unprocessed region 34 for (i = 0; i < s.length(); i++) { 35 final char c = s.charAt(i); 36 if (c == '=' && name == null) { 37 if (pos != i) { 38 name = s.substring(pos, i); 39 } 40 pos = i + 1; 41 } else if (c == '&') { 42 if (name == null && pos != i) { 43 // We haven't seen an `=' so far but moved forward. 44 // Must be a param of the form '&a&' so add it with 45 // an empty value. 46 params.add(s.substring(pos, i), ""); 47 } else if (name != null) { 48 params.add(name, s.substring(pos, i)); 49 name = null; 50 } 51 pos = i + 1; 52 } 53 } 54 55 if (pos != i) { // Are there characters we haven't dealt with? 56 if (name == null) { // Yes and we haven't seen any `='. 57 params.add(s.substring(pos, i), ""); 58 } else { // Yes and this must be the last value. 59 params.add(name, s.substring(pos, i)); 60 } 61 } else if (name != null) { // Have we seen a name without value? 62 params.add(name, ""); 63 } 64 65 return params; 66 } 67 68 /** 69 * Adds a query string element. 70 * @param name The name of the element. 71 * @param value The value of the element. 72 */ add(final String name, final String value)73 public void add(final String name, final String value) { 74 ArrayList<String> values = super.get(name); 75 if (values == null) { 76 values = new ArrayList<String>(1); // Often there's only 1 value. 77 super.put(name, values); 78 } 79 values.add(value); 80 } 81 82 /** 83 * Returns the first value for the given key, or {@code null}. 84 */ getFirst(final String key)85 public String getFirst(final String key) { 86 final ArrayList<String> values = super.get(key); 87 return values == null ? null : values.get(0); 88 } 89 90 } 91