/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */
package com.sun.web.security;

import java.io.*;
import java.net.*;
import java.security.KeyStore;
import java.security.SecureRandom;

import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.TrustManager;
import org.apache.catalina.net.ServerSocketFactory;
import com.sun.enterprise.log.Log;
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.security.SSLUtils;
import com.sun.enterprise.ServerConfiguration;
import com.sun.web.server.*;
import com.sun.enterprise.server.J2EEServer;
import java.util.logging.*;
import com.sun.logging.*;


/**
 * SSL server socket factory. 
 *
 * @author Harish Prabandham
 * @author Vivek Nagar
 * @author Harpreet Singh
 */

public class SSLSocketFactory implements org.apache.catalina.net.ServerSocketFactory {

    static Logger _logger=LogDomains.getLogger(LogDomains.WEB_LOGGER);

    private static final boolean clientAuth = false;

    private static LocalStringManagerImpl localStrings = 
	new LocalStringManagerImpl(SSLSocketFactory.class);

    private SSLContext context = null;
    private javax.net.ssl.SSLServerSocketFactory factory = null;
    private String cipherSuites[];
    private static SecureRandom sr = J2EEServer.secureRandom;
    private static KeyManager[] keyManagers = null;
    private static TrustManager[] trustManagers = null;


    /**
     * Create the SSL socket factory. Initialize the key managers and
     * trust managers which are passed to the SSL context.
     */
    public SSLSocketFactory () {
	try {
	    if(keyManagers == null || trustManagers == null) {
		SSLUtils.initStoresAtStartup();
	    }
	    context = SSLContext.getInstance("TLS");
	    context.init(keyManagers, trustManagers, sr);

	    factory = context.getServerSocketFactory();
	    cipherSuites = factory.getSupportedCipherSuites();
	    
            for(int i=0; i < cipherSuites.length; ++i) {
                if (_logger.isLoggable(Level.FINEST)) {
                    _logger.log(Level.FINEST,"Suite: " + cipherSuites[i]);
                }
	    }
            
	} catch(Exception e) {
	  _logger.log(Level.SEVERE,
                      "web_security.excep_sslsockfact", e.getMessage());
	}
    }

    /**
     * Create the socket at the specified port.
     * @param the port number.
     * @return the SSL server socket.
     */
    public ServerSocket createSocket (int port)
    throws IOException
    {
	SSLServerSocket socket = 
	    (SSLServerSocket) factory.createServerSocket(port);
	init(socket);
	return socket;
    }

    /**
     * Specify whether the server will require client authentication.
     * @param the SSL server socket.
     */
    private void init(SSLServerSocket socket) {
	// Some initialization goes here.....
	// socket.setEnabledCipherSuites(cipherSuites);
	socket.setNeedClientAuth(clientAuth);
    }

    /**
     * Create the socket at the specified port.
     * @param the port number.
     * @return the SSL server socket.
     */
    public ServerSocket createSocket (int port, int backlog)
    throws IOException
    {
	SSLServerSocket socket = (SSLServerSocket)
	    factory.createServerSocket(port, backlog);
	init(socket);
	return socket;
    }

    /**
     * Create the socket at the specified port.
     * @param the port number.
     * @return the SSL server socket.
     */
    public ServerSocket createSocket (int port, int backlog, InetAddress ifAddress)
    throws IOException
    {
	SSLServerSocket socket = (SSLServerSocket)
	    factory.createServerSocket(port, backlog, ifAddress);
	init(socket);
	return socket;
    }

    public static void setManagers(KeyManager[] kmgrs, TrustManager[] tmgrs) {
        keyManagers = kmgrs;
        trustManagers = tmgrs;
    }
}
