    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
    10   *   http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing,
    13   * software distributed under the License is distributed on an
    14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   * KIND, either express or implied.  See the License for the
    16   * specific language governing permissions and limitations
    17   * under the License.
    18   */
    19  package org.apache.felix.obrplugin;
    20
    21
    22  import java.io.BufferedWriter;
    23  import java.io.File;
    24  import java.io.FileWriter;
    25  import java.io.IOException;
    26  import java.io.Writer;
    27
    28  import org.apache.maven.artifact.manager.WagonManager;
    29  import org.apache.maven.plugin.MojoExecutionException;
    30  import org.apache.maven.plugin.logging.Log;
    31  import org.apache.maven.settings.Proxy;
    32  import org.apache.maven.settings.Settings;
    33  import org.apache.maven.wagon.ConnectionException;
    34  import org.apache.maven.wagon.ResourceDoesNotExistException;
    35  import org.apache.maven.wagon.TransferFailedException;
    36  import org.apache.maven.wagon.UnsupportedProtocolException;
    37  import org.apache.maven.wagon.Wagon;
    38  import org.apache.maven.wagon.WagonException;
    39  import org.apache.maven.wagon.authentication.AuthenticationException;
    40  import org.apache.maven.wagon.authorization.AuthorizationException;
    41  import org.apache.maven.wagon.proxy.ProxyInfo;
    42  import org.apache.maven.wagon.repository.Repository;
    43
    44
    45  /**
    46   * this class is used to manage all connections by wagon.
    47   * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
    48   */
    49  public class RemoteFileManager
    50  {
    51      /**
    52       * save the connection.
    53       */
    54      private Wagon m_wagon;
    55
    56      /**
    57       * the wagon manager.
    58       */
    59      private WagonManager m_wagonManager;
    60
    61      /**
    62       * the project settings.
    63       */
    64      private Settings m_settings;
    65
    66      /**
    67       * logger instance.
    68       */
    69      private Log m_log;
    70
    71
    72      /**
    73       * initialize main information.
    74       * @param wm WagonManager provides by maven
    75       * @param settings settings of the current project provides by maven
    76       * @param log logger
    77       */
    78      public RemoteFileManager( WagonManager wm, Settings settings, Log log )
    79      {
    80          m_wagonManager = wm;
    81          m_settings = settings;
    82          m_log = log;
    83          m_wagon = null;
    84      }
    85
    86
    87      /**
    88       * disconnect the current object.
    89       */
    90      public void disconnect()
    91      {
    92          try
    93          {
    94              if ( m_wagon != null )
    95              {
    96                  m_wagon.disconnect();
    97              }
    98          }
    99          catch ( ConnectionException e )
    100         {
    101             m_log.error( "Error disconnecting Wagon", e );
    102         }
    103     }
    104
    105
    106     /**
    107      * connect the current object to repository given in constructor.
    108      * @param id repository id
    109      * @param url repository url
    110      * @throws MojoExecutionException
    111      */
    112     public void connect( String id, String url ) throws MojoExecutionException
    113     {
    114         Repository repository = new Repository( id, url );
    115
    116         try
    117         {
    118             m_wagon = m_wagonManager.getWagon( repository );
    119         }
    120         catch ( UnsupportedProtocolException e )
    121         {
    122             throw new MojoExecutionException( "Unsupported protocol: '" + repository.getProtocol() + "'", e );
    123         }
    124         catch ( WagonException e )
    125         {
    126             throw new MojoExecutionException( "Unable to configure Wagon: '" + repository.getProtocol() + "'", e );
    127         }
    128
    129         try
    130         {
    131             ProxyInfo proxyInfo = getProxyInfo( m_settings );
    132             if ( proxyInfo != null )
    133             {
    134                 m_wagon.connect( repository, m_wagonManager.getAuthenticationInfo( id ), proxyInfo );
    135             }
    136             else
    137             {
    138                 m_wagon.connect( repository, m_wagonManager.getAuthenticationInfo( id ) );
    139             }
    140         }
    141         catch ( ConnectionException e )
    142         {
    143             throw new MojoExecutionException( "Connection failed", e );
    144         }
    145         catch ( AuthenticationException e )
    146         {
    147             throw new MojoExecutionException( "Authentication failed", e );
    148         }
    149     }
    150
    151
    152     /**
    153      * get a file from the current repository connected.
    154      * @param url url to the targeted file
    155      * @param suffix suggested file suffix
    156      * @return get a file descriptor on the required resource
    157      * @throws MojoExecutionException
    158      */
    159     public File get( String url, String suffix ) throws MojoExecutionException
    160     {
    161         if ( m_wagon == null )
    162         {
    163             m_log.error( "must be connected first!" );
    164             return null;
    165         }
    166
    167         File file = null;
    168         try
    169         {
    170             file = File.createTempFile( String.valueOf( System.currentTimeMillis() ), suffix );
    171         }
    172         catch ( IOException e )
    173         {
    174             throw new MojoExecutionException( "I/O problem", e );
    175         }
    176
    177         try
    178         {
    179             m_wagon.get( url, file );
    180         }
    181         catch ( TransferFailedException e )
    182         {
    183             file.delete(); // cleanup on failure
    184             throw new MojoExecutionException( "Transfer failed", e );
    185         }
    186         catch ( AuthorizationException e )
    187         {
    188             file.delete(); // cleanup on failure
    189             throw new MojoExecutionException( "Authorization failed", e );
    190         }
    191         catch ( ResourceDoesNotExistException e )
    192         {
    193             file.delete(); // return non-existent file
    194         }
    195
    196         return file;
    197     }
    198
    199
    200     /**
    201      * put a file on the current repository connected.
    202      * @param file file to upload
    203      * @param url url to copy file
    204      * @throws MojoExecutionException
    205      */
    206     public void put( File file, String url ) throws MojoExecutionException
    207     {
    208         if ( m_wagon == null )
    209         {
    210             m_log.error( "must be connected first!" );
    211             return;
    212         }
    213
    214         try
    215         {
    216             m_wagon.put( file, url );
    217         }
    218         catch ( TransferFailedException e )
    219         {
    220             throw new MojoExecutionException( "Transfer failed", e );
    221         }
    222         catch ( AuthorizationException e )
    223         {
    224             throw new MojoExecutionException( "Authorization failed", e );
    225         }
    226         catch ( ResourceDoesNotExistException e )
    227         {
    228             throw new MojoExecutionException( "Resource does not exist:" + file, e );
    229         }
    230     }
    231
    232
    233     /**
    234      * Convenience method to map a Proxy object from the user system settings to a ProxyInfo object.
    235      * @param settings project settings given by maven
    236      * @return a proxyInfo object instancied or null if no active proxy is define in the settings.xml
    237      */
    238     public static ProxyInfo getProxyInfo( Settings settings )
    239     {
    240         ProxyInfo proxyInfo = null;
    241         if ( settings != null && settings.getActiveProxy() != null )
    242         {
    243             Proxy settingsProxy = settings.getActiveProxy();
    244
    245             proxyInfo = new ProxyInfo();
    246             proxyInfo.setHost( settingsProxy.getHost() );
    247             proxyInfo.setType( settingsProxy.getProtocol() );
    248             proxyInfo.setPort( settingsProxy.getPort() );
    249             proxyInfo.setNonProxyHosts( settingsProxy.getNonProxyHosts() );
    250             proxyInfo.setUserName( settingsProxy.getUsername() );
    251             proxyInfo.setPassword( settingsProxy.getPassword() );
    252         }
    253
    254         return proxyInfo;
    255     }
    256
    257
    258     public void lockFile( String fileName, boolean ignoreLock ) throws MojoExecutionException
    259     {
    260         if ( !ignoreLock )
    261         {
    262             int countError = 0;
    263             while ( isLockedFile( fileName ) && countError < 2 )
    264             {
    265                 countError++;
    266                 m_log.warn( "File is currently locked, retry in 10s" );
    267                 try
    268                 {
    269                     Thread.sleep( 10000 );
    270                 }
    271                 catch ( InterruptedException e )
    272                 {
    273                     m_log.warn( "Sleep interrupted" );
    274                 }
    275             }
    276
    277             if ( countError == 2 )
    278             {
    279                 m_log.error( "File " + fileName + " is locked. Use -DignoreLock to force uploading" );
    280                 throw new MojoExecutionException( "Remote file locked" );
    281             }
    282         }
    283
    284         File file = null;
    285         try
    286         {
    287             // create a non-empty file used to lock the remote file
    288             file = File.createTempFile( String.valueOf( System.currentTimeMillis() ), ".lock" );
    289
    290             Writer writer = new BufferedWriter( new FileWriter( file ) );
    291             writer.write( "LOCKED" );
    292             writer.close();
    293
    294             put( file, fileName + ".lock" );
    295         }
    296         catch ( IOException e )
    297         {
    298             throw new MojoExecutionException( "I/O problem", e );
    299         }
    300         finally
    301         {
    302             if ( null != file )
    303             {
    304                 file.delete();
    305             }
    306         }
    307     }
    308
    309
    310     public void unlockFile( String fileName ) throws MojoExecutionException
    311     {
    312         File file = null;
    313         try
    314         {
    315             // clear the contents of the file used to lock the remote file
    316             file = File.createTempFile( String.valueOf( System.currentTimeMillis() ), ".lock" );
    317
    318             Writer writer = new BufferedWriter( new FileWriter( file ) );
    319             writer.write( " " ); // write 1 byte to force wagon upload
    320             writer.close();
    321
    322             put( file, fileName + ".lock" );
    323         }
    324         catch ( IOException e )
    325         {
    326             throw new MojoExecutionException( "I/O problem", e );
    327         }
    328         finally
    329         {
    330             if ( null != file )
    331             {
    332                 file.delete();
    333             }
    334         }
    335     }
    336
    337
    338     /**
    339      * this method indicates if the targeted file is locked or not.
    340      * @param fileName name targeted
    341      * @return  true if the required file is locked, else false
    342      * @throws MojoExecutionException
    343      */
    344     public boolean isLockedFile( String fileName ) throws MojoExecutionException
    345     {
    346         File file = null;
    347         try
    348         {
    349             file = get( fileName + ".lock", ".lock" );
    350
    351             // file is locked with contents "LOCKED"
    352             if ( null != file && file.length() <= 2 )
    353             {
    354                 return false;
    355             }
    356         }
    357         finally
    358         {
    359             if ( null != file )
    360             {
    361                 file.delete();
    362             }
    363         }
    364
    365         return true;
    366     }
    367
    368
    369     public String toString()
    370     {
    371         return m_wagon.getRepository().getUrl();
    372     }
    373 }