001package org.apache.maven.wagon.providers.http;
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.http.HttpEntity;
023import org.apache.http.HttpException;
024import org.apache.http.HttpStatus;
025import org.apache.http.client.methods.CloseableHttpResponse;
026import org.apache.http.client.methods.HttpGet;
027import org.apache.http.util.EntityUtils;
028import org.apache.maven.wagon.ResourceDoesNotExistException;
029import org.apache.maven.wagon.TransferFailedException;
030import org.apache.maven.wagon.authorization.AuthorizationException;
031import org.apache.maven.wagon.shared.http.AbstractHttpClientWagon;
032import org.apache.maven.wagon.shared.http.HtmlFileListParser;
033import org.apache.maven.wagon.shared.http.HttpMessageUtils;
034
035import java.io.IOException;
036import java.util.Collections;
037import java.util.List;
038
039import static org.apache.maven.wagon.shared.http.HttpMessageUtils.formatResourceDoesNotExistMessage;
040import static org.apache.maven.wagon.shared.http.HttpMessageUtils.formatTransferDebugMessage;
041import static org.apache.maven.wagon.shared.http.HttpMessageUtils.formatTransferFailedMessage;
042
043/**
044 * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
045 */
046public class HttpWagon
047    extends AbstractHttpClientWagon
048{
049
050    public List<String> getFileList( String destinationDirectory )
051        throws AuthorizationException, ResourceDoesNotExistException, TransferFailedException
052    {
053        return getFileList( getInitialBackoffSeconds(), destinationDirectory );
054    }
055
056    private List<String> getFileList( int wait, String destinationDirectory )
057        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
058    {
059        if ( destinationDirectory.length() > 0 && !destinationDirectory.endsWith( "/" ) )
060        {
061            destinationDirectory += "/";
062        }
063
064        String url = getRepository().getUrl() + "/" + destinationDirectory;
065
066        HttpGet getMethod = new HttpGet( url );
067
068        try
069        {
070            CloseableHttpResponse response = execute( getMethod );
071            try
072            {
073                String reasonPhrase = response.getStatusLine().getReasonPhrase();
074                int statusCode = response.getStatusLine().getStatusCode();
075
076                fireTransferDebug( formatTransferDebugMessage( url, statusCode, reasonPhrase, getProxyInfo() ) );
077
078                switch ( statusCode )
079                {
080                    case HttpStatus.SC_OK:
081                        break;
082
083                    // TODO Move 401/407 to AuthenticationException after WAGON-587
084                    case HttpStatus.SC_FORBIDDEN:
085                    case HttpStatus.SC_UNAUTHORIZED:
086                    case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
087                        EntityUtils.consumeQuietly( response.getEntity() );
088                        throw new AuthorizationException( HttpMessageUtils.formatAuthorizationMessage( url, statusCode,
089                                reasonPhrase, getProxyInfo() ) );
090
091                    case HttpStatus.SC_NOT_FOUND:
092                    case HttpStatus.SC_GONE:
093                        EntityUtils.consumeQuietly( response.getEntity() );
094                        throw new ResourceDoesNotExistException( formatResourceDoesNotExistMessage( url, statusCode,
095                                reasonPhrase, getProxyInfo() ) );
096
097                    case SC_TOO_MANY_REQUESTS:
098                        EntityUtils.consumeQuietly( response.getEntity() );
099                        return getFileList( backoff( wait, url ), destinationDirectory );
100
101                    //add more entries here
102                    default:
103                        EntityUtils.consumeQuietly( response.getEntity() );
104                        throw new TransferFailedException( formatTransferFailedMessage( url, statusCode, reasonPhrase,
105                                getProxyInfo() ) );
106                }
107                HttpEntity entity = response.getEntity();
108                if ( entity != null )
109                {
110                    return HtmlFileListParser.parseFileList( url, entity.getContent() );
111                }
112                else
113                {
114                    return Collections.emptyList();
115                }
116
117            }
118            finally
119            {
120                response.close();
121            }
122        }
123        catch ( IOException e )
124        {
125            throw new TransferFailedException( "Could not read response body.", e );
126        }
127        catch ( HttpException e )
128        {
129            throw new TransferFailedException( "Could not read response body.", e );
130        }
131        catch ( InterruptedException e )
132        {
133            throw new TransferFailedException( "Unable to wait for resource.", e );
134        }
135    }
136
137}