View Javadoc

1   package com.atlassian.sal.core.net;
2   
3   import java.net.URI;
4   import java.net.URISyntaxException;
5   
6   import com.atlassian.sal.api.net.NonMarshallingRequestFactory;
7   import org.apache.commons.httpclient.HttpClient;
8   import org.apache.commons.httpclient.UsernamePasswordCredentials;
9   import org.apache.commons.httpclient.auth.AuthScope;
10  import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
11  import org.apache.commons.lang.StringUtils;
12  import org.apache.log4j.Logger;
13  
14  import com.atlassian.sal.api.net.Request.MethodType;
15  import com.atlassian.sal.api.user.UserManager;
16  import com.atlassian.sal.core.trusted.CertificateFactory;
17  
18  /**
19   * Does NOT support json/xml oject marshalling. Use the atlassian-rest implementation of
20   * {@link com.atlassian.sal.api.net.RequestFactory} instead.
21   */
22  public class HttpClientRequestFactory implements NonMarshallingRequestFactory<HttpClientRequest>
23  {
24      private static final Logger log = Logger.getLogger(HttpClientRequestFactory.class);
25  
26      private final CertificateFactory certificateFactory;
27      private final UserManager userManager;
28  
29      public HttpClientRequestFactory(final CertificateFactory certificateFactory, final UserManager userManager)
30      {
31          this.certificateFactory = certificateFactory;
32          this.userManager = userManager;
33      }
34  
35      /**
36       * The default time to wait without retrieving data from the remote connection
37       */
38      public static final int DEFAULT_SOCKET_TIMEOUT=Integer.parseInt(System.getProperty("http.socketTimeout", "10000"));
39  
40      /**
41       * The default time allowed for establishing a connection
42       */
43      public static final int DEFAULT_CONNECTION_TIMEOUT=Integer.parseInt(System.getProperty("http.connectionTimeout", "10000"));
44      
45      /* (non-Javadoc)
46       * @see com.atlassian.sal.api.net.RequestFactory#createMethod(com.atlassian.sal.api.net.Request.MethodType, java.lang.String)
47       */
48      public HttpClientRequest createRequest(final MethodType methodType, final String url)
49      {
50          final HttpClient httpClient = getHttpClient(url);
51          return new HttpClientRequest(httpClient, methodType, url, certificateFactory, userManager);
52      }
53  
54      /**
55       * @param url The URL
56       * @return The HTTP client
57       */
58      protected HttpClient getHttpClient(final String url)
59      {
60          final HttpClient httpClient = new HttpClient();
61          configureProxy(httpClient, url);
62          configureConnectionParameters(httpClient);
63          return httpClient;
64      }
65  
66      /**
67       * Applies a set of parameters to a client
68       *
69       * @param httpClient the client to which parameters are applied
70       */
71      protected void configureConnectionParameters(final HttpClient httpClient)
72      {
73          final HttpConnectionManagerParams params = httpClient.getHttpConnectionManager().getParams();
74          params.setSoTimeout(DEFAULT_SOCKET_TIMEOUT);
75          params.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
76      }
77  
78      /**
79       * @param client The client to configure the proxy of
80       * @param remoteUrl The remote URL
81       */
82      protected void configureProxy(final HttpClient client, final String remoteUrl)
83      {
84          final String proxyHost = System.getProperty("http.proxyHost");
85  
86          URI uri;
87          try
88          {
89              uri = new URI(remoteUrl);
90          } catch (final URISyntaxException e)
91          {
92              log.warn("Invalid url: " + remoteUrl, e);
93              return;
94          }
95          if (proxyHost != null && !isNonProxyHost(uri.getHost()))
96          {
97              int port = 80;
98              try
99              {
100                 port = Integer.parseInt(System.getProperty("http.proxyPort", "80"));
101             }
102             catch (final NumberFormatException e)
103             {
104                 log.warn("System property 'http.proxyPort' is not a number. Defaulting to 80.");
105             }
106 
107             client.getHostConfiguration().setProxy(proxyHost, port);
108             if(proxyAuthenticationRequired())
109             {
110                 client.getState().setProxyCredentials(new AuthScope(proxyHost,port),
111                         new UsernamePasswordCredentials(System.getProperty("http.proxyUser"),
112                                 System.getProperty("http.proxyPassword")));
113             }
114         }
115     }
116 
117     /**
118      * Discover whether or not proxy authentication is required; if we are behind a proxy then it is required,
119      * otherwise it isn't
120      *
121      * @return true if proxy authentication is required, false otherwise
122      */
123     private boolean proxyAuthenticationRequired()
124     {
125         return System.getProperty("http.proxyUser") != null;
126     }
127 
128     private boolean isNonProxyHost(final String host)
129     {
130         final String httpNonProxyHosts = System.getProperty("http.nonProxyHosts");
131         if (StringUtils.isBlank(httpNonProxyHosts))
132         {
133             // checking if property was misspelt, notice there is no 's' at the end of this property
134             if (StringUtils.isBlank(System.getProperty("http.nonProxyHost")))
135             {
136                 log.warn("The system property http.nonProxyHost is set. You probably meant to set http.nonProxyHosts.");
137             }
138             return false;
139         }
140         final String[] nonProxyHosts = httpNonProxyHosts.split("\\|");
141         for (final String nonProxyHost : nonProxyHosts) {
142             if (nonProxyHost.startsWith("*")) {
143                 if (host.endsWith(nonProxyHost.substring(1))) {
144                     return true;
145                 }
146             } else if (host.equals(nonProxyHost)) {
147                 return true;
148             }
149         }
150         return false;
151     }
152     
153     public boolean supportsHeader()
154     {
155     	return true;
156     }
157 }