View Javadoc
1   /*
2    * Copyright (C) 2013 Christian Halstrick <christian.halstrick@sap.com>
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  package org.eclipse.jgit.transport.http;
44  
45  import java.io.IOException;
46  import java.io.InputStream;
47  import java.io.OutputStream;
48  import java.net.HttpURLConnection;
49  import java.net.MalformedURLException;
50  import java.net.ProtocolException;
51  import java.net.Proxy;
52  import java.net.URL;
53  import java.security.KeyManagementException;
54  import java.security.NoSuchAlgorithmException;
55  import java.security.SecureRandom;
56  import java.util.LinkedList;
57  import java.util.List;
58  import java.util.Map;
59  
60  import javax.net.ssl.HostnameVerifier;
61  import javax.net.ssl.HttpsURLConnection;
62  import javax.net.ssl.KeyManager;
63  import javax.net.ssl.SSLContext;
64  import javax.net.ssl.TrustManager;
65  
66  import org.eclipse.jgit.annotations.NonNull;
67  /**
68   * A {@link org.eclipse.jgit.transport.http.HttpConnection} which simply
69   * delegates every call to a {@link java.net.HttpURLConnection}. This is the
70   * default implementation used by JGit
71   *
72   * @since 3.3
73   */
74  public class JDKHttpConnection implements HttpConnection {
75  	HttpURLConnection wrappedUrlConnection;
76  
77  	// used for mock testing
78  	JDKHttpConnection(HttpURLConnection urlConnection) {
79  		this.wrappedUrlConnection = urlConnection;
80  	}
81  
82  	/**
83  	 * Constructor for JDKHttpConnection.
84  	 *
85  	 * @param url
86  	 *            a {@link java.net.URL} object.
87  	 * @throws java.net.MalformedURLException
88  	 * @throws java.io.IOException
89  	 */
90  	protected JDKHttpConnection(URL url)
91  			throws MalformedURLException,
92  			IOException {
93  		this.wrappedUrlConnection = (HttpURLConnection) url.openConnection();
94  	}
95  
96  	/**
97  	 * Constructor for JDKHttpConnection.
98  	 *
99  	 * @param url
100 	 *            a {@link java.net.URL} object.
101 	 * @param proxy
102 	 *            a {@link java.net.Proxy} object.
103 	 * @throws java.net.MalformedURLException
104 	 * @throws java.io.IOException
105 	 */
106 	protected JDKHttpConnection(URL url, Proxy proxy)
107 			throws MalformedURLException, IOException {
108 		this.wrappedUrlConnection = (HttpURLConnection) url
109 				.openConnection(proxy);
110 	}
111 
112 	/** {@inheritDoc} */
113 	@Override
114 	public int getResponseCode() throws IOException {
115 		return wrappedUrlConnection.getResponseCode();
116 	}
117 
118 	/** {@inheritDoc} */
119 	@Override
120 	public URL getURL() {
121 		return wrappedUrlConnection.getURL();
122 	}
123 
124 	/** {@inheritDoc} */
125 	@Override
126 	public String getResponseMessage() throws IOException {
127 		return wrappedUrlConnection.getResponseMessage();
128 	}
129 
130 	/** {@inheritDoc} */
131 	@Override
132 	public Map<String, List<String>> getHeaderFields() {
133 		return wrappedUrlConnection.getHeaderFields();
134 	}
135 
136 	/** {@inheritDoc} */
137 	@Override
138 	public void setRequestProperty(String key, String value) {
139 		wrappedUrlConnection.setRequestProperty(key, value);
140 	}
141 
142 	/** {@inheritDoc} */
143 	@Override
144 	public void setRequestMethod(String method) throws ProtocolException {
145 		wrappedUrlConnection.setRequestMethod(method);
146 	}
147 
148 	/** {@inheritDoc} */
149 	@Override
150 	public void setUseCaches(boolean usecaches) {
151 		wrappedUrlConnection.setUseCaches(usecaches);
152 	}
153 
154 	/** {@inheritDoc} */
155 	@Override
156 	public void setConnectTimeout(int timeout) {
157 		wrappedUrlConnection.setConnectTimeout(timeout);
158 	}
159 
160 	/** {@inheritDoc} */
161 	@Override
162 	public void setReadTimeout(int timeout) {
163 		wrappedUrlConnection.setReadTimeout(timeout);
164 	}
165 
166 	/** {@inheritDoc} */
167 	@Override
168 	public String getContentType() {
169 		return wrappedUrlConnection.getContentType();
170 	}
171 
172 	/** {@inheritDoc} */
173 	@Override
174 	public InputStream getInputStream() throws IOException {
175 		return wrappedUrlConnection.getInputStream();
176 	}
177 
178 	/** {@inheritDoc} */
179 	@Override
180 	public String getHeaderField(@NonNull String name) {
181 		return wrappedUrlConnection.getHeaderField(name);
182 	}
183 
184 	@Override
185 	public List<String> getHeaderFields(@NonNull String name) {
186 		Map<String, List<String>> m = wrappedUrlConnection.getHeaderFields();
187 		List<String> fields = mapValuesToListIgnoreCase(name, m);
188 		return fields;
189 	}
190 
191 	private static List<String> mapValuesToListIgnoreCase(String keyName,
192 			Map<String, List<String>> m) {
193 		List<String> fields = new LinkedList<>();
194 		m.entrySet().stream().filter(e -> keyName.equalsIgnoreCase(e.getKey()))
195 				.filter(e -> e.getValue() != null)
196 				.forEach(e -> fields.addAll(e.getValue()));
197 		return fields;
198 	}
199 
200 	/** {@inheritDoc} */
201 	@Override
202 	public int getContentLength() {
203 		return wrappedUrlConnection.getContentLength();
204 	}
205 
206 	/** {@inheritDoc} */
207 	@Override
208 	public void setInstanceFollowRedirects(boolean followRedirects) {
209 		wrappedUrlConnection.setInstanceFollowRedirects(followRedirects);
210 	}
211 
212 	/** {@inheritDoc} */
213 	@Override
214 	public void setDoOutput(boolean dooutput) {
215 		wrappedUrlConnection.setDoOutput(dooutput);
216 	}
217 
218 	/** {@inheritDoc} */
219 	@Override
220 	public void setFixedLengthStreamingMode(int contentLength) {
221 		wrappedUrlConnection.setFixedLengthStreamingMode(contentLength);
222 	}
223 
224 	/** {@inheritDoc} */
225 	@Override
226 	public OutputStream getOutputStream() throws IOException {
227 		return wrappedUrlConnection.getOutputStream();
228 	}
229 
230 	/** {@inheritDoc} */
231 	@Override
232 	public void setChunkedStreamingMode(int chunklen) {
233 		wrappedUrlConnection.setChunkedStreamingMode(chunklen);
234 	}
235 
236 	/** {@inheritDoc} */
237 	@Override
238 	public String getRequestMethod() {
239 		return wrappedUrlConnection.getRequestMethod();
240 	}
241 
242 	/** {@inheritDoc} */
243 	@Override
244 	public boolean usingProxy() {
245 		return wrappedUrlConnection.usingProxy();
246 	}
247 
248 	/** {@inheritDoc} */
249 	@Override
250 	public void connect() throws IOException {
251 		wrappedUrlConnection.connect();
252 	}
253 
254 	/** {@inheritDoc} */
255 	@Override
256 	public void setHostnameVerifier(HostnameVerifier hostnameverifier) {
257 		((HttpsURLConnection) wrappedUrlConnection)
258 				.setHostnameVerifier(hostnameverifier);
259 	}
260 
261 	/** {@inheritDoc} */
262 	@Override
263 	public void configure(KeyManager[] km, TrustManager[] tm,
264 			SecureRandom random) throws NoSuchAlgorithmException,
265 			KeyManagementException {
266 		SSLContext ctx = SSLContext.getInstance("TLS"); //$NON-NLS-1$
267 		ctx.init(km, tm, random);
268 		((HttpsURLConnection) wrappedUrlConnection).setSSLSocketFactory(ctx
269 				.getSocketFactory());
270 	}
271 }