001package org.apache.maven.wagon.tck.http.fixture;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.eclipse.jetty.security.ConstraintMapping;
023import org.eclipse.jetty.security.ConstraintSecurityHandler;
024import org.eclipse.jetty.security.HashLoginService;
025import org.eclipse.jetty.server.Handler;
026import org.eclipse.jetty.server.Server;
027import org.eclipse.jetty.server.ServerConnector;
028import org.eclipse.jetty.server.handler.DefaultHandler;
029import org.eclipse.jetty.server.handler.HandlerCollection;
030import org.eclipse.jetty.server.session.AbstractSessionManager;
031import org.eclipse.jetty.server.session.SessionHandler;
032import org.eclipse.jetty.servlet.FilterHolder;
033import org.eclipse.jetty.servlet.FilterMapping;
034import org.eclipse.jetty.servlet.ServletHolder;
035import org.eclipse.jetty.util.security.Constraint;
036import org.eclipse.jetty.util.security.Password;
037import org.eclipse.jetty.util.ssl.SslContextFactory;
038import org.eclipse.jetty.webapp.WebAppContext;
039import org.slf4j.Logger;
040import org.slf4j.LoggerFactory;
041
042import javax.servlet.Filter;
043import javax.servlet.Servlet;
044import java.io.File;
045import java.io.IOException;
046import java.net.URISyntaxException;
047
048import static org.apache.maven.wagon.tck.http.util.TestUtil.getResource;
049
050/**
051 *
052 */
053public class ServerFixture
054{
055    private static Logger logger = LoggerFactory.getLogger( ServerFixture.class );
056
057    public static final String SERVER_ROOT_RESOURCE_PATH = "default-server-root";
058
059    // it seems that some JDKs have a problem if you use different key stores
060    // so we gonna reuse the keystore which is is used in the wagon implementations already
061    public static final String SERVER_SSL_KEYSTORE_RESOURCE_PATH = "ssl/keystore";
062
063    public static final String SERVER_SSL_KEYSTORE_PASSWORD = "wagonhttp";
064
065    public static final String SERVER_HOST = "localhost";
066
067    private final Server server;
068    private ServerConnector serverConnector;
069
070    private final WebAppContext webappContext;
071
072    private final HashLoginService loginService;
073
074    private final ConstraintSecurityHandler securityHandler;
075
076    private int filterCount = 0;
077
078    private int httpPort;
079
080    public ServerFixture( final boolean ssl )
081        throws URISyntaxException, IOException
082    {
083        server = new Server();
084        if ( ssl )
085        {
086            String keystore = getResource( SERVER_SSL_KEYSTORE_RESOURCE_PATH ).getAbsolutePath();
087
088            LoggerFactory.getLogger( ServerFixture.class ).info( "TCK Keystore path: " + keystore );
089            System.setProperty( "javax.net.ssl.keyStore", keystore );
090            System.setProperty( "javax.net.ssl.trustStore", keystore );
091
092            SslContextFactory sslContextFactory = new SslContextFactory();
093            sslContextFactory.setKeyStorePath( keystore );
094            sslContextFactory.setKeyStorePassword( SERVER_SSL_KEYSTORE_PASSWORD );
095            sslContextFactory.setKeyManagerPassword( SERVER_SSL_KEYSTORE_PASSWORD );
096            serverConnector = new ServerConnector( server, sslContextFactory );
097            server.addConnector( serverConnector );
098        }
099        else
100        {
101            serverConnector = new ServerConnector( server );
102            serverConnector.setHost( "localhost" );
103            //connector.setPort( port );
104            server.addConnector( serverConnector );
105        }
106
107        Constraint constraint = new Constraint();
108        constraint.setName( Constraint.__BASIC_AUTH );
109
110        constraint.setRoles( new String[]{ "allowed" } );
111        constraint.setAuthenticate( true );
112
113        ConstraintMapping cm = new ConstraintMapping();
114        cm.setConstraint( constraint );
115        cm.setPathSpec( "/protected/*" );
116
117        securityHandler = new ConstraintSecurityHandler();
118
119        loginService = new HashLoginService( "Test Server" );
120
121        securityHandler.setLoginService( loginService );
122        securityHandler.setConstraintMappings( new ConstraintMapping[]{ cm } );
123
124        webappContext = new WebAppContext();
125        webappContext.setContextPath( "/" );
126
127        File base = getResource( SERVER_ROOT_RESOURCE_PATH );
128        logger.info( "docroot: " + base );
129        webappContext.setWar( base.getAbsolutePath() );
130        webappContext.setHandler( securityHandler );
131
132        SessionHandler sessionHandler = webappContext.getSessionHandler();
133        ( (AbstractSessionManager) sessionHandler.getSessionManager() ).setUsingCookies( false );
134
135        HandlerCollection handlers = new HandlerCollection();
136        handlers.setHandlers( new Handler[]{ webappContext, new DefaultHandler() } );
137
138        server.setHandler( handlers );
139    }
140
141    public void addFilter( final String pathSpec, final Filter filter )
142    {
143        String name = "filter" + filterCount++;
144
145        FilterMapping fm = new FilterMapping();
146        fm.setPathSpec( pathSpec );
147        fm.setFilterName( name );
148
149        FilterHolder fh = new FilterHolder( filter );
150        fh.setName( name );
151
152        webappContext.getServletHandler().addFilter( fh, fm );
153    }
154
155    public void addServlet( final String pathSpec, final Servlet servlet )
156    {
157        webappContext.getServletHandler().addServletWithMapping( new ServletHolder( servlet ), pathSpec );
158    }
159
160    public void addUser( final String user, final String password )
161    {
162        loginService.putUser( user, new Password( password ), new String[] { "allowed" } );
163    }
164
165    public Server getServer()
166    {
167        return server;
168    }
169
170    public WebAppContext getWebappContext()
171    {
172        return webappContext;
173    }
174
175    public void stop()
176        throws Exception
177    {
178        if ( server != null )
179        {
180            server.stop();
181        }
182    }
183
184    public void start()
185        throws Exception
186    {
187        if ( server.isStarted() || server.isRunning() )
188        {
189            return;
190        }
191        server.start();
192
193        int total = 0;
194        while ( total < 3 * 1000 && !server.isStarted() )
195        {
196            server.wait( 10 );
197            total += 10;
198        }
199
200        if ( !server.isStarted() )
201        {
202            throw new IllegalStateException( "Server didn't start in: " + total + "ms." );
203        }
204        this.httpPort = serverConnector.getLocalPort();
205    }
206
207    public int getHttpPort()
208    {
209        return httpPort;
210    }
211}