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.Iterator;
028 import java.util.Map;
029
030 /**
031 * URI utilities.
032 *
033 * @version $Revision: 41272 $
034 */
035 public class URISupport {
036
037 public static class CompositeData {
038 public String host;
039
040 String scheme;
041 String path;
042 URI components[];
043 Map parameters;
044 String fragment;
045
046 public URI[] getComponents() {
047 return components;
048 }
049
050 public String getFragment() {
051 return fragment;
052 }
053
054 public Map getParameters() {
055 return parameters;
056 }
057
058 public String getScheme() {
059 return scheme;
060 }
061
062 public String getPath() {
063 return path;
064 }
065
066 public String getHost() {
067 return host;
068 }
069
070 public URI toURI() throws URISyntaxException {
071 StringBuffer sb = new StringBuffer();
072 if (scheme != null) {
073 sb.append(scheme);
074 sb.append(':');
075 }
076
077 if (host != null && host.length() != 0) {
078 sb.append(host);
079 } else {
080 sb.append('(');
081 for (int i = 0; i < components.length; i++) {
082 if (i != 0) {
083 sb.append(',');
084 }
085 sb.append(components[i].toString());
086 }
087 sb.append(')');
088 }
089
090 if (path != null) {
091 sb.append('/');
092 sb.append(path);
093 }
094 if (!parameters.isEmpty()) {
095 sb.append("?");
096 sb.append(createQueryString(parameters));
097 }
098 if (fragment != null) {
099 sb.append("#");
100 sb.append(fragment);
101 }
102 return new URI(sb.toString());
103 }
104 }
105
106 public static Map parseQuery(String uri) throws URISyntaxException {
107 try {
108 Map rc = new HashMap();
109 if (uri != null) {
110 String[] parameters = uri.split("&");
111 for (int i = 0; i < parameters.length; i++) {
112 int p = parameters[i].indexOf("=");
113 if (p >= 0) {
114 String name = URLDecoder.decode(parameters[i].substring(0, p), "UTF-8");
115 String value = URLDecoder.decode(parameters[i].substring(p + 1), "UTF-8");
116 rc.put(name, value);
117 } else {
118 rc.put(parameters[i], null);
119 }
120 }
121 }
122 return rc;
123 } catch (UnsupportedEncodingException e) {
124 throw (URISyntaxException)new URISyntaxException(e.toString(), "Invalid encoding").initCause(e);
125 }
126 }
127
128 public static Map parseParameters(URI uri) throws URISyntaxException {
129 String query = uri.getQuery();
130 if (query == null) {
131 String schemeSpecificPart = uri.getSchemeSpecificPart();
132 int idx = schemeSpecificPart.lastIndexOf('?');
133 if (idx < 0) {
134 return Collections.EMPTY_MAP;
135 } else {
136 query = schemeSpecificPart.substring(idx + 1);
137 }
138 } else {
139 query = stripPrefix(query, "?");
140 }
141 return parseQuery(query);
142 }
143
144 /**
145 * Removes any URI query from the given uri
146 */
147 public static URI removeQuery(URI uri) throws URISyntaxException {
148 return createURIWithQuery(uri, null);
149 }
150
151 /**
152 * Creates a URI with the given query
153 */
154 public static URI createURIWithQuery(URI uri, String query) throws URISyntaxException {
155 return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(),
156 query, uri.getFragment());
157 }
158
159 public static CompositeData parseComposite(URI uri) throws URISyntaxException {
160
161 CompositeData rc = new CompositeData();
162 rc.scheme = uri.getScheme();
163 String ssp = stripPrefix(uri.getSchemeSpecificPart().trim(), "//").trim();
164
165 parseComposite(uri, rc, ssp);
166
167 rc.fragment = uri.getFragment();
168 return rc;
169 }
170
171 private static void parseComposite(URI uri, CompositeData rc, String ssp) throws URISyntaxException {
172 String componentString;
173 String params;
174
175 if (!checkParenthesis(ssp)) {
176 throw new URISyntaxException(uri.toString(), "Not a matching number of '(' and ')' parenthesis");
177 }
178
179 int p;
180 int intialParen = ssp.indexOf("(");
181 if (intialParen == 0) {
182 rc.host = ssp.substring(0, intialParen);
183 p = rc.host.indexOf("/");
184 if (p >= 0) {
185 rc.path = rc.host.substring(p);
186 rc.host = rc.host.substring(0, p);
187 }
188 p = ssp.lastIndexOf(")");
189 componentString = ssp.substring(intialParen + 1, p);
190 params = ssp.substring(p + 1).trim();
191 } else {
192 componentString = ssp;
193 params = "";
194 }
195
196 String components[] = splitComponents(componentString);
197 rc.components = new URI[components.length];
198 for (int i = 0; i < components.length; i++) {
199 rc.components[i] = new URI(components[i].trim());
200 }
201
202 p = params.indexOf("?");
203 if (p >= 0) {
204 if (p > 0) {
205 rc.path = stripPrefix(params.substring(0, p), "/");
206 }
207 rc.parameters = parseQuery(params.substring(p + 1));
208 } else {
209 if (params.length() > 0) {
210 rc.path = stripPrefix(params, "/");
211 }
212 rc.parameters = Collections.EMPTY_MAP;
213 }
214 }
215
216 private static String[] splitComponents(String str) {
217 ArrayList l = new ArrayList();
218
219 int last = 0;
220 int depth = 0;
221 char chars[] = str.toCharArray();
222 for (int i = 0; i < chars.length; i++) {
223 switch (chars[i]) {
224 case '(':
225 depth++;
226 break;
227 case ')':
228 depth--;
229 break;
230 case ',':
231 if (depth == 0) {
232 String s = str.substring(last, i);
233 l.add(s);
234 last = i + 1;
235 }
236 break;
237 default:
238 }
239 }
240
241 String s = str.substring(last);
242 if (s.length() != 0) {
243 l.add(s);
244 }
245
246 String rc[] = new String[l.size()];
247 l.toArray(rc);
248 return rc;
249 }
250
251 public static String stripPrefix(String value, String prefix) {
252 if (value.startsWith(prefix)) {
253 return value.substring(prefix.length());
254 }
255 return value;
256 }
257
258 public static URI stripScheme(URI uri) throws URISyntaxException {
259 return new URI(stripPrefix(uri.getSchemeSpecificPart().trim(), "//"));
260 }
261
262 public static String createQueryString(Map options) throws URISyntaxException {
263 try {
264 if (options.size() > 0) {
265 StringBuffer rc = new StringBuffer();
266 boolean first = true;
267 for (Iterator iter = options.keySet().iterator(); iter.hasNext();) {
268 if (first) {
269 first = false;
270 } else {
271 rc.append("&");
272 }
273
274 String key = (String)iter.next();
275 String value = (String)options.get(key);
276 rc.append(URLEncoder.encode(key, "UTF-8"));
277 rc.append("=");
278 rc.append(URLEncoder.encode(value, "UTF-8"));
279 }
280 return rc.toString();
281 } else {
282 return "";
283 }
284 } catch (UnsupportedEncodingException e) {
285 throw (URISyntaxException)new URISyntaxException(e.toString(), "Invalid encoding").initCause(e);
286 }
287 }
288
289 /**
290 * Creates a URI from the original URI and the remaining parameters
291 *
292 * @throws URISyntaxException
293 */
294 public static URI createRemainingURI(URI originalURI, Map params) throws URISyntaxException {
295 String s = createQueryString(params);
296 if (s.length() == 0) {
297 s = null;
298 }
299 return createURIWithQuery(originalURI, s);
300 }
301
302 public static URI changeScheme(URI bindAddr, String scheme) throws URISyntaxException {
303 return new URI(scheme, bindAddr.getUserInfo(), bindAddr.getHost(), bindAddr.getPort(), bindAddr
304 .getPath(), bindAddr.getQuery(), bindAddr.getFragment());
305 }
306
307 public static boolean checkParenthesis(String str) {
308 boolean result = true;
309 if (str != null) {
310 int open = 0;
311 int closed = 0;
312
313 int i = 0;
314 while ((i = str.indexOf('(', i)) >= 0) {
315 i++;
316 open++;
317 }
318 i = 0;
319 while ((i = str.indexOf(')', i)) >= 0) {
320 i++;
321 closed++;
322 }
323 result = open == closed;
324 }
325 return result;
326 }
327
328 /**
329 * @deprecated this method will be removed in a future release
330 */
331 public int indexOfParenthesisMatch(String str) {
332 int result = -1;
333
334 return result;
335 }
336 }