001 package com.nimbusds.oauth2.sdk.util; 002 003 004 import java.io.UnsupportedEncodingException; 005 import java.net.MalformedURLException; 006 import java.net.URL; 007 import java.net.URLDecoder; 008 import java.net.URLEncoder; 009 import java.util.HashMap; 010 import java.util.Iterator; 011 import java.util.Map; 012 import java.util.StringTokenizer; 013 014 015 /** 016 * URL operations. 017 * 018 * @author Vladimir Dzhuvinov 019 */ 020 public class URLUtils { 021 022 023 /** 024 * The default UTF-8 character set. 025 */ 026 public static final String CHARSET = "utf-8"; 027 028 029 /** 030 * Gets the base part (protocol, host, port and path) of the specified 031 * URL. 032 * 033 * @param url The URL. May be {@code null}. 034 * 035 * @return The base part of the URL, {@code null} if the original URL 036 * is {@code null} or doesn't specify a protocol. 037 */ 038 public static URL getBaseURL(final URL url) { 039 040 if (url == null) 041 return null; 042 043 try { 044 return new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getPath()); 045 046 } catch (MalformedURLException e) { 047 048 return null; 049 } 050 } 051 052 053 /** 054 * Serialises the specified map of parameters into a URL query string. 055 * The parameter keys and values are 056 * {@code application/x-www-form-urlencoded} encoded. 057 * 058 * <p>Note that the '?' character preceding the query string in GET 059 * requests is not included in the returned string. 060 * 061 * <p>Example query string: 062 * 063 * <pre> 064 * response_type=code 065 * &client_id=s6BhdRkqt3 066 * &state=xyz 067 * &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb 068 * </pre> 069 * 070 * <p>The opposite method is {@link #parseParameters}. 071 * 072 * @param params A map of the URL query parameters. May be empty or 073 * {@code null}. 074 * 075 * @return The serialised URL query string, empty if no parameters. 076 */ 077 public static String serializeParameters(final Map<String,String> params) { 078 079 if (params == null || params.isEmpty()) 080 return ""; 081 082 StringBuilder sb = new StringBuilder(); 083 084 Iterator <Map.Entry<String,String>> it = params.entrySet().iterator(); 085 086 while (it.hasNext()) { 087 088 Map.Entry<String,String> entry = it.next(); 089 090 if (entry.getKey() == null || entry.getValue() == null) 091 continue; 092 093 try { 094 String encodedKey = URLEncoder.encode(entry.getKey(), CHARSET); 095 String encodedValue = URLEncoder.encode(entry.getValue(), CHARSET); 096 097 if (sb.length() > 0) 098 sb.append('&'); 099 100 sb.append(encodedKey); 101 sb.append('='); 102 sb.append(encodedValue); 103 104 } catch (UnsupportedEncodingException e) { 105 106 // UTF-8 should always be supported 107 } 108 } 109 110 return sb.toString(); 111 } 112 113 114 /** 115 * Parses the specified URL query string into a parameter map. If a 116 * parameter has multiple values only the first one will be saved. The 117 * parameter keys and values are 118 * {@code application/x-www-form-urlencoded} decoded. 119 * 120 * <p>Note that the '?' character preceding the query string in GET 121 * requests must not be included. 122 * 123 * <p>Example query string: 124 * 125 * <pre> 126 * response_type=code 127 * &client_id=s6BhdRkqt3 128 * &state=xyz 129 * &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb 130 * </pre> 131 * 132 * <p>The opposite method {@link #serializeParameters}. 133 * 134 * @param query The URL query string to parse. May be {@code null}. 135 * 136 * @return A map of the URL query parameters, empty if none are found. 137 */ 138 public static Map<String,String> parseParameters(final String query) { 139 140 Map<String,String> params = new HashMap<String, String>(); 141 142 if (query == null) 143 return params; // empty map 144 145 try { 146 StringTokenizer st = new StringTokenizer(query, "&"); 147 148 while(st.hasMoreTokens()) { 149 150 String param = st.nextToken(); 151 152 String pair[] = param.split("="); 153 154 String key = URLDecoder.decode(pair[0], CHARSET); 155 156 // Save the first value only 157 if (params.containsKey(key)) 158 continue; 159 160 String value = ""; 161 162 if (pair.length > 1) 163 value = URLDecoder.decode(pair[1], CHARSET); 164 165 params.put(key, value); 166 } 167 168 } catch (UnsupportedEncodingException e) { 169 170 // UTF-8 should always be supported 171 } 172 173 return params; 174 } 175 176 177 /** 178 * Prevents instantiation. 179 */ 180 private URLUtils() { 181 182 // do nothing 183 } 184 }