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