Java tutorial
/* * Adito * * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.maverick.ssl.https; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PushbackInputStream; import java.net.HttpURLConnection; import java.net.Socket; import java.net.URL; import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Hashtable; import java.util.StringTokenizer; import java.util.TimeZone; import java.util.Vector; import com.maverick.http.AuthenticationCancelledException; import com.maverick.http.ConnectMethod; import com.maverick.http.HttpClient; import com.maverick.http.HttpException; import com.maverick.http.HttpMethod; import com.maverick.http.HttpResponse; import com.maverick.http.PasswordCredentials; import com.maverick.http.UnsupportedAuthenticationException; import com.maverick.ssl.SSLException; import com.maverick.ssl.SSLIOException; import com.maverick.ssl.SSLSocket; /** * * @author Lee David Painter <a href="mailto:lee@localhost"><lee@localhost></a> */ public class HttpsURLConnection extends HttpURLConnection { boolean debugging; ByteArrayOutputStream output = new ByteArrayOutputStream(); Vector requestKeys, requestValues; Vector headers = new Vector(), headerKeys = new Vector(); Hashtable headerValues = new Hashtable(); Socket socket; PushbackInputStream input; int responseCode = -1; String responseMessage; /* * public static final String httpsProxyHostPropertyName = * "ssl.https.proxy.host"; * * public static final String httpsProxyPortPropertyName = * "ssl.https.proxy.port"; */ // #ifdef DEBUG static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory .getLog(HttpsURLConnection.class); // #endif public static final String httpProxyHostProperty = "com.maverick.ssl.https.HTTPProxyHostname"; //$NON-NLS-1$ public static final String httpProxyPortProperty = "com.maverick.ssl.https.HTTPProxyPort"; //$NON-NLS-1$ public static final String httpProxyUsernameProperty = "com.maverick.ssl.https.HTTPProxyUsername"; //$NON-NLS-1$ public static final String httpProxyPasswordProperty = "com.maverick.ssl.https.HTTPProxyPassword"; //$NON-NLS-1$ public static final String httpProxySecureProperty = "com.maverick.ssl.https.HTTPProxySecure"; //$NON-NLS-1$ public static final String httpProxyNonProxyHostsProperty = "com.maverick.ssl.https.HTTPProxyNonProxyHosts"; //$NON-NLS-1$ static Vector defaultRequestKeys = new Vector(), defaultRequestValues = new Vector(); static { defaultRequestKeys.addElement("User-agent"); //$NON-NLS-1$ defaultRequestValues.addElement(HttpClient.USER_AGENT); } public HttpsURLConnection(URL url) { super(url); synchronized (defaultRequestKeys) { requestKeys = (Vector) defaultRequestKeys.clone(); requestValues = (Vector) defaultRequestValues.clone(); } } public void addRequestProperty(String name, String value) { setRequestProperty(name, value); } public static void setDefaultRequestProperty(String key, String value) { synchronized (defaultRequestKeys) { int i = 0; while ((i < defaultRequestKeys.size()) && !(key.equalsIgnoreCase((String) defaultRequestKeys.elementAt(i)))) { ++i; } if (i < defaultRequestKeys.size()) { defaultRequestValues.removeElementAt(i); defaultRequestKeys.removeElementAt(i); } if (value != null) { defaultRequestValues.addElement(value); defaultRequestKeys.addElement(key); } } } public static String getDefaultRequestProperty(String key) { synchronized (defaultRequestKeys) { int i = 0; while ((i < defaultRequestKeys.size()) && !(key.equalsIgnoreCase((String) defaultRequestKeys.elementAt(i)))) { ++i; } if (i < defaultRequestKeys.size()) { return (String) defaultRequestValues.elementAt(i); } else { return null; } } } public synchronized void setRequestProperty(String key, String value) { if (connected) { throw new IllegalStateException(Messages.getString("HttpsURLConnection.alreadyConnected")); //$NON-NLS-1$ } int i = 0; while ((i < requestKeys.size()) && !(key.equalsIgnoreCase((String) requestKeys.elementAt(i)))) { ++i; } if (i < requestKeys.size()) { requestValues.removeElementAt(i); requestKeys.removeElementAt(i); } if (value != null) { requestValues.addElement(value); requestKeys.addElement(key); } } public String getRequestProperty(String key) { int i = 0; while ((i < requestKeys.size()) && !(key.equalsIgnoreCase((String) requestKeys.elementAt(i)))) { ++i; } if (i < requestKeys.size()) { return (String) requestValues.elementAt(i); } else { return null; } } public OutputStream getOutputStream() throws IOException { if (!doOutput) { throw new IOException(Messages.getString("HttpsURLConnection.protocolOutputNotConfigured")); //$NON-NLS-1$ } if (connected) { throw new IOException(Messages.getString("HttpsURLConnection.alreadyConnected")); //$NON-NLS-1$ } return output; } private boolean isNonProxiedHost(String host) { String nonProxiedHosts = System.getProperty(httpProxyNonProxyHostsProperty); if (nonProxiedHosts == null || nonProxiedHosts.equals("")) { //$NON-NLS-1$ return false; } StringTokenizer t = new StringTokenizer(nonProxiedHosts, "|"); //$NON-NLS-1$ // TODO add wildcard logic like the sun implementation while (t.hasMoreTokens()) { if (host.equalsIgnoreCase(t.nextToken())) { return true; } } return false; } public synchronized void connect() throws IOException { if (!connected) { // #ifdef DEBUG log.info(MessageFormat.format(Messages.getString("HttpsURLConnection.connecting"), //$NON-NLS-1$ new Object[] { url.getHost(), new Integer(url.getPort() == -1 ? 443 : url.getPort()) })); // #endif String proxyHost = System.getProperty(httpProxyHostProperty); if (proxyHost != null && !isNonProxiedHost(url.getHost())) { boolean isSecure = Boolean.valueOf(System.getProperty(httpProxySecureProperty, "true")) //$NON-NLS-1$ .booleanValue(); String proxyPort = System.getProperty(httpProxyPortProperty); String proxyUsername = System.getProperty(httpProxyUsernameProperty); String proxyPassword = System.getProperty(httpProxyPasswordProperty); // #ifdef DEBUG log.info(MessageFormat.format(Messages.getString("HttpsURLConnection.requiresProxyConnection"), //$NON-NLS-1$ new Object[] { isSecure ? "https" : "http://", proxyHost, new Integer(proxyPort) })); //$NON-NLS-1$ //$NON-NLS-2$ log.info(MessageFormat.format(Messages.getString("HttpsURLConnection.proxyUsername"), new Object[] { //$NON-NLS-1$ proxyUsername == null || proxyUsername.equals("") ? "not set" : proxyUsername })); //$NON-NLS-1$ //$NON-NLS-2$ // #endif if (proxyPort == null) { throw new IOException(Messages.getString("HttpsURLConnection.noProxyPort")); //$NON-NLS-1$ } try { int port = Integer.parseInt(proxyPort); HttpClient client = new HttpClient(proxyHost, port, isSecure); HttpMethod method = new ConnectMethod(url.getHost(), url.getPort() == -1 ? 443 : url.getPort(), true); PasswordCredentials credentials = new PasswordCredentials(); credentials.setUsername(proxyUsername); credentials.setPassword(proxyPassword); client.setCredentials(credentials); HttpResponse response = client.execute(method); socket = response.getConnection().getSocket(); } catch (HttpException ex) { // #ifdef DEBUG log.info(MessageFormat.format(Messages.getString("HttpsURLConnection.proxyConnectionFailed"), //$NON-NLS-1$ new Object[] { ex.getMessage(), new Integer(ex.getStatus()) })); // #endif throw new IOException( MessageFormat.format(Messages.getString("HttpsURLConnection.proxyConnectionFailed"), //$NON-NLS-1$ new Object[] { ex.getMessage(), new Integer(ex.getStatus()) })); //$NON-NLS-2$ //$NON-NLS-3$ } catch (UnsupportedAuthenticationException ex) { // #ifdef DEBUG log.info(Messages.getString("HttpsURLConnection.proxyAuthenticationFailed"), ex); //$NON-NLS-1$ // #endif throw new IOException(ex.getMessage()); } catch (AuthenticationCancelledException ex) { throw new IOException(Messages.getString("HttpsURLConnection.userCancelledAuthenitcation")); //$NON-NLS-1$ } } else { String host = url.getHost(); if (host == null) { throw new IOException(Messages.getString("HttpsURLConnection.noHost")); //$NON-NLS-1$ } int port = url.getPort(); try { socket = new SSLSocket(host, port == -1 ? 443 : port); } catch (SSLException ex1) { throw new SSLIOException(ex1); } } try { writeRequest(socket.getOutputStream()); readResponse(input = new PushbackInputStream(socket.getInputStream(), 2048)); } catch (IOException ex) { try { socket.close(); } catch (IOException ignored) { } throw ex; } connected = true; } } void writeRequest(OutputStream out) throws IOException { DataOutputStream data = new DataOutputStream(new BufferedOutputStream(out)); if ((doOutput) && (output == null)) { throw new IOException(Messages.getString("HttpsURLConnection.noPOSTData")); //$NON-NLS-1$ } if (ifModifiedSince != 0) { Date date = new Date(ifModifiedSince); SimpleDateFormat formatter = new SimpleDateFormat("EEE, d MMM yyyy hh:mm:ss z"); //$NON-NLS-1$ formatter.setTimeZone(TimeZone.getTimeZone("GMT")); //$NON-NLS-1$ setRequestProperty("If-Modified-Since", formatter.format(date)); //$NON-NLS-1$ } if (doOutput) { setRequestProperty("Content-length", "" + output.size()); //$NON-NLS-1$ //$NON-NLS-2$ } data.writeBytes((doOutput ? "POST" : "GET") + " " + (url.getFile().equals("") ? "/" : url.getFile()) //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$//$NON-NLS-5$ + " HTTP/1.0\r\n"); //$NON-NLS-1$ for (int i = 0; i < requestKeys.size(); ++i) { String key = (String) requestKeys.elementAt(i); if (!key.startsWith("Proxy-")) { //$NON-NLS-1$ data.writeBytes(key + ": " + requestValues.elementAt(i) + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ } } data.writeBytes("\r\n"); //$NON-NLS-1$ data.flush(); if (doOutput) { output.writeTo(out); } out.flush(); } void readResponse(PushbackInputStream in) throws IOException { DataInputStream data = new DataInputStream(in); String line; while (((line = data.readLine()) != null) && (line.length() > 0)) { headers.addElement(line); int index = line.indexOf(':'); if (index >= 0) { String key = line.substring(0, index); String value = line.substring(index + 1).trim(); headerKeys.addElement(key); headerValues.put(key.toLowerCase(), value); } else { // If the first line back is not a header, the unread as the // rest is going to be content if (headerValues.size() == 0) { // This is a response code if (line.startsWith("HTTP/")) { //$NON-NLS-1$ try { int idx = line.indexOf(' '); while (line.charAt(++idx) == ' ') { ; } responseMessage = line.substring(idx + 4); responseCode = Integer.parseInt(line.substring(idx, idx + 3)); } catch (Throwable t) { responseCode = 200; } } else { // Just content responseCode = 200; byte[] unread = line.getBytes(); in.unread(unread); break; } } } } } public int getResponseCode() { if (!connected) { throw new IllegalStateException(Messages.getString("HttpsURLConnection.notConnected")); //$NON-NLS-1$ } // if (responseCode == -1) { // responseCode = 200; // Its possible that there wont be a response // code // if(headers.size() > 0) { // String response = getHeaderField(0); // System.out.println("!!!!! REMOVE ME // maverick/src/com/maverick/ssl/https/HttpsURLConnection.getResponseCode() // - response = " + response); // int index = response.indexOf(' '); // while (response.charAt(++index) == ' ') { // ; // } // responseMessage = response.substring(index + 4); // try { // responseCode = Integer.parseInt(response.substring(index, index + // 3)); // } // catch(NumberFormatException nfe) { // // ???? // } // } // } return responseCode; } public String getResponseMessage() { if (!connected) { throw new IllegalStateException(Messages.getString("HttpsURLConnection.notConnected")); //$NON-NLS-1$ } getResponseCode(); return responseMessage; } public String getHeaderField(String name) { if (!connected) { throw new IllegalStateException(Messages.getString("HttpsURLConnection.notConnected")); //$NON-NLS-1$ } return (String) headerValues.get(name.toLowerCase()); } public String getHeaderFieldKey(int n) { if (!connected) { throw new IllegalStateException(Messages.getString("HttpsURLConnection.notConnected")); //$NON-NLS-1$ } if (n < headerKeys.size()) { return (String) headerKeys.elementAt(n); } else { return null; } } public String getHeaderField(int n) { if (!connected) { throw new IllegalStateException(Messages.getString("HttpsURLConnection.notConnected")); //$NON-NLS-1$ } if (n < headers.size()) { return (String) headers.elementAt(n); } else { return null; } } public InputStream getInputStream() throws IOException { if (!doInput) { throw new IOException(Messages.getString("HttpsURLConnection.protocolInputNotConfigured")); //$NON-NLS-1$ } connect(); return input; } public Socket getSocket() { if (!connected) { throw new IllegalStateException(Messages.getString("HttpsURLConnection.notConnected")); //$NON-NLS-1$ } return socket; } public void disconnect() { } public boolean usingProxy() { return System.getProperty(httpProxyHostProperty) != null; } }