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 }