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