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