1 package org.apache.maven.artifact.repository.metadata;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.manager.WagonManager;
23 import org.apache.maven.artifact.metadata.ArtifactMetadata;
24 import org.apache.maven.artifact.repository.ArtifactRepository;
25 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
26 import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
27 import org.apache.maven.wagon.ResourceDoesNotExistException;
28 import org.apache.maven.wagon.TransferFailedException;
29 import org.codehaus.plexus.logging.AbstractLogEnabled;
30 import org.codehaus.plexus.util.IOUtil;
31 import org.codehaus.plexus.util.ReaderFactory;
32 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
33
34 import java.io.File;
35 import java.io.FileNotFoundException;
36 import java.io.IOException;
37 import java.io.Reader;
38 import java.util.Date;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Set;
45
46 public class DefaultRepositoryMetadataManager
47 extends AbstractLogEnabled
48 implements RepositoryMetadataManager
49 {
50
51 private WagonManager wagonManager;
52
53
54
55
56 private Set cachedMetadata = new HashSet();
57
58 public void resolve( RepositoryMetadata metadata, List remoteRepositories, ArtifactRepository localRepository )
59 throws RepositoryMetadataResolutionException
60 {
61 boolean alreadyResolved = alreadyResolved( metadata );
62 if ( !alreadyResolved )
63 {
64 for ( Iterator i = remoteRepositories.iterator(); i.hasNext(); )
65 {
66 ArtifactRepository repository = (ArtifactRepository) i.next();
67
68 ArtifactRepositoryPolicy policy =
69 metadata.isSnapshot() ? repository.getSnapshots() : repository.getReleases();
70
71 if ( !policy.isEnabled() )
72 {
73 getLogger().debug( "Skipping disabled repository " + repository.getId() );
74 }
75 else if ( repository.isBlacklisted() )
76 {
77 getLogger().debug( "Skipping blacklisted repository " + repository.getId() );
78 }
79 else
80 {
81 File file = new File( localRepository.getBasedir(),
82 localRepository.pathOfLocalRepositoryMetadata( metadata, repository ) );
83
84
85 boolean checkForUpdates =
86 !file.exists() || policy.checkOutOfDate( new Date( file.lastModified() ) );
87
88 if ( checkForUpdates )
89 {
90 if ( wagonManager.isOnline() )
91 {
92 getLogger().info( metadata.getKey() + ": checking for updates from " + repository.getId() );
93
94 boolean storeMetadata = false;
95 try
96 {
97 wagonManager.getArtifactMetadata( metadata, repository, file,
98 policy.getChecksumPolicy() );
99 storeMetadata = true;
100 }
101 catch ( ResourceDoesNotExistException e )
102 {
103 getLogger().debug(
104 metadata + " could not be found on repository: " + repository.getId() );
105
106
107 if ( file.exists() )
108 {
109 file.delete();
110 }
111 storeMetadata = true;
112 }
113 catch ( TransferFailedException e )
114 {
115 getLogger().warn( metadata + " could not be retrieved from repository: " +
116 repository.getId() + " due to an error: " + e.getMessage() );
117 getLogger().debug( "Exception", e );
118
119 getLogger().info( "Repository '" + repository.getId() + "' will be blacklisted" );
120 repository.setBlacklisted( true );
121
122
123
124 }
125 if ( storeMetadata )
126 {
127
128 if ( file.exists() )
129 {
130 file.setLastModified( System.currentTimeMillis() );
131 }
132 else
133 {
134
135
136
137
138 try
139 {
140 metadata.storeInLocalRepository( localRepository, repository );
141 }
142 catch ( RepositoryMetadataStoreException e )
143 {
144 throw new RepositoryMetadataResolutionException(
145 "Unable to store local copy of metadata: " + e.getMessage(), e );
146 }
147 }
148 }
149 }
150 else
151 {
152 getLogger().debug( "System is offline. Cannot resolve metadata:\n" +
153 metadata.extendedToString() + "\n\n" );
154 }
155 }
156 }
157 }
158
159
160
161 cachedMetadata.add( metadata.getKey() );
162 }
163
164 try
165 {
166 mergeMetadata( metadata, remoteRepositories, localRepository );
167 }
168 catch ( RepositoryMetadataStoreException e )
169 {
170 throw new RepositoryMetadataResolutionException(
171 "Unable to store local copy of metadata: " + e.getMessage(), e );
172 }
173 catch ( RepositoryMetadataReadException e )
174 {
175 throw new RepositoryMetadataResolutionException( "Unable to read local copy of metadata: " + e.getMessage(),
176 e );
177 }
178 }
179
180 private void mergeMetadata( RepositoryMetadata metadata, List remoteRepositories,
181 ArtifactRepository localRepository )
182 throws RepositoryMetadataStoreException, RepositoryMetadataReadException
183 {
184
185
186
187
188
189 Map previousMetadata = new HashMap();
190 ArtifactRepository selected = null;
191 for ( Iterator i = remoteRepositories.iterator(); i.hasNext(); )
192 {
193 ArtifactRepository repository = (ArtifactRepository) i.next();
194
195 ArtifactRepositoryPolicy policy =
196 metadata.isSnapshot() ? repository.getSnapshots() : repository.getReleases();
197
198 if ( policy.isEnabled() && loadMetadata( metadata, repository, localRepository, previousMetadata ) )
199 {
200 metadata.setRepository( repository );
201 selected = repository;
202 }
203 }
204 if ( loadMetadata( metadata, localRepository, localRepository, previousMetadata ) )
205 {
206 metadata.setRepository( null );
207 selected = localRepository;
208 }
209
210 updateSnapshotMetadata( metadata, previousMetadata, selected, localRepository );
211 }
212
213 private void updateSnapshotMetadata( RepositoryMetadata metadata, Map previousMetadata, ArtifactRepository selected,
214 ArtifactRepository localRepository )
215 throws RepositoryMetadataStoreException
216 {
217
218 if ( metadata.isSnapshot() )
219 {
220 Metadata prevMetadata = metadata.getMetadata();
221
222 for ( Iterator i = previousMetadata.keySet().iterator(); i.hasNext(); )
223 {
224 ArtifactRepository repository = (ArtifactRepository) i.next();
225 Metadata m = (Metadata) previousMetadata.get( repository );
226 if ( repository.equals( selected ) )
227 {
228 if ( m.getVersioning() == null )
229 {
230 m.setVersioning( new Versioning() );
231 }
232
233 if ( m.getVersioning().getSnapshot() == null )
234 {
235 m.getVersioning().setSnapshot( new Snapshot() );
236 }
237
238
239
240
241
242
243
244
245
246
247 }
248 else
249 {
250 if ( ( m.getVersioning() != null ) && ( m.getVersioning().getSnapshot() != null ) &&
251 m.getVersioning().getSnapshot().isLocalCopy() )
252 {
253 m.getVersioning().getSnapshot().setLocalCopy( false );
254 metadata.setMetadata( m );
255 metadata.storeInLocalRepository( localRepository, repository );
256 }
257 }
258 }
259
260 metadata.setMetadata( prevMetadata );
261 }
262 }
263
264 private boolean loadMetadata( RepositoryMetadata repoMetadata, ArtifactRepository remoteRepository,
265 ArtifactRepository localRepository, Map previousMetadata )
266 throws RepositoryMetadataReadException
267 {
268 boolean setRepository = false;
269
270 File metadataFile = new File( localRepository.getBasedir(),
271 localRepository.pathOfLocalRepositoryMetadata( repoMetadata, remoteRepository ) );
272
273 if ( metadataFile.exists() )
274 {
275 Metadata metadata = readMetadata( metadataFile );
276
277 if ( repoMetadata.isSnapshot() && ( previousMetadata != null ) )
278 {
279 previousMetadata.put( remoteRepository, metadata );
280 }
281
282 if ( repoMetadata.getMetadata() != null )
283 {
284 setRepository = repoMetadata.getMetadata().merge( metadata );
285 }
286 else
287 {
288 repoMetadata.setMetadata( metadata );
289 setRepository = true;
290 }
291 }
292 return setRepository;
293 }
294
295
296
297
298 protected static Metadata readMetadata( File mappingFile )
299 throws RepositoryMetadataReadException
300 {
301 Metadata result;
302
303 Reader reader = null;
304 try
305 {
306 reader = ReaderFactory.newXmlReader( mappingFile );
307
308 MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
309
310 result = mappingReader.read( reader, false );
311 }
312 catch ( FileNotFoundException e )
313 {
314 throw new RepositoryMetadataReadException( "Cannot read metadata from '" + mappingFile + "'", e );
315 }
316 catch ( IOException e )
317 {
318 throw new RepositoryMetadataReadException(
319 "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e );
320 }
321 catch ( XmlPullParserException e )
322 {
323 throw new RepositoryMetadataReadException(
324 "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e );
325 }
326 finally
327 {
328 IOUtil.close( reader );
329 }
330 return result;
331 }
332
333 public void resolveAlways( RepositoryMetadata metadata, ArtifactRepository localRepository,
334 ArtifactRepository remoteRepository )
335 throws RepositoryMetadataResolutionException
336 {
337 if ( !wagonManager.isOnline() )
338 {
339
340 throw new RepositoryMetadataResolutionException(
341 "System is offline. Cannot resolve required metadata:\n" + metadata.extendedToString() );
342 }
343
344 File file;
345 try
346 {
347 file = getArtifactMetadataFromDeploymentRepository( metadata, localRepository, remoteRepository );
348 }
349 catch ( TransferFailedException e )
350 {
351 throw new RepositoryMetadataResolutionException( metadata + " could not be retrieved from repository: " +
352 remoteRepository.getId() + " due to an error: " + e.getMessage(), e );
353 }
354
355 try
356 {
357 if ( file.exists() )
358 {
359 Metadata prevMetadata = readMetadata( file );
360 metadata.setMetadata( prevMetadata );
361 }
362 }
363 catch ( RepositoryMetadataReadException e )
364 {
365 throw new RepositoryMetadataResolutionException( e.getMessage(), e );
366 }
367 }
368
369 private File getArtifactMetadataFromDeploymentRepository( ArtifactMetadata metadata,
370 ArtifactRepository localRepository,
371 ArtifactRepository remoteRepository )
372 throws TransferFailedException
373 {
374 File file = new File( localRepository.getBasedir(),
375 localRepository.pathOfLocalRepositoryMetadata( metadata, remoteRepository ) );
376
377 try
378 {
379 wagonManager.getArtifactMetadataFromDeploymentRepository( metadata, remoteRepository, file,
380 ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
381 }
382 catch ( ResourceDoesNotExistException e )
383 {
384 getLogger().info(
385 metadata + " could not be found on repository: " + remoteRepository.getId() + ", so will be created" );
386
387
388 if ( file.exists() )
389 {
390 file.delete();
391 }
392 }
393 return file;
394 }
395
396 private boolean alreadyResolved( ArtifactMetadata metadata )
397 {
398 return cachedMetadata.contains( metadata.getKey() );
399 }
400
401 public void deploy( ArtifactMetadata metadata, ArtifactRepository localRepository,
402 ArtifactRepository deploymentRepository )
403 throws RepositoryMetadataDeploymentException
404 {
405 if ( !wagonManager.isOnline() )
406 {
407
408 throw new RepositoryMetadataDeploymentException(
409 "System is offline. Cannot deploy metadata:\n" + metadata.extendedToString() );
410 }
411
412 File file;
413 if ( metadata instanceof RepositoryMetadata )
414 {
415 getLogger().info( "Retrieving previous metadata from " + deploymentRepository.getId() );
416 try
417 {
418 file = getArtifactMetadataFromDeploymentRepository( metadata, localRepository, deploymentRepository );
419 }
420 catch ( TransferFailedException e )
421 {
422 throw new RepositoryMetadataDeploymentException( metadata +
423 " could not be retrieved from repository: " + deploymentRepository.getId() + " due to an error: " +
424 e.getMessage(), e );
425 }
426 }
427 else
428 {
429
430 file = new File( localRepository.getBasedir(),
431 localRepository.pathOfLocalRepositoryMetadata( metadata, deploymentRepository ) );
432 }
433
434 try
435 {
436 metadata.storeInLocalRepository( localRepository, deploymentRepository );
437 }
438 catch ( RepositoryMetadataStoreException e )
439 {
440 throw new RepositoryMetadataDeploymentException( "Error installing metadata: " + e.getMessage(), e );
441 }
442
443 try
444 {
445 wagonManager.putArtifactMetadata( file, metadata, deploymentRepository );
446 }
447 catch ( TransferFailedException e )
448 {
449 throw new RepositoryMetadataDeploymentException( "Error while deploying metadata: " + e.getMessage(), e );
450 }
451 }
452
453 public void install( ArtifactMetadata metadata, ArtifactRepository localRepository )
454 throws RepositoryMetadataInstallationException
455 {
456 try
457 {
458 metadata.storeInLocalRepository( localRepository, localRepository );
459 }
460 catch ( RepositoryMetadataStoreException e )
461 {
462 throw new RepositoryMetadataInstallationException( "Error installing metadata: " + e.getMessage(), e );
463 }
464 }
465 }