]> source.dussan.org Git - archiva.git/blob
c9553082dfaa3fbfed532a9adc7f9afbf23525a1
[archiva.git] /
1 package org.apache.archiva.scheduler.indexing;
2 /*
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  */
20
21 import org.apache.archiva.admin.model.RepositoryAdminException;
22 import org.apache.archiva.admin.model.beans.NetworkProxy;
23 import org.apache.archiva.admin.model.beans.RemoteRepository;
24 import org.apache.archiva.admin.model.remote.RemoteRepositoryAdmin;
25 import org.apache.archiva.proxy.common.WagonFactory;
26 import org.apache.archiva.proxy.common.WagonFactoryException;
27 import org.apache.commons.io.FileUtils;
28 import org.apache.commons.lang.time.StopWatch;
29 import org.apache.maven.index.context.IndexingContext;
30 import org.apache.maven.index.updater.IndexUpdateRequest;
31 import org.apache.maven.index.updater.IndexUpdater;
32 import org.apache.maven.index.updater.ResourceFetcher;
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.Wagon;
37 import org.apache.maven.wagon.authentication.AuthenticationException;
38 import org.apache.maven.wagon.authentication.AuthenticationInfo;
39 import org.apache.maven.wagon.authorization.AuthorizationException;
40 import org.apache.maven.wagon.events.TransferEvent;
41 import org.apache.maven.wagon.events.TransferListener;
42 import org.apache.maven.wagon.proxy.ProxyInfo;
43 import org.apache.maven.wagon.repository.Repository;
44 import org.apache.maven.wagon.shared.http.HttpConfiguration;
45 import org.apache.maven.wagon.shared.http.HttpMethodConfiguration;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 import java.io.File;
50 import java.io.FileInputStream;
51 import java.io.FileNotFoundException;
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.lang.reflect.Method;
55 import java.net.MalformedURLException;
56 import java.net.URL;
57 import java.util.Arrays;
58 import java.util.List;
59
60 /**
61  * @author Olivier Lamy
62  * @since 1.4-M1
63  */
64 public class DownloadRemoteIndexTask
65     implements Runnable
66 {
67     private Logger log = LoggerFactory.getLogger( getClass() );
68
69     private RemoteRepository remoteRepository;
70
71     private RemoteRepositoryAdmin remoteRepositoryAdmin;
72
73     private WagonFactory wagonFactory;
74
75     private NetworkProxy networkProxy;
76
77     private boolean fullDownload;
78
79     private List<String> runningRemoteDownloadIds;
80
81     private IndexUpdater indexUpdater;
82
83     public DownloadRemoteIndexTask( DownloadRemoteIndexTaskRequest downloadRemoteIndexTaskRequest,
84                                     List<String> runningRemoteDownloadIds )
85     {
86         this.remoteRepository = downloadRemoteIndexTaskRequest.getRemoteRepository();
87         this.wagonFactory = downloadRemoteIndexTaskRequest.getWagonFactory();
88         this.networkProxy = downloadRemoteIndexTaskRequest.getNetworkProxy();
89         this.fullDownload = downloadRemoteIndexTaskRequest.isFullDownload();
90         this.runningRemoteDownloadIds = runningRemoteDownloadIds;
91         this.indexUpdater = downloadRemoteIndexTaskRequest.getIndexUpdater();
92         this.remoteRepositoryAdmin = downloadRemoteIndexTaskRequest.getRemoteRepositoryAdmin();
93     }
94
95     public void run()
96     {
97
98         // so short lock : not sure we need it
99         synchronized ( this.runningRemoteDownloadIds )
100         {
101             if ( this.runningRemoteDownloadIds.contains( this.remoteRepository.getId() ) )
102             {
103                 // skip it as it's running
104                 log.info( "skip download index remote for repo {} it's already running",
105                           this.remoteRepository.getId() );
106                 return;
107             }
108             this.runningRemoteDownloadIds.add( this.remoteRepository.getId() );
109         }
110         File tempIndexDirectory = null;
111         StopWatch stopWatch = new StopWatch();
112         stopWatch.start();
113         try
114         {
115             log.info( "start download remote index for remote repository " + this.remoteRepository.getId() );
116             IndexingContext indexingContext = remoteRepositoryAdmin.createIndexContext( this.remoteRepository );
117
118             // create a temp directory to download files
119             tempIndexDirectory = new File( indexingContext.getIndexDirectoryFile().getParent(), ".tmpIndex" );
120             File indexCacheDirectory = new File( indexingContext.getIndexDirectoryFile().getParent(), ".indexCache" );
121             indexCacheDirectory.mkdirs();
122             if ( tempIndexDirectory.exists() )
123             {
124                 FileUtils.deleteDirectory( tempIndexDirectory );
125             }
126             tempIndexDirectory.mkdirs();
127             tempIndexDirectory.deleteOnExit();
128             String baseIndexUrl = indexingContext.getIndexUpdateUrl();
129
130             String wagonProtocol =
131                 new URL( this.remoteRepository.getUrl() ).getProtocol() + ( ( this.networkProxy != null
132                     && this.networkProxy.isUseNtlm() ) ? "-ntlm" : "" );
133
134             final Wagon wagon = wagonFactory.getWagon( wagonProtocol );
135             setupWagonReadTimeout( wagon );
136
137             wagon.addTransferListener( new DownloadListener() );
138             ProxyInfo proxyInfo = null;
139             if ( this.networkProxy != null )
140             {
141                 proxyInfo = new ProxyInfo();
142                 proxyInfo.setHost( this.networkProxy.getHost() );
143                 proxyInfo.setPort( this.networkProxy.getPort() );
144                 proxyInfo.setUserName( this.networkProxy.getUsername() );
145                 proxyInfo.setPassword( this.networkProxy.getPassword() );
146             }
147             AuthenticationInfo authenticationInfo = null;
148             if ( this.remoteRepository.getUserName() != null )
149             {
150                 authenticationInfo = new AuthenticationInfo();
151                 authenticationInfo.setUserName( this.remoteRepository.getUserName() );
152                 authenticationInfo.setPassword( this.remoteRepository.getPassword() );
153             }
154             wagon.connect( new Repository( this.remoteRepository.getId(), baseIndexUrl ), authenticationInfo,
155                            proxyInfo );
156
157             File indexDirectory = indexingContext.getIndexDirectoryFile();
158             if ( !indexDirectory.exists() )
159             {
160                 indexDirectory.mkdirs();
161             }
162
163             ResourceFetcher resourceFetcher = new WagonResourceFetcher( log, tempIndexDirectory, wagon );
164             IndexUpdateRequest request = new IndexUpdateRequest( indexingContext, resourceFetcher );
165             request.setForceFullUpdate( this.fullDownload );
166             request.setLocalIndexCacheDir( indexCacheDirectory );
167
168             this.indexUpdater.fetchAndUpdateIndex( request );
169             stopWatch.stop();
170             log.info( "time to download remote repository index for repository {}: {} s", this.remoteRepository.getId(),
171                       ( stopWatch.getTime() / 1000 ) );
172         }
173         catch ( MalformedURLException e )
174         {
175             log.error( e.getMessage(), e );
176             throw new RuntimeException( e.getMessage(), e );
177         }
178         catch ( WagonFactoryException e )
179         {
180             log.error( e.getMessage(), e );
181             throw new RuntimeException( e.getMessage(), e );
182         }
183         catch ( ConnectionException e )
184         {
185             log.error( e.getMessage(), e );
186             throw new RuntimeException( e.getMessage(), e );
187         }
188         catch ( AuthenticationException e )
189         {
190             log.error( e.getMessage(), e );
191             throw new RuntimeException( e.getMessage(), e );
192         }
193         catch ( IOException e )
194         {
195             log.error( e.getMessage(), e );
196             throw new RuntimeException( e.getMessage(), e );
197         }
198         catch ( RepositoryAdminException e )
199         {
200             log.error( e.getMessage(), e );
201             throw new RuntimeException( e.getMessage(), e );
202         }
203         finally
204         {
205             deleteDirectoryQuiet( tempIndexDirectory );
206             this.runningRemoteDownloadIds.remove( this.remoteRepository.getId() );
207         }
208         log.info( "end download remote index for remote repository " + this.remoteRepository.getId() );
209     }
210
211     private void deleteDirectoryQuiet( File f )
212     {
213         try
214         {
215             FileUtils.deleteDirectory( f );
216         }
217         catch ( IOException e )
218         {
219             log.warn( "skip error delete " + f + ": " + e.getMessage() );
220         }
221     }
222
223     private void setupWagonReadTimeout( Wagon wagon )
224     {
225         try
226         {
227             HttpConfiguration httpConfiguration = new HttpConfiguration().setAll(
228                 new HttpMethodConfiguration().setReadTimeout( remoteRepository.getRemoteDownloadTimeout() * 1000 ) );
229             Method setHttpConfigurationMethod =
230                 wagon.getClass().getMethod( "setHttpConfiguration", HttpConfiguration.class );
231             setHttpConfigurationMethod.invoke( wagon, httpConfiguration );
232         }
233         catch ( Exception e )
234         {
235             log.debug( "unable to set download remote time out for index {}", e.getMessage(), e );
236         }
237     }
238
239
240     public static class DownloadListener
241         implements TransferListener
242     {
243         private Logger log = LoggerFactory.getLogger( getClass() );
244
245         String reourceName;
246
247         long startTime;
248
249         public void transferInitiated( TransferEvent transferEvent )
250         {
251             reourceName = transferEvent.getResource().getName();
252             log.debug( "initiate transfer of {}", reourceName );
253         }
254
255         public void transferStarted( TransferEvent transferEvent )
256         {
257             reourceName = transferEvent.getResource().getName();
258             startTime = System.currentTimeMillis();
259             log.info( "start transfer of {}", transferEvent.getResource().getName() );
260         }
261
262         public void transferProgress( TransferEvent transferEvent, byte[] buffer, int length )
263         {
264             log.debug( "transfer of {} : {}/{}",
265                        Arrays.asList( transferEvent.getResource().getName(), buffer.length, length ).toArray() );
266         }
267
268         public void transferCompleted( TransferEvent transferEvent )
269         {
270             reourceName = transferEvent.getResource().getName();
271             long endTime = System.currentTimeMillis();
272             log.info( "end of transfer file {}: {}s", transferEvent.getResource().getName(),
273                       ( endTime - startTime ) / 1000 );
274         }
275
276         public void transferError( TransferEvent transferEvent )
277         {
278             log.info( "error of transfer file {}: {}", Arrays.asList( transferEvent.getResource().getName(),
279                                                                       transferEvent.getException().getMessage() ).toArray(
280                 new Object[2] ), transferEvent.getException() );
281         }
282
283         public void debug( String message )
284         {
285             log.debug( "transfer debug {}", message );
286         }
287     }
288
289     private static class WagonResourceFetcher
290         implements ResourceFetcher
291     {
292
293         Logger log;
294
295         File tempIndexDirectory;
296
297         Wagon wagon;
298
299         private WagonResourceFetcher( Logger log, File tempIndexDirectory, Wagon wagon )
300         {
301             this.log = log;
302             this.tempIndexDirectory = tempIndexDirectory;
303             this.wagon = wagon;
304         }
305
306         public void connect( String id, String url )
307             throws IOException
308         {
309             //no op  
310         }
311
312         public void disconnect()
313             throws IOException
314         {
315             // no op
316         }
317
318         public InputStream retrieve( String name )
319             throws IOException, FileNotFoundException
320         {
321             try
322             {
323                 log.info( "index update retrieve file, name:{}", name );
324                 File file = new File( tempIndexDirectory, name );
325                 if ( file.exists() )
326                 {
327                     file.delete();
328                 }
329                 file.deleteOnExit();
330                 wagon.get( name, file );
331                 return new FileInputStream( file );
332             }
333             catch ( AuthorizationException e )
334             {
335                 throw new IOException( e.getMessage() );
336             }
337             catch ( TransferFailedException e )
338             {
339                 throw new IOException( e.getMessage() );
340             }
341             catch ( ResourceDoesNotExistException e )
342             {
343                 throw new FileNotFoundException( e.getMessage() );
344             }
345         }
346     }
347 }
348
349