View Javadoc

1   package com.atlassian.sal.core.net;
2   
3   import org.apache.commons.httpclient.HttpClient;
4   import org.apache.commons.httpclient.UsernamePasswordCredentials;
5   import org.apache.commons.httpclient.auth.AuthScope;
6   import org.apache.commons.lang.StringUtils;
7   import org.apache.log4j.Logger;
8   
9   import java.net.URI;
10  import java.net.URISyntaxException;
11  
12  /**
13   * Configures the proxy on the HttpClient instance, reads the proxy configuration
14   * from the following system properties:
15   *
16   *<ul>
17   *     <li><b>http.proxyHost</b></li>
18   *     <li><b>http.proxyPort</b> (optional, default to 80)</li>
19   *</ul>
20   * A list of excluded hosts can be provided to bypass the proxy:
21   *<ul>
22   *     <li><b>http.nonProxyHosts</b> (format: www.atlassian.com|*.example.com) - The only wildcard supported is the simple suffix match.</li>
23   *</ul>
24   * If the proxy needs authentication, the credentials must be provided using:
25   *<ul>
26   *     <li><b>http.proxyUser</b></li>
27   *     <li><b>http.proxyPassword</b></li>
28   *</ul>
29   */
30  public class HttpClientProxyConfig {
31  
32      private static final Logger log = Logger.getLogger(HttpClientProxyConfig.class);
33  
34      /**
35       * @param client The client to configure the proxy of
36       * @param remoteUrl The remote URL
37       */
38      protected void configureProxy(final HttpClient client, final String remoteUrl)
39      {
40          if (client == null)
41          {
42              throw new IllegalArgumentException("Please provide a valid HttpClient instance");
43          }
44          final String proxyHost = System.getProperty("http.proxyHost");
45  
46          URI uri;
47          try
48          {
49              uri = new URI(remoteUrl);
50          } catch (final URISyntaxException e)
51          {
52              log.warn("Invalid url: " + remoteUrl, e);
53              return;
54          }
55          if (proxyHost != null && !isNonProxyHost(uri.getHost()))
56          {
57              int port = 80;
58              try
59              {
60                  port = Integer.parseInt(System.getProperty("http.proxyPort", "80"));
61              }
62              catch (final NumberFormatException e)
63              {
64                  log.warn("System property 'http.proxyPort' is not a number. Defaulting to 80.");
65              }
66  
67              client.getHostConfiguration().setProxy(proxyHost, port);
68              if(proxyAuthenticationRequired())
69              {
70                  client.getState().setProxyCredentials(new AuthScope(proxyHost,port),
71                          new UsernamePasswordCredentials(System.getProperty("http.proxyUser"),
72                                  System.getProperty("http.proxyPassword")));
73              }
74          }
75      }
76  
77      /**
78       * Discover whether or not proxy authentication is required; if we are behind a proxy then it is required,
79       * otherwise it isn't
80       *
81       * @return true if proxy authentication is required, false otherwise
82       */
83      private boolean proxyAuthenticationRequired()
84      {
85          return System.getProperty("http.proxyUser") != null;
86      }
87  
88      private boolean isNonProxyHost(final String host)
89      {
90          if (StringUtils.isBlank(host))
91          {
92              return true;
93          }
94          final String httpNonProxyHosts = System.getProperty("http.nonProxyHosts");
95          if (StringUtils.isBlank(httpNonProxyHosts))
96          {
97              // checking if property was misspelt, notice there is no 's' at the end of this property
98              if (StringUtils.isBlank(System.getProperty("http.nonProxyHost")))
99              {
100                 log.warn("The system property http.nonProxyHost is set. You probably meant to set http.nonProxyHosts.");
101             }
102             return false;
103         }
104         final String[] nonProxyHosts = httpNonProxyHosts.split("\\|");
105         for (final String nonProxyHost : nonProxyHosts) {
106             if (nonProxyHost.startsWith("*")) {
107                 if (host.endsWith(nonProxyHost.substring(1))) {
108                     return true;
109                 }
110             } else if (host.equals(nonProxyHost)) {
111                 return true;
112             }
113         }
114         return false;
115     }
116 
117 }