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.server.Connector;
023import org.eclipse.jetty.server.Handler;
024import org.eclipse.jetty.server.Server;
025import org.eclipse.jetty.server.handler.DefaultHandler;
026import org.eclipse.jetty.server.handler.HandlerCollection;
027import org.eclipse.jetty.server.nio.SelectChannelConnector;
028import org.eclipse.jetty.server.session.AbstractSessionManager;
029import org.eclipse.jetty.server.session.SessionHandler;
030import org.eclipse.jetty.security.ConstraintMapping;
031import org.eclipse.jetty.security.ConstraintSecurityHandler;
032import org.eclipse.jetty.security.HashLoginService;
033import org.eclipse.jetty.server.ssl.SslSocketConnector;
034import org.eclipse.jetty.servlet.FilterHolder;
035import org.eclipse.jetty.servlet.FilterMapping;
036import org.eclipse.jetty.servlet.ServletHolder;
037import org.eclipse.jetty.util.security.Constraint;
038import org.eclipse.jetty.util.security.Password;
039import org.eclipse.jetty.webapp.WebAppContext;
040
041import javax.servlet.Filter;
042import javax.servlet.Servlet;
043import java.io.File;
044import java.io.IOException;
045import java.net.URISyntaxException;
046
047import static org.apache.maven.wagon.tck.http.util.TestUtil.getResource;
048
049import org.slf4j.Logger;
050import org.slf4j.LoggerFactory;
051
052/**
053 *
054 */
055public class ServerFixture
056{
057    private static Logger logger = LoggerFactory.getLogger( ServerFixture.class );
058
059    public static final String SERVER_ROOT_RESOURCE_PATH = "default-server-root";
060
061    // it seems that some JDKs have a problem if you use different key stores
062    // so we gonna reuse the keystore which is is used in the wagon implementations already
063    public static final String SERVER_SSL_KEYSTORE_RESOURCE_PATH = "ssl/keystore";
064
065    public static final String SERVER_SSL_KEYSTORE_PASSWORD = "wagonhttp";
066
067    public static final String SERVER_HOST = "localhost";
068
069    private final Server server;
070
071    private final WebAppContext webappContext;
072
073    private final HashLoginService loginService;
074
075    private final ConstraintSecurityHandler securityHandler;
076
077    private int filterCount = 0;
078
079    private int httpPort;
080
081    public ServerFixture( final boolean ssl )
082        throws URISyntaxException, IOException
083    {
084        server = new Server();
085        if ( ssl )
086        {
087            SslSocketConnector connector = new SslSocketConnector();
088            String keystore = getResource( SERVER_SSL_KEYSTORE_RESOURCE_PATH ).getAbsolutePath();
089
090            LoggerFactory.getLogger( ServerFixture.class ).info( "TCK Keystore path: " + keystore );
091            System.setProperty( "javax.net.ssl.keyStore", keystore );
092            System.setProperty( "javax.net.ssl.trustStore", keystore );
093
094            // connector.setHost( SERVER_HOST );
095            //connector.setPort( port );
096            connector.setKeystore( keystore );
097            connector.setPassword( SERVER_SSL_KEYSTORE_PASSWORD );
098            connector.setKeyPassword( SERVER_SSL_KEYSTORE_PASSWORD );
099
100            server.addConnector( connector );
101        }
102        else
103        {
104            Connector connector = new SelectChannelConnector();
105            connector.setHost( "localhost" );
106            //connector.setPort( port );
107            server.addConnector( connector );
108        }
109
110        Constraint constraint = new Constraint();
111        constraint.setName( Constraint.__BASIC_AUTH );
112
113        constraint.setRoles( new String[]{ "allowed" } );
114        constraint.setAuthenticate( true );
115
116        ConstraintMapping cm = new ConstraintMapping();
117        cm.setConstraint( constraint );
118        cm.setPathSpec( "/protected/*" );
119
120        securityHandler = new ConstraintSecurityHandler();
121
122        loginService = new HashLoginService( "Test Server" );
123
124        securityHandler.setLoginService( loginService );
125        securityHandler.setConstraintMappings( new ConstraintMapping[]{ cm } );
126
127        webappContext = new WebAppContext();
128        webappContext.setContextPath( "/" );
129
130        File base = getResource( SERVER_ROOT_RESOURCE_PATH );
131        logger.info( "docroot: " + base );
132        webappContext.setWar( base.getAbsolutePath() );
133        webappContext.setHandler( securityHandler );
134
135        SessionHandler sessionHandler = webappContext.getSessionHandler();
136        ( (AbstractSessionManager) sessionHandler.getSessionManager() ).setUsingCookies( false );
137
138        HandlerCollection handlers = new HandlerCollection();
139        handlers.setHandlers( new Handler[]{ webappContext, new DefaultHandler() } );
140
141        server.setHandler( handlers );
142    }
143
144    public void addFilter( final String pathSpec, final Filter filter )
145    {
146        String name = "filter" + filterCount++;
147
148        FilterMapping fm = new FilterMapping();
149        fm.setPathSpec( pathSpec );
150        fm.setFilterName( name );
151
152        FilterHolder fh = new FilterHolder( filter );
153        fh.setName( name );
154
155        webappContext.getServletHandler().addFilter( fh, fm );
156    }
157
158    public void addServlet( final String pathSpec, final Servlet servlet )
159    {
160        webappContext.getServletHandler().addServletWithMapping( new ServletHolder( servlet ), pathSpec );
161    }
162
163    public void addUser( final String user, final String password )
164    {
165        loginService.putUser( user, new Password( password ), new String[] { "allowed" } );
166    }
167
168    public Server getServer()
169    {
170        return server;
171    }
172
173    public WebAppContext getWebappContext()
174    {
175        return webappContext;
176    }
177
178    public void stop()
179        throws Exception
180    {
181        if ( server != null )
182        {
183            server.stop();
184        }
185    }
186
187    public void start()
188        throws Exception
189    {
190        if ( server.isStarted() || server.isRunning() )
191        {
192            return;
193        }
194        server.start();
195
196        int total = 0;
197        while ( total < 3 * 1000 && !server.isStarted() )
198        {
199            server.wait( 10 );
200            total += 10;
201        }
202
203        if ( !server.isStarted() )
204        {
205            throw new IllegalStateException( "Server didn't start in: " + total + "ms." );
206        }
207        this.httpPort = server.getConnectors()[0].getLocalPort();
208    }
209
210    public int getHttpPort()
211    {
212        return httpPort;
213    }
214}