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