Package hamsam.util.net.ssl

Source Code of hamsam.util.net.ssl.HamsamHttpsConnection

/*
* Hamsam - Instant Messaging API
* Copyright (C) 2003 Raghu K
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package hamsam.util.net.ssl;

import hamsam.net.ProxyInfo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;

/**
* An HTTPS URL connection that uses a proxy tunnel.
*
* @author Raghu
*/
public class HamsamHttpsConnection
{
  /**
   * TrustManager for all SSL connections that we make.
   */
  private static TrustManager[] trustManagers;

  /**
   * SSL context for all SSL connections.
   */
  private static SSLContext sc;

  /**
   * URL for this connection
   */
  private URL url;

  /**
   * The tunnelling SSL socket factory that we use to open
   * all SSL sockets.
   */
  private SSLTunnelSocketFactory factory;

  /**
   * All outgoing headers.
   */
  private Map requestHeaders;

  /**
   * All incoming headers.
   */
  private Map responseHeaders;

  /**
   * In case we recieve a 3xx response, this object is where we
   * redirect to.
   */
  private HamsamHttpsConnection redirection;

  /**
   * The HTTP method to be used for querying.
   */
  private String method;

  static
  {
    trustManagers = new TrustManager[1];
    trustManagers[0] = new HamsamTrustManager();

    try
    {
      sc = SSLContext.getInstance("SSL");
      sc.init(null, trustManagers, new SecureRandom());
    }
    catch(NoSuchAlgorithmException e)
    {
      e.printStackTrace();
      // TODO log this exception
    }
    catch(KeyManagementException e)
    {
      e.printStackTrace();
      // TODO log this exception
    }
  }

  /**
   * Constructs an HTTPS connection to the specified URL.
   *
   * @param urlStr the URL to connect to.
   */
  public HamsamHttpsConnection(String urlStr, ProxyInfo info) throws MalformedURLException
  {
    this(urlStr, new SSLTunnelSocketFactory(sc.getSocketFactory(), info));
  }

  /**
   * Constructs an HTTPS connection to the specified URL using specified
   * SSL socket factory.
   *
   * @param urlStr the URL to connect to.
   * @param factory factory for creating SSL sockets
   */
  private HamsamHttpsConnection(String urlStr, SSLTunnelSocketFactory factory) throws MalformedURLException
  {
    this.url = new URL(urlStr);
    String protocol = url.getProtocol();
    if(protocol == null || !protocol.toLowerCase().equals("https"))
      throw new MalformedURLException("Invalid HTTPS URL: " + urlStr);

    this.factory = factory;

    this.requestHeaders = new HashMap();

    setMethod("GET");
    setHeaderField("Host", url.getHost());
    setHeaderField("Connection", "Keep-Alive");
    setHeaderField("Cache-Control", "no-cache");
  }

  public void doRequest() throws UnknownHostException, IOException
  {
    // Open a socket
    int port = url.getPort();
    port = port == -1 ? url.getDefaultPort() : port;
    SSLSocket sock = (SSLSocket) factory.createSocket(url.getHost(), port);
    sock.startHandshake();

    // Now send the request
    PrintStream out = new PrintStream(sock.getOutputStream());
    out.println(getMethod() + " " + url.getPath() + " HTTP/1.1");
    for(Iterator i = requestHeaders.keySet().iterator(); i.hasNext();)
    {
      String key = (String) i.next();
      String val = (String) requestHeaders.get(key);
      out.println(key + ": " + val);
    }
    out.println();
    out.flush();

    // Read the response
    this.responseHeaders = new HashMap();
    BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));

    // Status line
    String line = in.readLine();
    if(line != null)
      responseHeaders.put(null, line);

    // Check for 3xx status lines
    boolean redirected = false;
    if(line.startsWith("HTTP/1.1 30"))
      redirected = true;

    // Response Headers
    line = in.readLine();
    while(line != null)
    {
      if(line.equals(""))
        break;

      int pos = line.indexOf(":");
      String key = line.substring(0, pos).trim();
      String val = line.substring(pos + 1).trim();
      responseHeaders.put(key, val);
      line = in.readLine();
    }

    // TODO read body

    in.close();
    out.close();

    if(redirected)
    {
      redirection = new HamsamHttpsConnection(getHeaderField("Location"), factory);
      redirection.requestHeaders = this.requestHeaders;
      redirection.doRequest();
    }
  }

  /**
   * Returns a header field from the HTTP response.
   *
   * @param key the header key
   * @return corresponding header value, or <code>null</code> if none found.
   * @throws IllegalStateException if the HTTP request is not already sent.
   */
  public String getHeaderField(String key)
  {
    if(this.responseHeaders == null)
      throw new IllegalStateException("Cannot get headers before sending request.");
    else if(this.redirection != null)
      return this.redirection.getHeaderField(key);
    else
      return (String) this.responseHeaders.get(key);
  }

  /**
   * Set an HTTP header to be sent while sending the request.
   *
   * @param key the header key
   * @param val the header value
   */
  public void setHeaderField(String key, String val)
  {
    this.requestHeaders.put(key, val);
  }

  /**
   * Returns the HTTP method that is used while sending a request.
   *
   * @return the HTTP method.
   */
  public String getMethod()
  {
    return method;
  }

  /**
   * Sets the HTTP method to be used while sending a request.
   *
   * @param method the HTTP method
   */
  public void setMethod(String method)
  {
    this.method = method;
  }
}
TOP

Related Classes of hamsam.util.net.ssl.HamsamHttpsConnection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.