/*
 *   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.directory.server.integration.http;


import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.OutputStream;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.server.bridge.http.HttpDirectoryService;
import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.security.TlsKeyGenerator;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;
import org.bouncycastle.jce.provider.X509CertParser;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.ContextHandler;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.security.SslSocketConnector;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.xml.XmlConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Class to start the jetty http server
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class HttpServer
{

    /** the jetty http server instance */
    private Server jetty;

    /** jetty config file */
    private String confFile;

    /** a collection to hold the configured web applications */
    private Set<WebApp> webApps;

    /** Transport for http */
    private TcpTransport httpTransport = null;

    /** Transport for https */
    private TcpTransport httpsTransport = null;

    /** protocol identifier for http */
    public static final String HTTP_TRANSPORT_ID = "http";

    /** protocol identifier for https */
    public static final String HTTPS_TRANSPORT_ID = "https";

    /** an internal flag to check the server configuration */
    private boolean configured = false;

    private static final Logger LOG = LoggerFactory.getLogger( HttpServer.class );

    private DirectoryService dirService;


    public HttpServer()
    {
    }


    /**
     * starts the jetty http server
     * 
     * @throws Exception
     */
    public void start( DirectoryService dirService ) throws Exception
    {
        this.dirService = dirService;

        XmlConfiguration jettyConf = null;

        if ( confFile != null )
        {
            jettyConf = new XmlConfiguration( new FileInputStream( confFile ) );

            LOG.info( "configuring jetty http server from the configuration file {}", confFile );

            try
            {
                jetty = new Server();
                jettyConf.configure( jetty );
                configured = true;
            }
            catch ( Exception e )
            {
                LOG.error( I18n.err( I18n.ERR_120 ) );
                throw e;
            }
        }
        else
        {
            LOG.info( "No configuration file set, looking for web apps" );
            configureServerThroughCode();
        }

        if ( configured )
        {
            Handler[] handlers = jetty.getHandlers();

            for ( Handler h : handlers )
            {
                if ( h instanceof ContextHandler )
                {
                    ContextHandler ch = ( ContextHandler ) h;
                    ch.setAttribute( HttpDirectoryService.KEY, new HttpDirectoryService( dirService ) );
                }
            }

            LOG.info( "starting jetty http server" );
            jetty.start();
        }
        else
        {
            jetty = null;
            LOG.warn( "Error while configuring the http server, skipping the http server startup" );
        }
    }


    /*
     * configure the jetty server programmatically without using any configuration file 
     */
    private void configureServerThroughCode()
    {
        try
        {
            jetty = new Server();

            if ( httpTransport != null )
            {
                SelectChannelConnector httpConnector = new SelectChannelConnector();
                httpConnector.setPort( httpTransport.getPort() );
                httpConnector.setHost( httpTransport.getAddress() );
                jetty.addConnector( httpConnector );
            }

            if ( httpsTransport != null )
            {
                // load the admin entry to get the private key and certificate
                Dn adminDn = dirService.getDnFactory().create( ServerDNConstants.ADMIN_SYSTEM_DN );
                Entry adminEntry = dirService.getAdminSession().lookup( adminDn, "*", "+" );

                File confDir = dirService.getInstanceLayout().getConfDirectory();
                File ksFile = new File( confDir, "httpserver.generated.ks" );

                String password = UUID.randomUUID().toString();

                KeyStore ks = KeyStore.getInstance( KeyStore.getDefaultType() );
                ks.load( null, null );

                X509CertParser parser = new X509CertParser();

                parser.engineInit( new ByteArrayInputStream( adminEntry.get( TlsKeyGenerator.USER_CERTIFICATE_AT )
                    .getBytes() ) );

                X509Certificate cert = ( X509Certificate ) parser.engineRead();

                ks.setCertificateEntry( "cert", cert );

                KeyPair keyPair = TlsKeyGenerator.getKeyPair( adminEntry );
                ks.setKeyEntry( "privatekey", keyPair.getPrivate(), password.toCharArray(), new Certificate[]
                    { cert } );

                OutputStream stream = new FileOutputStream( ksFile );
                ks.store( stream, password.toCharArray() );
                stream.close();

                SslSocketConnector httpsConnector = new SslSocketConnector();
                httpsConnector.setPort( httpsTransport.getPort() );
                httpsConnector.setHost( httpsTransport.getAddress() );
                httpsConnector.setKeystoreType( ks.getType() );
                httpsConnector.setKeystore( ksFile.getAbsolutePath() );
                httpsConnector.setPassword( password );
                httpsConnector.setKeyPassword( password );

                jetty.addConnector( httpsConnector );
            }

            List<Handler> handlers = new ArrayList<Handler>();
            for ( WebApp w : webApps )
            {
                WebAppContext webapp = new WebAppContext();
                webapp.setWar( w.getWarFile() );
                webapp.setContextPath( w.getContextPath() );
                handlers.add( webapp );

                webapp.setParentLoaderPriority( true );
            }

            // add web apps from the webapps directory inside directory service's working directory
            // the exploded or archived wars
            File webAppDir = new File( dirService.getInstanceLayout().getInstanceDirectory(), "webapps" );

            FilenameFilter webAppFilter = new FilenameFilter()
            {

                public boolean accept( File dir, String name )
                {
                    return name.endsWith( ".war" );
                }
            };

            if ( webAppDir.exists() )
            {
                File[] appList = webAppDir.listFiles( webAppFilter );
                for ( File app : appList )
                {
                    WebAppContext webapp = new WebAppContext();
                    webapp.setWar( app.getAbsolutePath() );
                    String ctxName = app.getName();
                    int pos = ctxName.indexOf( '.' );
                    if ( pos > 0 )
                    {
                        ctxName = ctxName.substring( 0, pos );
                    }

                    webapp.setContextPath( "/" + ctxName );
                    handlers.add( webapp );

                    webapp.setParentLoaderPriority( true );
                }
            }

            jetty.setHandlers( handlers.toArray( new Handler[handlers.size()] ) );

            configured = true;
        }
        catch ( Exception e )
        {
            LOG.error( I18n.err( I18n.ERR_121 ), e );
        }

    }


    /**
     * stops the jetty http server
     * 
     * @throws Exception
     */
    public void stop() throws Exception
    {
        if ( jetty != null && jetty.isStarted() )
        {
            LOG.info( "stopping jetty http server" );
            jetty.stop();
        }
    }


    public void setConfFile( String confFile )
    {
        this.confFile = confFile;
    }


    public Set<WebApp> getWebApps()
    {
        return webApps;
    }


    public void setWebApps( Set<WebApp> webapps )
    {
        this.webApps = webapps;
    }


    public TcpTransport getHttpTransport()
    {
        return httpTransport;
    }


    public void setHttpTransport( TcpTransport httpTransport )
    {
        this.httpTransport = httpTransport;
    }


    public TcpTransport getHttpsTransport()
    {
        return httpsTransport;
    }


    public void setHttpsTransport( TcpTransport httpsTransport )
    {
        this.httpsTransport = httpsTransport;
    }

}
