package org.apache.maven.it;

/*
 * 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.
 */

import org.apache.maven.it.util.ResourceExtractor;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;

import static org.eclipse.jetty.http.HttpVersion.HTTP_1_1;

/**
 * This is a test set for <a href="https://issues.apache.org/jira/browse/MNG-2305">MNG-2305</a>.
 * 
 * @author Benjamin Bentmann
 */
public class MavenITmng2305MultipleProxiesTest
    extends AbstractMavenIntegrationTestCase
{

    public MavenITmng2305MultipleProxiesTest()
    {
        super( "[3.0-alpha-3,)" );
    }

    /**
     * Verify that proxies can be setup for multiple protocols, in this case HTTP and HTTPS. As a nice side effect,
     * this checks HTTPS tunneling over a web proxy.
     */
    public void testit()
        throws Exception
    {
        File testDir = ResourceExtractor.simpleExtractResources( getClass(), "/mng-2305" );

        Verifier verifier = newVerifier( testDir.getAbsolutePath() );

        // NOTE: trust store cannot be reliably configured for the current JVM
        verifier.setForkJvm( true );

        // keytool -genkey -alias https.mngit -keypass key-passwd -keystore keystore -storepass store-passwd \
        //   -validity 4096 -dname "cn=https.mngit, ou=None, L=Seattle, ST=Washington, o=ExampleOrg, c=US" -keyalg RSA
        String storePath = new File( testDir, "keystore" ).getAbsolutePath();
        String storePwd = "store-passwd";
        String keyPwd = "key-passwd";

        Server server = new Server( 0 );
        addHttpsConnector( server, storePath, storePwd, keyPwd );
        server.setHandler( new RepoHandler() );
        server.start();
        if ( server.isFailed() )
        {
            fail( "Couldn't bind the server socket to a free port!" );
        }
        int httpPort = ( (NetworkConnector) server.getConnectors()[0] ).getLocalPort();
        System.out.println( "Bound server socket to HTTP port " + httpPort );
        int httpsPort = ( (NetworkConnector) server.getConnectors()[1] ).getLocalPort();
        System.out.println( "Bound server socket to HTTPS port " + httpsPort );

        TunnelingProxyServer proxy = new TunnelingProxyServer( 0, "localhost", httpsPort, "https.mngit:443" );
        proxy.start();
        int proxyPort = proxy.getPort();
        System.out.println( "Bound server socket to the proxy port " + proxyPort );

        try
        {
            verifier.setAutoclean( false );
            verifier.deleteDirectory( "target" );
            verifier.deleteArtifacts( "org.apache.maven.its.mng2305" );
            Properties filterProps = verifier.newDefaultFilterProperties();
            filterProps.setProperty( "@proxy.http@", Integer.toString( httpPort ) );
            filterProps.setProperty( "@proxy.https@", Integer.toString( proxyPort ) );
            verifier.filterFile( "settings-template.xml", "settings.xml", "UTF-8", filterProps );
            verifier.addCliOption( "--settings" );
            verifier.addCliOption( "settings.xml" );
            verifier.setSystemProperty( "javax.net.ssl.trustStore", storePath );
            verifier.setSystemProperty( "javax.net.ssl.trustStorePassword", storePwd );
            // disable concurrent downloading as not all wagons (e.g. wagon-lightweight-http) are thread-safe regarding proxy settings
            verifier.setSystemProperty( "maven.artifact.threads", "1" );
            verifier.executeGoal( "validate" );
            verifier.verifyErrorFreeLog();
            verifier.resetStreams();
        }
        finally
        {
            proxy.stop();
            server.stop();
            server.join();
        }

        List<String> cp = verifier.loadLines( "target/classpath.txt", "UTF-8" );
        assertTrue( cp.toString(), cp.contains( "http-0.1.jar" ) );
        assertTrue( cp.toString(), cp.contains( "https-0.1.jar" ) );
    }

    private void addHttpsConnector( Server server, String keyStorePath, String keyStorePassword, String keyPassword )
    {
        SslContextFactory sslContextFactory = new SslContextFactory( keyStorePath );
        sslContextFactory.setKeyStorePassword( keyStorePassword );
        sslContextFactory.setKeyManagerPassword( keyPassword );
        HttpConfiguration httpConfiguration = new HttpConfiguration();
        httpConfiguration.setSecureScheme( "https" );
        HttpConfiguration httpsConfiguration = new HttpConfiguration( httpConfiguration );
        httpsConfiguration.addCustomizer( new SecureRequestCustomizer() );
        ServerConnector httpsConnector = new ServerConnector( server,
                new SslConnectionFactory( sslContextFactory, HTTP_1_1.asString() ),
                new HttpConnectionFactory( httpsConfiguration ) );
        server.addConnector( httpsConnector );
    }

    static class RepoHandler extends AbstractHandler
    {
        public void handle( String target, Request baseRequest, HttpServletRequest request,
                            HttpServletResponse response )
            throws IOException
        {
            PrintWriter writer = response.getWriter();

            String uri = request.getRequestURI();

            if ( !uri.startsWith( "/repo/org/apache/maven/its/mng2305/" + request.getScheme() + "/" ) )
            {
                // HTTP connector serves only http-0.1.jar and HTTPS connector serves only https-0.1.jar
                response.setStatus( HttpServletResponse.SC_NOT_FOUND );
            }
            else if ( uri.endsWith( ".pom" ) )
            {
                writer.println( "<project>" );
                writer.println( "  <modelVersion>4.0.0</modelVersion>" );
                writer.println( "  <groupId>org.apache.maven.its.mng2305</groupId>" );
                writer.println( "  <artifactId>" + request.getScheme() + "</artifactId>" );
                writer.println( "  <version>0.1</version>" );
                writer.println( "</project>" );
                response.setStatus( HttpServletResponse.SC_OK );
            }
            else if ( uri.endsWith( ".jar" ) )
            {
                writer.println( "empty" );
                response.setStatus( HttpServletResponse.SC_OK );
            }
            else
            {
                response.setStatus( HttpServletResponse.SC_NOT_FOUND );
            }

            ( (Request) request ).setHandled( true );
        }
    }
}
