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