001// Copyright (C) 2000 by Matt Towers <eBozo_AT_hotmail_DOT_com>.
002// All rights reserved.  Use of this class is limited.
003// Please see the LICENSE for more information.
004
005/*
006 The source code and object code, of the HttpsMessage class is copyright and
007 owned by Matt Towers. 
008
009 Feel free to use the HttpsMessage class in the development of any development
010 project. For this use you are granted a non-exclusive, non-transferable 
011 limited license at no cost.
012
013 Redistribution of the HttpsMessage source code is permitted provided that the
014 following conditions are met: 
015
016   1.You maintain the original copyright notice in the source code. 
017   2.This license file is redistributed with the source code. 
018   3.You acknowledge that the parent HttpMessage class, with which this class
019     is intended to be used, is owned and copyrighted by Jason Hunter
020     <jhunter_AT_acm_DOT_org>. (For more information see
021     http://www.servlets.com) 
022
023 To clarify, you may use the HttpsMessage class to build new software and may
024 distribute the object code as you see fit. You may NOT distribute the source
025 code as part of a software development kit, other library, or development tool
026 without consent of the copyright holder. Any modified form of the HttpsMessage
027 class is bound by these same restrictions.
028
029 Note that the HttpsMessage class is provided "as is" and the author will not
030 be liable for any damages suffered as a result of your use. 
031 Furthermore, you understand the source code comes without any technical
032 support.
033
034 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
035 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
036 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
037 ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
038 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
039 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
040 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
041 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
042 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
043 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044 SUCH DAMAGE.
045
046 Matt Towers <eBozo_AT_hotmail_DOT_com> 
047*/
048
049package com.oreilly.servlet;
050
051import java.io.*;
052import java.net.*;
053import java.util.*;
054import java.security.Security;
055import java.security.Provider;
056
057/**
058 * A class to simplify HTTP/HTTPS client-server communication.  It abstracts
059 * the communication into messages, which can be either GET or POST.
060 * <p>
061 * It can be used like this:
062 * <blockquote><pre>
063 * &nbsp;
064 * HttpsMessage msg = new HttpsMessage("https://[some server]");
065 * &nbsp;
066 * Properties props = new Properties();
067 * props.put("name", "value");
068 * &nbsp;
069 * InputStream in = msg.sendGetMessage(props);
070 * </pre></blockquote>
071 * This class extends the HttpMessage class
072 * written by Jason Hunter at servlets.com.
073 * The HttpMessage class can be found in the com.oreilly.servlet
074 * package found at www.servlets.com
075 * <p>
076 * For information see http://www.javaworld.com/javatips/jw-javatip96.html
077 * Note this class works with JDK 1.2 or later only.
078 * <p>
079 * @author <b>Matt Towers</b>
080 * @author Copyright &#169; 2000
081 * @version 1.0, 2000/05/05
082 */
083public class HttpsMessage extends com.oreilly.servlet.HttpMessage
084{
085
086  //A flag to indicate weather or not the stream handler has been set
087  static boolean m_bStreamHandlerSet = false;
088
089  /**
090   * Constructs a new HttpsMessage that can be used to communicate with the 
091   * servlet at the specified URL using HTTPS.
092   *
093   * @param szURL the server resource (typically a servlet) with which 
094   * to communicate
095   */
096  public HttpsMessage(String szURL) throws Exception
097  {
098        super(null);
099        //If the stream handler has already been set
100        //there is no need to do anything
101        if( !m_bStreamHandlerSet )
102        {
103                String szVendor = System.getProperty("java.vendor");
104                String szVersion = System.getProperty("java.version");
105                //Assumes a system version string of the form [major].[minor].[release]  (eg. 1.2.2)
106                Double dVersion = new Double(szVersion.substring(0, 3));
107
108                //Otherwise, if we are running in a MS environment, use the MS stream handler.
109                if( -1 < szVendor.indexOf("Microsoft") )
110                {
111                try
112                {
113                        Class clsFactory = Class.forName("com.ms.net.wininet.WininetStreamHandlerFactory" );
114                                if ( null != clsFactory)
115                                        URL.setURLStreamHandlerFactory((URLStreamHandlerFactory)clsFactory.newInstance());
116                        }
117                        catch( ClassNotFoundException cfe )
118                        {
119                                throw new Exception("Unable to load the Microsoft SSL stream handler.  Check classpath."  + cfe.toString());
120                        }                       
121                        //If the stream handler factory has already been successfuly set
122                        //make sure our flag is set and eat the error
123                        catch( Error err ){m_bStreamHandlerSet = true;}
124                }
125                //If we are in a normal Java environment, try to use the JSSE handler.
126                else if( 1.2 <= dVersion.doubleValue() )
127                {
128                        System.getProperties().put("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol"); 
129                        try
130                        {
131                                //if we have the JSSE provider available, and it has not already been
132                                //set, add it as a new provide to the Security class.
133                                Class clsFactory = Class.forName("com.sun.net.ssl.internal.ssl.Provider");
134                                if( (null != clsFactory) && (null == Security.getProvider("SunJSSE")) )
135                                                Security.addProvider((Provider)clsFactory.newInstance());
136                        }
137                        catch( ClassNotFoundException cfe )
138                        {
139                                throw new Exception("Unable to load the JSSE SSL stream handler.  Check classpath."  + cfe.toString());
140                        }
141                }
142                                                                                
143                m_bStreamHandlerSet = true;
144        }
145        
146        super.servlet = new URL(szURL);
147  }
148}