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 }