/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.axis2.testutils;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Random;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppContext;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.transport.http.AxisServlet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

/**
 * Support for running an embedded Jetty server
 */
public class JettyServer extends AbstractAxis2Server {
    /**
     * The alias of the certificate to configure for Jetty's ssl context factory: {@value}
     */
    private static final String CERT_ALIAS = "server";
    
    /**
     * Webapp resource base directory to use: {@value}
     */
    private static final String WEBAPP_DIR = "target" + File.separator + "webapp";
    
    private static final Log log = LogFactory.getLog(JettyServer.class);
    
    private final boolean secure;
    private File keyStoreFile;
    private SSLContext clientSslContext;
    private SslContextFactory serverSslContextFactory;
    private Server server;
    
    /**
     * Constructor.
     * 
     * @param repositoryPath
     *            The path to the Axis2 repository to use. Must not be null or empty.
     * @param secure
     *            Whether to enable HTTPS.
     */
    public JettyServer(String repositoryPath, boolean secure, AxisServiceFactory... axisServiceFactories) {
        super(repositoryPath, axisServiceFactories);
        this.secure = secure;
    }
    
    private String generatePassword(Random random) {
        char[] password = new char[8];
        for (int i=0; i<password.length; i++) {
            password[i] = (char)('0' + random.nextInt(10));
        }
        return new String(password);
    }
    
    private void writeKeyStore(KeyStore keyStore, File file, String password) throws Exception {
        FileOutputStream out = new FileOutputStream(file);
        try {
            keyStore.store(out, password.toCharArray());
        } finally {
            out.close();
        }
    }
    
    private void generateKeys() throws Exception {
        SecureRandom random = new SecureRandom();
        
        // Generate key pair
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024, random);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        
        // Generate certificate
        X500Name dn = new X500Name("cn=localhost,o=Apache");
        BigInteger serial = BigInteger.valueOf(random.nextInt());
        Date notBefore = new Date();
        Date notAfter = new Date(notBefore.getTime() + 3600000L);
        SubjectPublicKeyInfo subPubKeyInfo =  SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
        X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(dn, serial, notBefore, notAfter, dn, subPubKeyInfo);
        X509CertificateHolder certHolder = certBuilder.build(new JcaContentSignerBuilder("SHA1WithRSA").build(privateKey));
        X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certHolder);
        
        // Build key store
        keyStoreFile = File.createTempFile("keystore", "jks", null);
        String keyStorePassword = generatePassword(random);
        String keyPassword = generatePassword(random);
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(null, null);
        keyStore.setKeyEntry(CERT_ALIAS, privateKey, keyPassword.toCharArray(), new X509Certificate[] { cert });
        writeKeyStore(keyStore, keyStoreFile, keyStorePassword);
        
        // Build trust store
        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(null, null);
        trustStore.setCertificateEntry(CERT_ALIAS, cert);
        
        serverSslContextFactory = new SslContextFactory();
        serverSslContextFactory.setKeyStorePath(keyStoreFile.getAbsolutePath());
        serverSslContextFactory.setKeyStorePassword(keyStorePassword);
        serverSslContextFactory.setKeyManagerPassword(keyPassword);
        serverSslContextFactory.setCertAlias(CERT_ALIAS);
        
        clientSslContext = SSLContext.getInstance("TLS");
        TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmfactory.init(trustStore);
        clientSslContext.init(null, tmfactory.getTrustManagers(), null);
    }
    
    @Override
    public SSLContext getClientSSLContext() throws Exception {
        if (secure) {
            if (clientSslContext == null) {
                generateKeys();
            }
            return clientSslContext;
        } else {
            return null;
        }
    }

    @Override
    protected void startServer(final ConfigurationContext configurationContext) throws Throwable {
        server = new Server();
        
        if (!secure) {
            ServerConnector connector = new ServerConnector(server);
            server.addConnector(connector);
        } else {
            if (serverSslContextFactory == null) {
                generateKeys();
            }
            ServerConnector sslConnector = new ServerConnector(server, serverSslContextFactory);
            server.addConnector(sslConnector);
        }
        
        WebAppContext context = new WebAppContext();
        File webappDir = new File(WEBAPP_DIR);
        if (!webappDir.exists() && !webappDir.mkdirs()) {
            log.error("Failed to create Axis2 webapp directory: " + webappDir.getAbsolutePath());
        }
        
        context.setResourceBase(webappDir.getAbsolutePath());
        context.setContextPath("/axis2");
        context.setParentLoaderPriority(true);
        context.setThrowUnavailableOnStartupException(true);
        
        @SuppressWarnings("serial")
        ServletHolder servlet = new ServletHolder(new AxisServlet() {
            @Override
            protected ConfigurationContext initConfigContext(ServletConfig config)
                    throws ServletException {
                return configurationContext;
            }
        });
        
        //load on startup to trigger Axis2 initialization and service deployment
        //this is for backward compatibility with the SimpleHttpServer which initializes Axis2 on startup
        servlet.setInitOrder(0);
        
        context.addServlet(servlet, "/services/*");
        
        server.setHandler(context);
        
        try {
            server.start();
        }
        catch (SecurityException e) {
            if (e.getMessage().equals("class \"javax.servlet.ServletRequestListener\"'s signer information does not match signer information of other classes in the same package")) {
                log.error(
                 "It is likely your test classpath contains multiple different versions of servlet api.\n" +
                 "If you are running this test in an IDE, please configure it to exclude Rampart's core module servlet api dependency.");
                throw e;
            }
        }
        
        log.info("Server started on port " + getPort());
    }
    
    @Override
    protected void stopServer() {
        if (server != null) {
            log.info("Stop called");
            try {
                server.stop();
            } catch (Exception ex) {
                log.error("Failed to stop Jetty server", ex);
            }
            server = null;
        }
        if (keyStoreFile != null) {
            keyStoreFile.delete();
            keyStoreFile = null;
        }
        clientSslContext = null;
        serverSslContextFactory = null;
    }

    @Override
    public boolean isSecure() {
        return secure;
    }

    /**
     * @return Jetty's http connector port. 
     * @throws IllegalStateException If Jetty is not running or the http connector cannot be found.
     */
    @Override
    public int getPort() throws IllegalStateException {
        if (server == null) {
            throw new IllegalStateException("Jetty server is not initialized");
        }
        if (!server.isStarted()) {
            throw new IllegalStateException("Jetty server is not started");
        }
        
        Connector[] connectors = server.getConnectors();
        if (connectors.length == 0) {
            throw new IllegalStateException("Jetty server is not configured with any connectors");
        }
        
        for (Connector connector : connectors) {
            if (connector instanceof ServerConnector) {
                //must be the http connector
                return ((ServerConnector) connector).getLocalPort();
            }
        }
        
        throw new IllegalStateException("Could not find Jetty http connector");
    }

    @Override
    public String getEndpoint(String serviceName) {
        return String.format("%s://localhost:%s/axis2/services/%s", secure ? "https" : "http", getPort(), serviceName);
    }

    @Override
    public EndpointReference getEndpointReference(String serviceName) {
        return new EndpointReference(getEndpoint(serviceName));
    }
}
