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