001package org.apache.maven.wagon.shared.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 java.net.URI;
023
024import org.apache.http.HttpEntityEnclosingRequest;
025import org.apache.http.HttpRequest;
026import org.apache.http.HttpResponse;
027import org.apache.http.HttpStatus;
028import org.apache.http.ProtocolException;
029import org.apache.http.client.methods.HttpGet;
030import org.apache.http.client.methods.HttpHead;
031import org.apache.http.client.methods.HttpPut;
032import org.apache.http.client.methods.HttpUriRequest;
033import org.apache.http.client.methods.RequestBuilder;
034import org.apache.http.impl.client.DefaultRedirectStrategy;
035import org.apache.http.protocol.HttpContext;
036import org.apache.http.util.Args;
037import org.apache.maven.wagon.events.TransferEvent;
038import org.apache.maven.wagon.shared.http.AbstractHttpClientWagon.WagonHttpEntity;
039import org.slf4j.Logger;
040import org.slf4j.LoggerFactory;
041
042/**
043 * A custom redirect strategy for Apache Maven Wagon HttpClient.
044 *
045 * @since 3.4.0
046 *
047 */
048public class WagonRedirectStrategy extends DefaultRedirectStrategy
049{
050
051    private static final Logger LOGGER = LoggerFactory.getLogger( WagonRedirectStrategy.class );
052
053    private static final int SC_PERMANENT_REDIRECT = 308;
054
055    public WagonRedirectStrategy()
056    {
057        super( new String[] {
058                HttpGet.METHOD_NAME,
059                HttpHead.METHOD_NAME,
060                HttpPut.METHOD_NAME,
061                /**
062                 * This covers the most basic case where the redirection relocates to another
063                 * collection which has an existing parent collection.
064                 */
065                "MKCOL" } );
066    }
067
068    @Override
069    public boolean isRedirected( final HttpRequest request, final HttpResponse response,
070            final HttpContext context ) throws ProtocolException
071    {
072        Args.notNull( request, "HTTP request" );
073        Args.notNull( response, "HTTP response" );
074
075        final int statusCode = response.getStatusLine().getStatusCode();
076        final String method = request.getRequestLine().getMethod();
077        switch ( statusCode )
078        {
079        case HttpStatus.SC_MOVED_TEMPORARILY:
080        case HttpStatus.SC_MOVED_PERMANENTLY:
081        case HttpStatus.SC_SEE_OTHER:
082        case HttpStatus.SC_TEMPORARY_REDIRECT:
083        case SC_PERMANENT_REDIRECT:
084            return isRedirectable( method );
085        default:
086            return false;
087        }
088    }
089
090    @Override
091    public HttpUriRequest getRedirect( final HttpRequest request, final HttpResponse response,
092            final HttpContext context ) throws ProtocolException
093    {
094        final URI uri = getLocationURI( request, response, context );
095        if ( request instanceof HttpEntityEnclosingRequest )
096        {
097            HttpEntityEnclosingRequest encRequest = (HttpEntityEnclosingRequest) request;
098            if ( encRequest.getEntity() instanceof AbstractHttpClientWagon.WagonHttpEntity )
099            {
100                AbstractHttpClientWagon.WagonHttpEntity whe = (WagonHttpEntity) encRequest.getEntity();
101                if ( whe.getWagon() instanceof AbstractHttpClientWagon )
102                {
103                    // Re-execute AbstractWagon#firePutStarted(Resource, File)
104                    AbstractHttpClientWagon httpWagon = (AbstractHttpClientWagon) whe.getWagon();
105                    TransferEvent transferEvent =
106                            new TransferEvent( httpWagon, whe.getResource(),
107                                               TransferEvent.TRANSFER_STARTED, TransferEvent.REQUEST_PUT );
108                    transferEvent.setTimestamp( System.currentTimeMillis() );
109                    transferEvent.setLocalFile( whe.getSource() );
110                    httpWagon.getTransferEventSupport().fireDebug(
111                            String.format( "Following redirect from '%s' to '%s'",
112                                          request.getRequestLine().getUri(), uri.toASCIIString() ) );
113                    httpWagon.getTransferEventSupport().fireTransferStarted( transferEvent );
114                }
115                else
116                {
117                    LOGGER.warn( "Cannot properly handle redirect transfer event, wagon has unexpected class: {}",
118                                whe.getWagon().getClass() );
119                }
120            }
121        }
122
123        return RequestBuilder.copy( request ).setUri( uri ).build();
124    }
125
126}