001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.util;
018
019 import java.io.UnsupportedEncodingException;
020 import java.net.URI;
021 import java.net.URISyntaxException;
022 import java.net.URLDecoder;
023 import java.net.URLEncoder;
024 import java.util.ArrayList;
025 import java.util.Collections;
026 import java.util.HashMap;
027 import java.util.Map;
028
029 /**
030 * URI utilities.
031 *
032 * @version $Revision: 751221 $
033 */
034 public final class URISupport {
035
036 private URISupport() {
037 // Helper class
038 }
039
040 /**
041 * Holder to get parts of the URI.
042 */
043 public static class CompositeData {
044 public String host;
045
046 String scheme;
047 String path;
048 URI components[];
049 Map parameters;
050 String fragment;
051
052 public URI[] getComponents() {
053 return components;
054 }
055
056 public String getFragment() {
057 return fragment;
058 }
059
060 public Map getParameters() {
061 return parameters;
062 }
063
064 public String getScheme() {
065 return scheme;
066 }
067
068 public String getPath() {
069 return path;
070 }
071
072 public String getHost() {
073 return host;
074 }
075
076 public URI toURI() throws URISyntaxException {
077 StringBuffer sb = new StringBuffer();
078 if (scheme != null) {
079 sb.append(scheme);
080 sb.append(':');
081 }
082
083 if (host != null && host.length() != 0) {
084 sb.append(host);
085 } else {
086 sb.append('(');
087 for (int i = 0; i < components.length; i++) {
088 if (i != 0) {
089 sb.append(',');
090 }
091 sb.append(components[i].toString());
092 }
093 sb.append(')');
094 }
095
096 if (path != null) {
097 sb.append('/');
098 sb.append(path);
099 }
100 if (!parameters.isEmpty()) {
101 sb.append("?");
102 sb.append(createQueryString(parameters));
103 }
104 if (fragment != null) {
105 sb.append("#");
106 sb.append(fragment);
107 }
108 return new URI(sb.toString());
109 }
110 }
111
112 @SuppressWarnings("unchecked")
113 public static Map parseQuery(String uri) throws URISyntaxException {
114 try {
115 Map rc = new HashMap();
116 if (uri != null) {
117 String[] parameters = uri.split("&");
118 for (String parameter : parameters) {
119 int p = parameter.indexOf("=");
120 if (p >= 0) {
121 String name = URLDecoder.decode(parameter.substring(0, p), "UTF-8");
122 String value = URLDecoder.decode(parameter.substring(p + 1), "UTF-8");
123 rc.put(name, value);
124 } else {
125 rc.put(parameter, null);
126 }
127 }
128 }
129 return rc;
130 } catch (UnsupportedEncodingException e) {
131 URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
132 se.initCause(e);
133 throw se;
134 }
135 }
136
137 public static Map parseParameters(URI uri) throws URISyntaxException {
138 String query = uri.getQuery();
139 if (query == null) {
140 String schemeSpecificPart = uri.getSchemeSpecificPart();
141 int idx = schemeSpecificPart.lastIndexOf('?');
142 if (idx < 0) {
143 return Collections.EMPTY_MAP;
144 } else {
145 query = schemeSpecificPart.substring(idx + 1);
146 }
147 } else {
148 query = stripPrefix(query, "?");
149 }
150 return parseQuery(query);
151 }
152
153 /**
154 * Removes any URI query from the given uri
155 */
156 public static URI removeQuery(URI uri) throws URISyntaxException {
157 return createURIWithQuery(uri, null);
158 }
159
160 /**
161 * Creates a URI with the given query
162 */
163 public static URI createURIWithQuery(URI uri, String query) throws URISyntaxException {
164 return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(),
165 query, uri.getFragment());
166 }
167
168 public static CompositeData parseComposite(URI uri) throws URISyntaxException {
169
170 CompositeData rc = new CompositeData();
171 rc.scheme = uri.getScheme();
172 String ssp = stripPrefix(uri.getSchemeSpecificPart().trim(), "//").trim();
173
174 parseComposite(uri, rc, ssp);
175
176 rc.fragment = uri.getFragment();
177 return rc;
178 }
179
180 private static void parseComposite(URI uri, CompositeData rc, String ssp) throws URISyntaxException {
181 String componentString;
182 String params;
183
184 if (!checkParenthesis(ssp)) {
185 throw new URISyntaxException(uri.toString(), "Not a matching number of '(' and ')' parenthesis");
186 }
187
188 int p;
189 int intialParen = ssp.indexOf("(");
190 if (intialParen == 0) {
191 rc.host = ssp.substring(0, intialParen);
192 p = rc.host.indexOf("/");
193 if (p >= 0) {
194 rc.path = rc.host.substring(p);
195 rc.host = rc.host.substring(0, p);
196 }
197 p = ssp.lastIndexOf(")");
198 componentString = ssp.substring(intialParen + 1, p);
199 params = ssp.substring(p + 1).trim();
200 } else {
201 componentString = ssp;
202 params = "";
203 }
204
205 String components[] = splitComponents(componentString);
206 rc.components = new URI[components.length];
207 for (int i = 0; i < components.length; i++) {
208 rc.components[i] = new URI(components[i].trim());
209 }
210
211 p = params.indexOf("?");
212 if (p >= 0) {
213 if (p > 0) {
214 rc.path = stripPrefix(params.substring(0, p), "/");
215 }
216 rc.parameters = parseQuery(params.substring(p + 1));
217 } else {
218 if (params.length() > 0) {
219 rc.path = stripPrefix(params, "/");
220 }
221 rc.parameters = Collections.EMPTY_MAP;
222 }
223 }
224
225 @SuppressWarnings("unchecked")
226 private static String[] splitComponents(String str) {
227 ArrayList l = new ArrayList();
228
229 int last = 0;
230 int depth = 0;
231 char chars[] = str.toCharArray();
232 for (int i = 0; i < chars.length; i++) {
233 switch (chars[i]) {
234 case '(':
235 depth++;
236 break;
237 case ')':
238 depth--;
239 break;
240 case ',':
241 if (depth == 0) {
242 String s = str.substring(last, i);
243 l.add(s);
244 last = i + 1;
245 }
246 break;
247 default:
248 }
249 }
250
251 String s = str.substring(last);
252 if (s.length() != 0) {
253 l.add(s);
254 }
255
256 String rc[] = new String[l.size()];
257 l.toArray(rc);
258 return rc;
259 }
260
261 public static String stripPrefix(String value, String prefix) {
262 if (value.startsWith(prefix)) {
263 return value.substring(prefix.length());
264 }
265 return value;
266 }
267
268 public static URI stripScheme(URI uri) throws URISyntaxException {
269 return new URI(stripPrefix(uri.getSchemeSpecificPart().trim(), "//"));
270 }
271
272 public static String createQueryString(Map options) throws URISyntaxException {
273 try {
274 if (options.size() > 0) {
275 StringBuffer rc = new StringBuffer();
276 boolean first = true;
277 for (Object o : options.keySet()) {
278 if (first) {
279 first = false;
280 } else {
281 rc.append("&");
282 }
283
284 String key = (String) o;
285 String value = (String) options.get(key);
286 rc.append(URLEncoder.encode(key, "UTF-8"));
287 rc.append("=");
288 rc.append(URLEncoder.encode(value, "UTF-8"));
289 }
290 return rc.toString();
291 } else {
292 return "";
293 }
294 } catch (UnsupportedEncodingException e) {
295 URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
296 se.initCause(e);
297 throw se;
298 }
299 }
300
301 /**
302 * Creates a URI from the original URI and the remaining parameters
303 */
304 public static URI createRemainingURI(URI originalURI, Map params) throws URISyntaxException {
305 String s = createQueryString(params);
306 if (s.length() == 0) {
307 s = null;
308 }
309 return createURIWithQuery(originalURI, s);
310 }
311
312 public static URI changeScheme(URI bindAddr, String scheme) throws URISyntaxException {
313 return new URI(scheme, bindAddr.getUserInfo(), bindAddr.getHost(), bindAddr.getPort(), bindAddr
314 .getPath(), bindAddr.getQuery(), bindAddr.getFragment());
315 }
316
317 public static boolean checkParenthesis(String str) {
318 boolean result = true;
319 if (str != null) {
320 int open = 0;
321 int closed = 0;
322
323 int i = 0;
324 while ((i = str.indexOf('(', i)) >= 0) {
325 i++;
326 open++;
327 }
328 i = 0;
329 while ((i = str.indexOf(')', i)) >= 0) {
330 i++;
331 closed++;
332 }
333 result = open == closed;
334 }
335 return result;
336 }
337
338 }