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