View Javadoc
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 }