Coverage Report - org.apache.maven.wagon.providers.http.LightweightHttpWagon
 
Classes in this File Line Coverage Branch Coverage Complexity
LightweightHttpWagon
88%
103/117
87%
45/52
4,4
LightweightHttpWagon$1
92%
11/12
58%
7/12
4,4
 
 1  
 package org.apache.maven.wagon.providers.http;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.io.FileNotFoundException;
 23  
 import java.io.IOException;
 24  
 import java.io.InputStream;
 25  
 import java.io.OutputStream;
 26  
 import java.net.Authenticator;
 27  
 import java.net.HttpURLConnection;
 28  
 import java.net.MalformedURLException;
 29  
 import java.net.PasswordAuthentication;
 30  
 import java.net.URL;
 31  
 import java.net.URLConnection;
 32  
 import java.util.Iterator;
 33  
 import java.util.List;
 34  
 import java.util.Properties;
 35  
 import java.util.zip.GZIPInputStream;
 36  
 
 37  
 import org.apache.maven.wagon.ConnectionException;
 38  
 import org.apache.maven.wagon.InputData;
 39  
 import org.apache.maven.wagon.OutputData;
 40  
 import org.apache.maven.wagon.ResourceDoesNotExistException;
 41  
 import org.apache.maven.wagon.StreamWagon;
 42  
 import org.apache.maven.wagon.TransferFailedException;
 43  
 import org.apache.maven.wagon.authentication.AuthenticationException;
 44  
 import org.apache.maven.wagon.authorization.AuthorizationException;
 45  
 import org.apache.maven.wagon.events.TransferEvent;
 46  
 import org.apache.maven.wagon.proxy.ProxyInfo;
 47  
 import org.apache.maven.wagon.resource.Resource;
 48  
 import org.apache.maven.wagon.shared.http.HtmlFileListParser;
 49  
 
 50  
 /**
 51  
  * LightweightHttpWagon
 52  
  * 
 53  
  * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
 54  
  * @version $Id: LightweightHttpWagon.java 834247 2009-11-09 21:46:14Z bentmann $
 55  
  * @plexus.component role="org.apache.maven.wagon.Wagon" role-hint="http" instantiation-strategy="per-lookup"
 56  
  */
 57  499
 public class LightweightHttpWagon
 58  
     extends StreamWagon
 59  
 {
 60  
     private String previousProxyExclusions;
 61  
 
 62  
     private String previousHttpProxyHost;
 63  
 
 64  
     private String previousHttpProxyPort;
 65  
 
 66  
     private HttpURLConnection putConnection;
 67  
 
 68  
     /**
 69  
      * Whether to use any proxy cache or not.
 70  
      * 
 71  
      * @plexus.configuration default="false"
 72  
      */
 73  
     private boolean useCache;
 74  
 
 75  
     /** @plexus.configuration */
 76  
     private Properties httpHeaders;
 77  
 
 78  
     /**
 79  
      * Builds a complete URL string from the repository URL and the relative path passed.
 80  
      * 
 81  
      * @param path the relative path
 82  
      * @return the complete URL
 83  
      */
 84  
     private String buildUrl( String path )
 85  
     {
 86  132
         final String repoUrl = getRepository().getUrl();
 87  
 
 88  132
         path = path.replace( ' ', '+' );
 89  
 
 90  132
         if ( repoUrl.charAt( repoUrl.length() - 1 ) != '/' )
 91  
         {
 92  60
             return repoUrl + '/' + path;
 93  
         }
 94  
 
 95  72
         return repoUrl + path;
 96  
     }
 97  
 
 98  
     public void fillInputData( InputData inputData )
 99  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 100  
     {
 101  50
         Resource resource = inputData.getResource();
 102  
         try
 103  
         {
 104  50
             URL url = new URL( buildUrl( resource.getName() ) );
 105  50
             HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
 106  50
             urlConnection.setRequestProperty( "Accept-Encoding", "gzip" );
 107  50
             if ( !useCache )
 108  
             {
 109  50
                 urlConnection.setRequestProperty( "Pragma", "no-cache" );
 110  
             }
 111  
 
 112  50
             addHeaders( urlConnection );
 113  
 
 114  
             // TODO: handle all response codes
 115  50
             int responseCode = urlConnection.getResponseCode();
 116  50
             if ( responseCode == HttpURLConnection.HTTP_FORBIDDEN
 117  
                 || responseCode == HttpURLConnection.HTTP_UNAUTHORIZED )
 118  
             {
 119  6
                 throw new AuthorizationException( "Access denied to: " + buildUrl( resource.getName() ) );
 120  
             }
 121  
 
 122  44
             InputStream is = urlConnection.getInputStream();
 123  30
             String contentEncoding = urlConnection.getHeaderField( "Content-Encoding" );
 124  30
             boolean isGZipped = contentEncoding == null ? false : "gzip".equalsIgnoreCase( contentEncoding );
 125  30
             if ( isGZipped )
 126  
             {
 127  2
                 is = new GZIPInputStream( is );
 128  
             }
 129  30
             inputData.setInputStream( is );
 130  30
             resource.setLastModified( urlConnection.getLastModified() );
 131  30
             resource.setContentLength( urlConnection.getContentLength() );
 132  
         }
 133  0
         catch ( MalformedURLException e )
 134  
         {
 135  0
             throw new ResourceDoesNotExistException( "Invalid repository URL: " + e.getMessage(), e );
 136  
         }
 137  12
         catch ( FileNotFoundException e )
 138  
         {
 139  12
             throw new ResourceDoesNotExistException( "Unable to locate resource in repository", e );
 140  
         }
 141  2
         catch ( IOException e )
 142  
         {
 143  2
             throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
 144  30
         }
 145  30
     }
 146  
 
 147  
     private void addHeaders( URLConnection urlConnection )
 148  
     {
 149  108
         if ( httpHeaders != null )
 150  
         {
 151  2
             for ( Iterator i = httpHeaders.keySet().iterator(); i.hasNext(); )
 152  
             {
 153  2
                 String header = (String) i.next();
 154  2
                 urlConnection.setRequestProperty( header, httpHeaders.getProperty( header ) );
 155  2
             }
 156  
         }
 157  108
     }
 158  
 
 159  
     public void fillOutputData( OutputData outputData )
 160  
         throws TransferFailedException
 161  
     {
 162  40
         Resource resource = outputData.getResource();
 163  
         try
 164  
         {
 165  40
             URL url = new URL( buildUrl( resource.getName() ) );
 166  40
             putConnection = (HttpURLConnection) url.openConnection();
 167  
 
 168  40
             addHeaders( putConnection );
 169  
 
 170  40
             putConnection.setRequestMethod( "PUT" );
 171  40
             putConnection.setDoOutput( true );
 172  40
             outputData.setOutputStream( putConnection.getOutputStream() );
 173  
         }
 174  0
         catch ( IOException e )
 175  
         {
 176  0
             throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
 177  40
         }
 178  40
     }
 179  
 
 180  
     protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output )
 181  
         throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
 182  
     {
 183  
         try
 184  
         {
 185  40
             int statusCode = putConnection.getResponseCode();
 186  
 
 187  40
             switch ( statusCode )
 188  
             {
 189  
                 // Success Codes
 190  
                 case HttpURLConnection.HTTP_OK: // 200
 191  
                 case HttpURLConnection.HTTP_CREATED: // 201
 192  
                 case HttpURLConnection.HTTP_ACCEPTED: // 202
 193  
                 case HttpURLConnection.HTTP_NO_CONTENT: // 204
 194  30
                     break;
 195  
 
 196  
                 case HttpURLConnection.HTTP_FORBIDDEN:
 197  2
                     throw new AuthorizationException( "Access denied to: " + buildUrl( resource.getName() ) );
 198  
 
 199  
                 case HttpURLConnection.HTTP_NOT_FOUND:
 200  2
                     throw new ResourceDoesNotExistException( "File: " + buildUrl( resource.getName() )
 201  
                         + " does not exist" );
 202  
 
 203  
                     // add more entries here
 204  
                 default:
 205  6
                     throw new TransferFailedException( "Failed to transfer file: " + buildUrl( resource.getName() )
 206  
                         + ". Return code is: " + statusCode );
 207  
             }
 208  
         }
 209  0
         catch ( IOException e )
 210  
         {
 211  0
             fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
 212  
 
 213  0
             throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
 214  30
         }
 215  30
     }
 216  
 
 217  
     protected void openConnectionInternal()
 218  
         throws ConnectionException, AuthenticationException
 219  
     {
 220  113
         previousHttpProxyHost = System.getProperty( "http.proxyHost" );
 221  113
         previousHttpProxyPort = System.getProperty( "http.proxyPort" );
 222  113
         previousProxyExclusions = System.getProperty( "http.nonProxyHosts" );
 223  
 
 224  113
         final ProxyInfo proxyInfo = getProxyInfo( "http", getRepository().getHost() );
 225  113
         if ( proxyInfo != null )
 226  
         {
 227  8
             setSystemProperty( "http.proxyHost", proxyInfo.getHost() );
 228  8
             setSystemProperty( "http.proxyPort", String.valueOf( proxyInfo.getPort() ) );
 229  8
             setSystemProperty( "http.nonProxyHosts", proxyInfo.getNonProxyHosts() );
 230  
         }
 231  
         else
 232  
         {
 233  105
             setSystemProperty( "http.proxyHost", null );
 234  105
             setSystemProperty( "http.proxyPort", null );
 235  
         }
 236  
 
 237  113
         final boolean hasProxy = ( proxyInfo != null && proxyInfo.getUserName() != null );
 238  113
         final boolean hasAuthentication = ( authenticationInfo != null && authenticationInfo.getUserName() != null );
 239  113
         if ( hasProxy || hasAuthentication )
 240  
         {
 241  14
             Authenticator.setDefault( new Authenticator()
 242  
             {
 243  14
                 protected PasswordAuthentication getPasswordAuthentication()
 244  
                 {
 245  
                     // TODO: ideally use getRequestorType() from JDK1.5 here...
 246  127
                     if ( hasProxy && getRequestingHost().equals( proxyInfo.getHost() )
 247  
                         && getRequestingPort() == proxyInfo.getPort() )
 248  
                     {
 249  1
                         String password = "";
 250  1
                         if ( proxyInfo.getPassword() != null )
 251  
                         {
 252  1
                             password = proxyInfo.getPassword();
 253  
                         }
 254  1
                         return new PasswordAuthentication( proxyInfo.getUserName(), password.toCharArray() );
 255  
                     }
 256  
 
 257  126
                     if ( hasAuthentication )
 258  
                     {
 259  126
                         String password = "";
 260  126
                         if ( authenticationInfo.getPassword() != null )
 261  
                         {
 262  126
                             password = authenticationInfo.getPassword();
 263  
                         }
 264  126
                         return new PasswordAuthentication( authenticationInfo.getUserName(), password.toCharArray() );
 265  
                     }
 266  
 
 267  0
                     return super.getPasswordAuthentication();
 268  
                 }
 269  
             } );
 270  
         }
 271  
         else
 272  
         {
 273  99
             Authenticator.setDefault( null );
 274  
         }
 275  113
     }
 276  
 
 277  
     public void closeConnection()
 278  
         throws ConnectionException
 279  
     {
 280  113
         if ( putConnection != null )
 281  
         {
 282  40
             putConnection.disconnect();
 283  
         }
 284  
 
 285  113
         setSystemProperty( "http.proxyHost", previousHttpProxyHost );
 286  113
         setSystemProperty( "http.proxyPort", previousHttpProxyPort );
 287  113
         setSystemProperty( "http.nonProxyHosts", previousProxyExclusions );
 288  113
     }
 289  
 
 290  
     public List getFileList( String destinationDirectory )
 291  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 292  
     {
 293  6
         InputData inputData = new InputData();
 294  
 
 295  6
         if ( destinationDirectory.length() > 0 && !destinationDirectory.endsWith( "/" ) )
 296  
         {
 297  4
             destinationDirectory += "/";
 298  
         }
 299  
 
 300  6
         String url = buildUrl( destinationDirectory );
 301  
 
 302  6
         Resource resource = new Resource( destinationDirectory );
 303  
 
 304  6
         inputData.setResource( resource );
 305  
 
 306  6
         fillInputData( inputData );
 307  
 
 308  4
         InputStream is = inputData.getInputStream();
 309  
 
 310  4
         if ( is == null )
 311  
         {
 312  0
             throw new TransferFailedException( url + " - Could not open input stream for resource: '" + resource
 313  
                                                + "'" );
 314  
         }
 315  
 
 316  4
         return HtmlFileListParser.parseFileList( url, is );
 317  
     }
 318  
 
 319  
     public boolean resourceExists( String resourceName )
 320  
         throws TransferFailedException, AuthorizationException
 321  
     {
 322  
         HttpURLConnection headConnection;
 323  
 
 324  
         try
 325  
         {
 326  18
             URL url = new URL( buildUrl( new Resource( resourceName ).getName() ) );
 327  18
             headConnection = (HttpURLConnection) url.openConnection();
 328  
 
 329  18
             addHeaders( headConnection );
 330  
 
 331  18
             headConnection.setRequestMethod( "HEAD" );
 332  18
             headConnection.setDoOutput( true );
 333  
 
 334  18
             int statusCode = headConnection.getResponseCode();
 335  
 
 336  18
             switch ( statusCode )
 337  
             {
 338  
                 case HttpURLConnection.HTTP_OK:
 339  4
                     return true;
 340  
 
 341  
                 case HttpURLConnection.HTTP_FORBIDDEN:
 342  2
                     throw new AuthorizationException( "Access denied to: " + url );
 343  
 
 344  
                 case HttpURLConnection.HTTP_NOT_FOUND:
 345  6
                     return false;
 346  
 
 347  
                 case HttpURLConnection.HTTP_UNAUTHORIZED:
 348  4
                     throw new AuthorizationException( "Access denied to: " + url );
 349  
 
 350  
                 default:
 351  2
                     throw new TransferFailedException( "Failed to look for file: " + buildUrl( resourceName )
 352  
                         + ". Return code is: " + statusCode );
 353  
             }
 354  
         }
 355  0
         catch ( IOException e )
 356  
         {
 357  0
             throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
 358  
         }
 359  
     }
 360  
 
 361  
     public boolean isUseCache()
 362  
     {
 363  0
         return useCache;
 364  
     }
 365  
 
 366  
     public void setUseCache( boolean useCache )
 367  
     {
 368  0
         this.useCache = useCache;
 369  0
     }
 370  
 
 371  
     public Properties getHttpHeaders()
 372  
     {
 373  0
         return httpHeaders;
 374  
     }
 375  
 
 376  
     public void setHttpHeaders( Properties httpHeaders )
 377  
     {
 378  2
         this.httpHeaders = httpHeaders;
 379  2
     }
 380  
 
 381  
     void setSystemProperty( String key, String value )
 382  
     {
 383  865
         if ( value != null )
 384  
         {
 385  44
             System.setProperty( key, value );
 386  
         }
 387  
         else
 388  
         {
 389  821
             System.getProperties().remove( key );
 390  
         }
 391  865
     }
 392  
 
 393  
 }