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.apache.log4j.Logger;
023import org.mortbay.jetty.Connector;
024import org.mortbay.jetty.Handler;
025import org.mortbay.jetty.Server;
026import org.mortbay.jetty.handler.DefaultHandler;
027import org.mortbay.jetty.handler.HandlerCollection;
028import org.mortbay.jetty.nio.SelectChannelConnector;
029import org.mortbay.jetty.security.Constraint;
030import org.mortbay.jetty.security.ConstraintMapping;
031import org.mortbay.jetty.security.HashUserRealm;
032import org.mortbay.jetty.security.SecurityHandler;
033import org.mortbay.jetty.security.SslSocketConnector;
034import org.mortbay.jetty.servlet.AbstractSessionManager;
035import org.mortbay.jetty.servlet.FilterHolder;
036import org.mortbay.jetty.servlet.FilterMapping;
037import org.mortbay.jetty.servlet.ServletHolder;
038import org.mortbay.jetty.servlet.SessionHandler;
039import org.mortbay.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
049/**
050 * 
051 */
052public class ServerFixture
053{
054    private static Logger logger = Logger.getLogger( ServerFixture.class );
055
056    public static final String SERVER_ROOT_RESOURCE_PATH = "default-server-root";
057
058    // it seems that some JDKs have a problem if you use different key stores
059    // so we gonna reuse the keystore which is is used in the wagon implementations already
060    public static final String SERVER_SSL_KEYSTORE_RESOURCE_PATH = "ssl/keystore";
061
062    public static final String SERVER_SSL_KEYSTORE_PASSWORD = "wagonhttp";
063
064    public static final String SERVER_HOST = "localhost";
065
066    private final Server server;
067
068    private final WebAppContext webappContext;
069
070    private final HashUserRealm securityRealm;
071
072    private final SecurityHandler securityHandler;
073
074    private int filterCount = 0;
075
076    private int httpPort;
077
078    public ServerFixture( final boolean ssl )
079        throws URISyntaxException, IOException
080    {
081        server = new Server();
082        if ( ssl )
083        {
084            SslSocketConnector connector = new SslSocketConnector();
085            String keystore = getResource( SERVER_SSL_KEYSTORE_RESOURCE_PATH ).getAbsolutePath();
086
087            Logger.getLogger( ServerFixture.class ).info( "TCK Keystore path: " + keystore );
088            System.setProperty( "javax.net.ssl.keyStore", keystore );
089            System.setProperty( "javax.net.ssl.trustStore", keystore );
090
091            // connector.setHost( SERVER_HOST );
092            //connector.setPort( port );
093            connector.setKeystore( keystore );
094            connector.setPassword( SERVER_SSL_KEYSTORE_PASSWORD );
095            connector.setKeyPassword( SERVER_SSL_KEYSTORE_PASSWORD );
096
097            server.addConnector( connector );
098        }
099        else
100        {
101            Connector connector = new SelectChannelConnector();
102            connector.setHost( "localhost" );
103            //connector.setPort( port );
104            server.addConnector( connector );
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 SecurityHandler();
118
119        securityRealm = new HashUserRealm( "Test Server" );
120
121        securityHandler.setUserRealm( securityRealm );
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.addHandler( 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        securityRealm.put( user, password );
163        securityRealm.addUserToRole( user, "allowed" );
164    }
165
166    public Server getServer()
167    {
168        return server;
169    }
170
171    public WebAppContext getWebappContext()
172    {
173        return webappContext;
174    }
175
176    public void stop()
177        throws Exception
178    {
179        if ( server != null )
180        {
181            server.stop();
182        }
183    }
184
185    public void start()
186        throws Exception
187    {
188        if ( server.isStarted() || server.isRunning() )
189        {
190            return;
191        }
192        server.start();
193
194        int total = 0;
195        while ( total < 3 * 1000 && !server.isStarted() )
196        {
197            server.wait( 10 );
198            total += 10;
199        }
200
201        if ( !server.isStarted() )
202        {
203            throw new IllegalStateException( "Server didn't start in: " + total + "ms." );
204        }
205        this.httpPort = server.getConnectors()[0].getLocalPort();
206    }
207
208    public int getHttpPort()
209    {
210        return httpPort;
211    }
212}