/**
 *    SslUtil utility class
 */

package article.ssl.util;

import javax.servlet.http.*;
import javax.servlet.*;

public class SslUtil {

    private static final String HTTP = "http";
    private static final String HTTPS = "https";
    public static final String HTTP_PORT_PARAM = "listenPort_http";
    public static final String HTTPS_PORT_PARAM = "listenPort_https";
    private static String HTTP_PORT = null;
    private static String HTTPS_PORT = null;
    private static final String STD_HTTP_PORT = "80";
    private static final String STD_HTTPS_PORT = "443";

    static public String getRedirectString(HttpServletRequest request,
            ServletContext servletContext,
            boolean isSecure ){

        initializeSchemePorts(servletContext);

        // get the scheme we want to use for this page and
        // get the scheme used in this request
        String desiredScheme = isSecure? HTTPS: HTTP;
        String usingScheme = request.getScheme();

        // Determine the port number we want to use
        // and the port number we used in this request
        String desiredPort = isSecure? HTTPS_PORT: HTTP_PORT;
        String usingPort = String.valueOf(request.getServerPort());

        String urlString = null;

        // Must also check ports, because of IE multiple redirect problem
        if ( !desiredScheme.equals(usingScheme) || !desiredPort.equals(usingPort)) {

            urlString = buildNewUrlString(request,
                    desiredScheme,
                    usingScheme,
                    desiredPort,
                    usingPort);

            // Temporarily store attributes in session
            RequestUtil.stowRequestAttributes(request);
          }else{
            // Retrieve attributes from session
            RequestUtil.reclaimRequestAttributes(request);
        }

        return urlString;

    }


    /**
     * Initializes the array of ports based on the port init parameters as defined
     * in web.xml
     */
    private static void initializeSchemePorts(ServletContext servletContext){

        if( HTTP_PORT == null){
            String portNumber = servletContext.getInitParameter(HTTP_PORT_PARAM);
            HTTP_PORT = (portNumber == null? STD_HTTP_PORT: portNumber);
        }
        if( HTTPS_PORT == null){
            String portNumber = servletContext.getInitParameter(HTTPS_PORT_PARAM);
            HTTPS_PORT = (portNumber == null? STD_HTTPS_PORT: portNumber);
        }
    }

    /**
     * Builds the URL that we will redirect to
     */
    private static String buildNewUrlString(HttpServletRequest request,
            String desiredScheme,
            String usingScheme,
            String desiredPort,
            String usingPort){

        StringBuffer url = HttpUtils.getRequestURL(request);

        url.replace(0, usingScheme.length(), desiredScheme );

        // Find the port used within the URL string
        int startIndex = url.toString().indexOf(usingPort);

        if( startIndex == -1 ){  // Port not found in URL
            if((!(STD_HTTPS_PORT.equals(desiredPort) && HTTPS.equals(desiredScheme)))
                    && (!(STD_HTTP_PORT.equals(desiredPort) && HTTP.equals(desiredScheme)))){
                startIndex = url.toString().indexOf("/", url.toString().indexOf("/", url.toString().indexOf("/")+1)+1);
                url.insert(startIndex, ":" + desiredPort);
            }
        }else{  // Port found in URL
            if((STD_HTTPS_PORT.equals(desiredPort) && HTTPS.equals(desiredScheme))
                    || (STD_HTTP_PORT.equals(desiredPort) && HTTP.equals(desiredScheme))){
                url.delete(startIndex-1, startIndex + usingPort.length());
            } else {  // desired port is not a default port
                // Replace requested port with desired port number in URL string
                url.replace(startIndex, startIndex + usingPort.length(), desiredPort );
            }
        }

        // add query string, if any
        String queryString = request.getQueryString();
        if (queryString != null && queryString.length() != 0 ) {
            url.append("?"+queryString);
        }else{
            queryString =  RequestUtil.getRequestParameters( request );
            if (queryString != null && queryString.length() != 0 ) {
                url.append("?"+queryString);
            }
        }

        return url.toString();
    }

}

/**
 *    RequestUtil utility class
 */

package article.ssl.util;

import javax.servlet.http.* ;
import java.util.Enumeration ;
import java.util.*;

public class RequestUtil {

    private static final String STOWED_REQUEST_ATTRIBS =
        "ssl.redirect.attrib.stowed";

    /**
     * Creates query String from request body parameters
     */
    public static String getRequestParameters( HttpServletRequest aRequest ){
        StringBuffer aReturn = new StringBuffer("");
        Map m = aRequest.getParameterMap();
        Set aEntryS = m.entrySet();
        Iterator aEntryI = aEntryS.iterator();
        while (aEntryI.hasNext()) {
            Map.Entry aEntry = (Map.Entry) aEntryI.next();
            List aValues = (List) aEntry.getValue();
            for (int i = 0; i < aValues.size(); i++) {
                if (aReturn.length() > 0) {
                    aReturn.append("&");
                }
                aReturn.append(aEntry.getKey());
                aReturn.append("=");
                aReturn.append(aValues.get(i));
            }
        }
        return aReturn.toString();
    }

    /**
     * Stores request attributes in session
     */
    public static void stowRequestAttributes( HttpServletRequest aRequest ){

        if( aRequest.getSession().getAttribute(STOWED_REQUEST_ATTRIBS) != null){
            return;
        }

        Enumeration enum = aRequest.getAttributeNames();
        Map map = new HashMap();
        while( enum.hasMoreElements() ){
            String name = (String)enum.nextElement();
            map.put(name, aRequest.getAttribute(name));
        }
        aRequest.getSession().setAttribute(STOWED_REQUEST_ATTRIBS, map);
    }


    /**
     * Returns request attributes from session to request
     */
    public static void reclaimRequestAttributes(HttpServletRequest aRequest ){
        Map map = (Map)aRequest.getSession().getAttribute(STOWED_REQUEST_ATTRIBS);

        if( map == null ){
            return;
        }

        Iterator itr = map.keySet().iterator();
        while(itr.hasNext()){
            String name = (String)itr.next();

            aRequest.setAttribute(name, map.get(name));
        }

        aRequest.getSession().removeAttribute(STOWED_REQUEST_ATTRIBS);
    }
}