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