001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.luni.internal.net.www.protocol.https;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.io.OutputStream;
022: import java.net.ProtocolException;
023: import java.net.Proxy;
024: import java.net.URL;
025: import java.security.Permission;
026: import java.security.Principal;
027: import java.security.cert.Certificate;
028: import java.util.List;
029: import java.util.Map;
030:
031: import javax.net.ssl.SSLPeerUnverifiedException;
032: import javax.net.ssl.SSLSocket;
033:
034: import org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection;
035: import org.apache.harmony.luni.internal.nls.Messages;
036:
037: /**
038: * HttpsURLConnection implementation.
039: */
040: public class HttpsURLConnection extends
041: javax.net.ssl.HttpsURLConnection {
042:
043: // Https engine to be wrapped
044: private final HttpsEngine httpsEngine;
045:
046: // SSLSocket to be used for connection
047: private SSLSocket sslSocket;
048:
049: protected HttpsURLConnection(URL url, int port) {
050: super (url);
051: httpsEngine = new HttpsEngine(url, port);
052: }
053:
054: protected HttpsURLConnection(URL url, int port, Proxy proxy) {
055: super (url);
056: httpsEngine = new HttpsEngine(url, port, proxy);
057: }
058:
059: @Override
060: public String getCipherSuite() {
061: if (sslSocket == null) {
062: throw new IllegalStateException(Messages
063: .getString("luni.00")); //$NON-NLS-1$
064: }
065: return sslSocket.getSession().getCipherSuite();
066: }
067:
068: @Override
069: public Certificate[] getLocalCertificates() {
070: if (sslSocket == null) {
071: throw new IllegalStateException(Messages
072: .getString("luni.00")); //$NON-NLS-1$
073: }
074: return sslSocket.getSession().getLocalCertificates();
075: }
076:
077: @Override
078: public Certificate[] getServerCertificates()
079: throws SSLPeerUnverifiedException {
080: if (sslSocket == null) {
081: throw new IllegalStateException(Messages
082: .getString("luni.00")); //$NON-NLS-1$
083: }
084: return sslSocket.getSession().getPeerCertificates();
085: }
086:
087: @Override
088: public Principal getPeerPrincipal()
089: throws SSLPeerUnverifiedException {
090: if (sslSocket == null) {
091: throw new IllegalStateException(Messages
092: .getString("luni.00")); //$NON-NLS-1$
093: }
094: return sslSocket.getSession().getPeerPrincipal();
095: }
096:
097: @Override
098: public Principal getLocalPrincipal() {
099: if (sslSocket == null) {
100: throw new IllegalStateException(Messages
101: .getString("luni.00")); //$NON-NLS-1$
102: }
103: return sslSocket.getSession().getLocalPrincipal();
104: }
105:
106: @Override
107: public void disconnect() {
108: httpsEngine.disconnect();
109: }
110:
111: @Override
112: public InputStream getErrorStream() {
113: return httpsEngine.getErrorStream();
114: }
115:
116: @Override
117: public String getRequestMethod() {
118: return httpsEngine.getRequestMethod();
119: }
120:
121: @Override
122: public int getResponseCode() throws IOException {
123: return httpsEngine.getResponseCode();
124: }
125:
126: @Override
127: public String getResponseMessage() throws IOException {
128: return httpsEngine.getResponseMessage();
129: }
130:
131: @Override
132: public void setRequestMethod(String method)
133: throws ProtocolException {
134: httpsEngine.setRequestMethod(method);
135: }
136:
137: @Override
138: public boolean usingProxy() {
139: return httpsEngine.usingProxy();
140: }
141:
142: @Override
143: public boolean getInstanceFollowRedirects() {
144: return httpsEngine.getInstanceFollowRedirects();
145: }
146:
147: @Override
148: public void setInstanceFollowRedirects(boolean followRedirects) {
149: httpsEngine.setInstanceFollowRedirects(followRedirects);
150: }
151:
152: @Override
153: public void connect() throws IOException {
154: httpsEngine.connect();
155: }
156:
157: @Override
158: public boolean getAllowUserInteraction() {
159: return httpsEngine.getAllowUserInteraction();
160: }
161:
162: @Override
163: public Object getContent() throws IOException {
164: return httpsEngine.getContent();
165: }
166:
167: @SuppressWarnings("unchecked")
168: // Spec does not generify
169: @Override
170: public Object getContent(Class[] types) throws IOException {
171: return httpsEngine.getContent(types);
172: }
173:
174: @Override
175: public String getContentEncoding() {
176: return httpsEngine.getContentEncoding();
177: }
178:
179: @Override
180: public int getContentLength() {
181: return httpsEngine.getContentLength();
182: }
183:
184: @Override
185: public String getContentType() {
186: return httpsEngine.getContentType();
187: }
188:
189: @Override
190: public long getDate() {
191: return httpsEngine.getDate();
192: }
193:
194: @Override
195: public boolean getDefaultUseCaches() {
196: return httpsEngine.getDefaultUseCaches();
197: }
198:
199: @Override
200: public boolean getDoInput() {
201: return httpsEngine.getDoInput();
202: }
203:
204: @Override
205: public boolean getDoOutput() {
206: return httpsEngine.getDoOutput();
207: }
208:
209: @Override
210: public long getExpiration() {
211: return httpsEngine.getExpiration();
212: }
213:
214: @Override
215: public String getHeaderField(int pos) {
216: return httpsEngine.getHeaderField(pos);
217: }
218:
219: @Override
220: public Map<String, List<String>> getHeaderFields() {
221: return httpsEngine.getHeaderFields();
222: }
223:
224: @Override
225: public Map<String, List<String>> getRequestProperties() {
226: return httpsEngine.getRequestProperties();
227: }
228:
229: @Override
230: public void addRequestProperty(String field, String newValue) {
231: httpsEngine.addRequestProperty(field, newValue);
232: }
233:
234: @Override
235: public String getHeaderField(String key) {
236: return httpsEngine.getHeaderField(key);
237: }
238:
239: @Override
240: public long getHeaderFieldDate(String field, long defaultValue) {
241: return httpsEngine.getHeaderFieldDate(field, defaultValue);
242: }
243:
244: @Override
245: public int getHeaderFieldInt(String field, int defaultValue) {
246: return httpsEngine.getHeaderFieldInt(field, defaultValue);
247: }
248:
249: @Override
250: public String getHeaderFieldKey(int posn) {
251: return httpsEngine.getHeaderFieldKey(posn);
252: }
253:
254: @Override
255: public long getIfModifiedSince() {
256: return httpsEngine.getIfModifiedSince();
257: }
258:
259: @Override
260: public InputStream getInputStream() throws IOException {
261: return httpsEngine.getInputStream();
262: }
263:
264: @Override
265: public long getLastModified() {
266: return httpsEngine.getLastModified();
267: }
268:
269: @Override
270: public OutputStream getOutputStream() throws IOException {
271: return httpsEngine.getOutputStream();
272: }
273:
274: @Override
275: public Permission getPermission() throws IOException {
276: return httpsEngine.getPermission();
277: }
278:
279: @Override
280: public String getRequestProperty(String field) {
281: return httpsEngine.getRequestProperty(field);
282: }
283:
284: @Override
285: public URL getURL() {
286: return httpsEngine.getURL();
287: }
288:
289: @Override
290: public boolean getUseCaches() {
291: return httpsEngine.getUseCaches();
292: }
293:
294: @Override
295: public void setAllowUserInteraction(boolean newValue) {
296: httpsEngine.setAllowUserInteraction(newValue);
297: }
298:
299: @Override
300: public void setDefaultUseCaches(boolean newValue) {
301: httpsEngine.setDefaultUseCaches(newValue);
302: }
303:
304: @Override
305: public void setDoInput(boolean newValue) {
306: httpsEngine.setDoInput(newValue);
307: }
308:
309: @Override
310: public void setDoOutput(boolean newValue) {
311: httpsEngine.setDoOutput(newValue);
312: }
313:
314: @Override
315: public void setIfModifiedSince(long newValue) {
316: httpsEngine.setIfModifiedSince(newValue);
317: }
318:
319: @Override
320: public void setRequestProperty(String field, String newValue) {
321: httpsEngine.setRequestProperty(field, newValue);
322: }
323:
324: @Override
325: public void setUseCaches(boolean newValue) {
326: httpsEngine.setUseCaches(newValue);
327: }
328:
329: @Override
330: public void setConnectTimeout(int timeout) {
331: httpsEngine.setConnectTimeout(timeout);
332: }
333:
334: @Override
335: public int getConnectTimeout() {
336: return httpsEngine.getConnectTimeout();
337: }
338:
339: @Override
340: public void setReadTimeout(int timeout) {
341: httpsEngine.setReadTimeout(timeout);
342: }
343:
344: @Override
345: public int getReadTimeout() {
346: return httpsEngine.getReadTimeout();
347: }
348:
349: @Override
350: public String toString() {
351: return httpsEngine.toString();
352: }
353:
354: /**
355: * HttpsEngine
356: */
357: private class HttpsEngine extends HttpURLConnection {
358:
359: // In case of using proxy this field indicates
360: // if it is a SSL Tunnel establishing stage
361: private boolean makingSSLTunnel;
362:
363: protected HttpsEngine(URL url, int port) {
364: super (url, port);
365: }
366:
367: protected HttpsEngine(URL url, int port, Proxy proxy) {
368: super (url, port, proxy);
369: }
370:
371: @Override
372: public void connect() throws IOException {
373: if (connected) {
374: return;
375: }
376: if (usingProxy() && !makingSSLTunnel) {
377: // SSL Tunnel through the proxy was not established yet, do so
378: makingSSLTunnel = true;
379: // first - make the connection
380: super .connect();
381: // keep request method
382: String save_meth = method;
383: // make SSL Tunnel
384: method = "CONNECT"; //$NON-NLS-1$
385: try {
386: doRequest();
387: endRequest();
388: } finally {
389: // restore initial request method
390: method = save_meth;
391: }
392: if (!connected) {
393: throw new IOException(Messages.getString("luni.01", //$NON-NLS-1$
394: responseMessage, responseCode));
395: }
396: // if there are some remaining data in the stream - read it out
397: InputStream is = connection.getInputStream();
398: while (is.available() != 0) {
399: is.read();
400: }
401: makingSSLTunnel = false;
402: } else {
403: // no need in SSL tunnel
404: super .connect();
405: }
406: if (!makingSSLTunnel) {
407: sslSocket = connection.getSecureSocket(
408: getSSLSocketFactory(), getHostnameVerifier());
409: setUpTransportIO(connection);
410: }
411: }
412:
413: @Override
414: protected String requestString() {
415: if (usingProxy()) {
416: if (makingSSLTunnel) {
417: // we are making the SSL Tunneling, return remotehost:port
418: int port = url.getPort();
419: return (port > 0) ? url.getHost() + ":" + port //$NON-NLS-1$
420: : url.getHost();
421: }
422: // we has made SSL Tunneling, return /requested.data
423: String file = url.getFile();
424: if (file == null || file.length() == 0) {
425: file = "/"; //$NON-NLS-1$
426: }
427: return file;
428: }
429: return super.requestString();
430: }
431:
432: }
433: }
|