1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http;
17
18 import java.io.UnsupportedEncodingException;
19 import java.net.URI;
20 import java.net.URLDecoder;
21 import java.nio.charset.Charset;
22 import java.nio.charset.UnsupportedCharsetException;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.Map;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class QueryStringDecoder {
50
51 private final Charset charset;
52 private final String uri;
53 private String path;
54 private Map<String, List<String>> params;
55
56
57
58
59
60 public QueryStringDecoder(String uri) {
61 this(uri, HttpCodecUtil.DEFAULT_CHARSET);
62 }
63
64
65
66
67
68 public QueryStringDecoder(String uri, Charset charset) {
69 if (uri == null) {
70 throw new NullPointerException("uri");
71 }
72 if (charset == null) {
73 throw new NullPointerException("charset");
74 }
75
76 this.uri = uri;
77 this.charset = charset;
78 }
79
80
81
82
83 @Deprecated
84 public QueryStringDecoder(String uri, String charset) {
85 this(uri, Charset.forName(charset));
86 }
87
88
89
90
91
92 public QueryStringDecoder(URI uri) {
93 this(uri, HttpCodecUtil.DEFAULT_CHARSET);
94 }
95
96
97
98
99
100 public QueryStringDecoder(URI uri, Charset charset){
101 if (uri == null) {
102 throw new NullPointerException("uri");
103 }
104 if (charset == null) {
105 throw new NullPointerException("charset");
106 }
107
108 this.uri = uri.toASCIIString();
109 this.charset = charset;
110 }
111
112
113
114
115 @Deprecated
116 public QueryStringDecoder(URI uri, String charset){
117 this(uri, Charset.forName(charset));
118 }
119
120
121
122
123 public String getPath() {
124 if (path == null) {
125 int pathEndPos = uri.indexOf('?');
126 if (pathEndPos < 0) {
127 path = uri;
128 }
129 else {
130 return path = uri.substring(0, pathEndPos);
131 }
132 }
133 return path;
134 }
135
136
137
138
139 public Map<String, List<String>> getParameters() {
140 if (params == null) {
141 int pathLength = getPath().length();
142 if (uri.length() == pathLength) {
143 return Collections.emptyMap();
144 }
145 params = decodeParams(uri.substring(pathLength + 1));
146 }
147 return params;
148 }
149
150 private Map<String, List<String>> decodeParams(String s) {
151 Map<String, List<String>> params = new LinkedHashMap<String, List<String>>();
152 String name = null;
153 int pos = 0;
154 int i;
155 char c = 0;
156 for (i = 0; i < s.length(); i++) {
157 c = s.charAt(i);
158 if (c == '=' && name == null) {
159 if (pos != i) {
160 name = decodeComponent(s.substring(pos, i), charset);
161 }
162 pos = i + 1;
163 } else if (c == '&') {
164 if (name == null && pos != i) {
165
166
167
168 addParam(params, decodeComponent(s.substring(pos, i), charset), "");
169 } else if (name != null) {
170 addParam(params, name, decodeComponent(s.substring(pos, i), charset));
171 name = null;
172 }
173 pos = i + 1;
174 }
175 }
176
177 if (pos != i) {
178 if (name == null) {
179 addParam(params, decodeComponent(s.substring(pos, i), charset), "");
180 } else {
181 addParam(params, name, decodeComponent(s.substring(pos, i), charset));
182 }
183 } else if (name != null) {
184 addParam(params, name, "");
185 }
186
187 return params;
188 }
189
190 private static String decodeComponent(String s, Charset charset) {
191 if (s == null) {
192 return "";
193 }
194
195 try {
196 return URLDecoder.decode(s, charset.name());
197 } catch (UnsupportedEncodingException e) {
198 throw new UnsupportedCharsetException(charset.name());
199 }
200 }
201
202 private static void addParam(Map<String, List<String>> params, String name, String value) {
203 List<String> values = params.get(name);
204 if (values == null) {
205 values = new ArrayList<String>(1);
206 params.put(name, values);
207 }
208 values.add(value);
209 }
210 }