View Javadoc

1   /*
2    * Copyright [2006] [University Corporation for Advanced Internet Development, Inc.]
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.opensaml.util;
18  
19  import java.io.UnsupportedEncodingException;
20  import java.net.URL;
21  import java.net.URLDecoder;
22  import java.net.URLEncoder;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.opensaml.xml.util.DatatypeHelper;
27  import org.opensaml.xml.util.Pair;
28  
29  /**
30   * Utility class for building URLs. May also be used to parse a URL into its invidual components. All components will be
31   * converted UTF-8 encoding and then application/x-www-form-urlencoded when built.
32   * 
33   * This class is not thread-safe.
34   */
35  public class URLBuilder {
36  
37      /** URL schema (http, https, etc). */
38      private String scheme;
39  
40      /** User name in the URL. */
41      private String username;
42  
43      /** Password in the URL. */
44      private String password;
45  
46      /** Host for the URL. */
47      private String host;
48  
49      /** URL port number. */
50      private int port;
51  
52      /** URL path. */
53      private String path;
54  
55      /** Parameters in the query string. */
56      private List<Pair<String, String>> queryParams;
57  
58      /** URL fragment. */
59      private String fragement;
60  
61      /**
62       * Constructor.
63       */
64      public URLBuilder() {
65          queryParams = new ArrayList<Pair<String, String>>();
66      }
67  
68      /**
69       * Constructor.
70       * 
71       * @param baseURL URL to parse and use as basis for creating other URLs
72       * 
73       * @throws IllegalArgumentException thrown if the given base URL is not well formed
74       */
75      public URLBuilder(String baseURL) {
76          try {
77              URL url = new URL(baseURL);
78  
79              setScheme(url.getProtocol());
80  
81              String userInfo = url.getUserInfo();
82              if (!DatatypeHelper.isEmpty(userInfo)) {
83                  if (userInfo.contains(":")) {
84                      String[] userInfoComps = userInfo.split(":");
85                      setUsername(URLDecoder.decode(userInfoComps[0], "UTF-8"));
86                      setPassword(URLDecoder.decode(userInfoComps[1], "UTF-8"));
87                  } else {
88                      setUsername(userInfo);
89                  }
90              }
91  
92              setHost(url.getHost());
93              setPort(url.getPort());
94              setPath(url.getPath());
95  
96              queryParams = new ArrayList<Pair<String, String>>();
97              String queryString = url.getQuery();
98              if (!DatatypeHelper.isEmpty(queryString)) {
99                  String[] queryComps = queryString.split("&");
100                 String queryComp;
101                 String[] paramComps;
102                 String paramName;
103                 String paramValue;
104                 for (int i = 0; i < queryComps.length; i++) {
105                     queryComp = queryComps[i];
106                     if (!queryComp.contains("=")) {
107                         paramName = URLDecoder.decode(queryComp, "UTF-8");
108                         queryParams.add(new Pair<String, String>(paramName, null));
109                     } else {
110                         paramComps = queryComp.split("=");
111                         paramName = URLDecoder.decode(paramComps[0], "UTF-8");
112                         paramValue = URLDecoder.decode(paramComps[1], "UTF-8");
113                         queryParams.add(new Pair<String, String>(paramName, paramValue));
114                     }
115                 }
116             }
117 
118             setFragment(url.getRef());
119         } catch (Exception e) {
120             throw new IllegalArgumentException("Given URL is not well formed", e);
121         }
122     }
123 
124     /**
125      * Gets the URL fragment in its decoded form.
126      * 
127      * @return URL fragment in its decoded form
128      */
129     public String getFragment() {
130         return fragement;
131     }
132 
133     /**
134      * Sets the URL fragment in its decoded form.
135      * 
136      * @param newFragment URL fragment in its decoded form
137      */
138     public void setFragment(String newFragment) {
139         fragement = DatatypeHelper.safeTrimOrNullString(newFragment);
140     }
141 
142     /**
143      * Gets the host component of the URL.
144      * 
145      * @return host component of the URL
146      */
147     public String getHost() {
148         return host;
149     }
150 
151     /**
152      * Sets the host component of the URL.
153      * 
154      * @param newHost host component of the URL
155      */
156     public void setHost(String newHost) {
157         host = DatatypeHelper.safeTrimOrNullString(newHost);
158     }
159 
160     /**
161      * Gets the user's password in the URL.
162      * 
163      * @return user's password in the URL
164      */
165     public String getPassword() {
166         return password;
167     }
168 
169     /**
170      * Sets the user's password in the URL.
171      * 
172      * @param newPassword user's password in the URL
173      */
174     public void setPassword(String newPassword) {
175         password = DatatypeHelper.safeTrimOrNullString(newPassword);
176     }
177 
178     /**
179      * Gets the path component of the URL.
180      * 
181      * @return path component of the URL
182      */
183     public String getPath() {
184         return path;
185     }
186 
187     /**
188      * Sets the path component of the URL.
189      * 
190      * @param newPath path component of the URL
191      */
192     public void setPath(String newPath) {
193         path = DatatypeHelper.safeTrimOrNullString(newPath);
194     }
195 
196     /**
197      * Gets the port component of the URL.
198      * 
199      * @return port component of the URL
200      */
201     public int getPort() {
202         return port;
203     }
204 
205     /**
206      * Sets the port component of the URL.
207      * 
208      * @param newPort port component of the URL
209      */
210     public void setPort(int newPort) {
211         port = newPort;
212     }
213 
214     /**
215      * Gets the query string parameters for the URL. Params may be added and removed through the map interface.
216      * 
217      * @return query string parameters for the URL
218      */
219     public List<Pair<String, String>> getQueryParams() {
220         return queryParams;
221     }
222 
223     /**
224      * Gets the URL scheme (http, https, etc).
225      * 
226      * @return URL scheme (http, https, etc)
227      */
228     public String getScheme() {
229         return scheme;
230     }
231 
232     /**
233      * Sets the URL scheme (http, https, etc).
234      * 
235      * @param newScheme URL scheme (http, https, etc)
236      */
237     public void setScheme(String newScheme) {
238         scheme = DatatypeHelper.safeTrimOrNullString(newScheme);
239     }
240 
241     /**
242      * Gets the user name component of the URL.
243      * 
244      * @return user name component of the URL
245      */
246     public String getUsername() {
247         return username;
248     }
249 
250     /**
251      * Sets the user name component of the URL.
252      * 
253      * @param newUsername user name component of the URL
254      */
255     public void setUsername(String newUsername) {
256         username = DatatypeHelper.safeTrimOrNullString(newUsername);
257     }
258 
259     /**
260      * Builds a URL from the given data. The constructured URL may not be valid if sufficient information is not
261      * provided. The returned URL will be appropriately encoded using application/x-www-form-urlencoded with appropriate
262      * encoding of UTF-8 characters.
263      * 
264      * @return URL built from the given data
265      */
266     public String buildURL() {
267         StringBuilder builder = new StringBuilder();
268 
269         if (!DatatypeHelper.isEmpty(scheme)) {
270             builder.append(scheme);
271             builder.append("://");
272         }
273 
274         if (!DatatypeHelper.isEmpty(username)) {
275             builder.append(username);
276             if (!DatatypeHelper.isEmpty(password)) {
277                 builder.append(":");
278                 builder.append(password);
279             }
280 
281             builder.append("@");
282         }
283 
284         if (!DatatypeHelper.isEmpty(host)) {
285             builder.append(host);
286             if (port > 0) {
287                 builder.append(":");
288                 builder.append(Integer.toString(port));
289             }
290         }
291 
292         if (!DatatypeHelper.isEmpty(path)) {
293             if (!path.startsWith("/")) {
294                 builder.append("/");
295             }
296             builder.append(path);
297         }
298 
299         String queryString = buildQueryString();
300         if(!DatatypeHelper.isEmpty(queryString)){
301             builder.append("?");
302             builder.append(queryString);
303         }
304 
305         if (!DatatypeHelper.isEmpty(fragement)) {
306             builder.append("#");
307             builder.append(fragement);
308         }
309 
310         return builder.toString();
311     }
312     
313     /**
314      * Builds the query string for the URL.
315      * 
316      * @return query string for the URL or null if there are now query parameters
317      */
318     public String buildQueryString(){
319         StringBuilder builder = new StringBuilder();
320         try {
321             if (queryParams.size() > 0) {
322                 String name;
323                 String value;
324 
325                 Pair<String, String> param;
326                 for (int i = 0; i < queryParams.size(); i++) {
327                     param = queryParams.get(i);
328                     name = DatatypeHelper.safeTrimOrNullString(param.getFirst());
329 
330                     if (name != null) {
331                         builder.append(URLEncoder.encode(name, "UTF-8"));
332                         value = DatatypeHelper.safeTrimOrNullString(param.getSecond());
333                         if (value != null) {
334                             builder.append("=");
335                             builder.append(URLEncoder.encode(value, "UTF-8"));
336                         }
337                         if (i < queryParams.size() - 1) {
338                             builder.append("&");
339                         }
340                     }
341                 }
342                 
343                 return builder.toString();
344             }
345         } catch (UnsupportedEncodingException e) {
346             // UTF-8 encoding is required to be supported by all JVMs
347         }
348         
349         return null;
350     }
351 }