KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > maven > artifact > repository > metadata > DefaultRepositoryMetadataManager


1 package org.apache.maven.artifact.repository.metadata;
2
3 /*
4  * Copyright 2001-2005 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * 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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import org.apache.maven.artifact.manager.WagonManager;
20 import org.apache.maven.artifact.metadata.ArtifactMetadata;
21 import org.apache.maven.artifact.repository.ArtifactRepository;
22 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
23 import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
24 import org.apache.maven.wagon.ResourceDoesNotExistException;
25 import org.apache.maven.wagon.TransferFailedException;
26 import org.codehaus.plexus.logging.AbstractLogEnabled;
27 import org.codehaus.plexus.util.IOUtil;
28 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
29
30 import java.io.File JavaDoc;
31 import java.io.FileNotFoundException JavaDoc;
32 import java.io.FileReader JavaDoc;
33 import java.io.IOException JavaDoc;
34 import java.io.Reader JavaDoc;
35 import java.util.Date JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.HashSet JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.List JavaDoc;
40 import java.util.Map JavaDoc;
41 import java.util.Set JavaDoc;
42
43 public class DefaultRepositoryMetadataManager
44     extends AbstractLogEnabled
45     implements RepositoryMetadataManager
46 {
47     // component requirement
48
private WagonManager wagonManager;
49
50     /**
51      * @todo very primitive. Probably we can cache artifacts themselves in a central location, as well as reset the flag over time in a long running process.
52      */

53     private Set JavaDoc cachedMetadata = new HashSet JavaDoc();
54
55     public void resolve( RepositoryMetadata metadata, List JavaDoc remoteRepositories, ArtifactRepository localRepository )
56         throws RepositoryMetadataResolutionException
57     {
58         boolean alreadyResolved = alreadyResolved( metadata );
59         if ( !alreadyResolved )
60         {
61             for ( Iterator JavaDoc i = remoteRepositories.iterator(); i.hasNext(); )
62             {
63                 ArtifactRepository repository = (ArtifactRepository) i.next();
64
65                 ArtifactRepositoryPolicy policy =
66                     metadata.isSnapshot() ? repository.getSnapshots() : repository.getReleases();
67
68                 if ( !policy.isEnabled() )
69                 {
70                     getLogger().debug( "Skipping disabled repository " + repository.getId() );
71                 }
72                 else if ( repository.isBlacklisted() )
73                 {
74                     getLogger().debug( "Skipping blacklisted repository " + repository.getId() );
75                 }
76                 else
77                 {
78                     File JavaDoc file = new File JavaDoc( localRepository.getBasedir(),
79                                           localRepository.pathOfLocalRepositoryMetadata( metadata, repository ) );
80
81                     boolean checkForUpdates = policy.checkOutOfDate( new Date JavaDoc( file.lastModified() ) ) || !file.exists();
82
83                     boolean metadataIsEmpty = true;
84                     
85                     if ( checkForUpdates )
86                     {
87                         getLogger().info( metadata.getKey() + ": checking for updates from " + repository.getId() );
88
89                         try
90                         {
91                             resolveAlways( metadata, repository, file, policy.getChecksumPolicy(), true );
92                             metadataIsEmpty = false;
93                         }
94                         catch ( TransferFailedException e )
95                         {
96                             // TODO: [jc; 08-Nov-2005] revisit this for 2.1
97
// suppressing logging to avoid logging this error twice.
98
metadataIsEmpty = true;
99                         }
100                     }
101
102                     // touch file so that this is not checked again until interval has passed
103
if ( file.exists() )
104                     {
105                         file.setLastModified( System.currentTimeMillis() );
106                     }
107                     else if ( !metadataIsEmpty )
108                     {
109                         // this ensures that files are not continuously checked when they don't exist remotely
110
try
111                         {
112                             metadata.storeInLocalRepository( localRepository, repository );
113                         }
114                         catch ( RepositoryMetadataStoreException e )
115                         {
116                             throw new RepositoryMetadataResolutionException(
117                                 "Unable to store local copy of metadata: " + e.getMessage(), e );
118                         }
119                     }
120                 }
121             }
122             cachedMetadata.add( metadata.getKey() );
123         }
124
125         try
126         {
127             mergeMetadata( metadata, remoteRepositories, localRepository );
128         }
129         catch ( RepositoryMetadataStoreException e )
130         {
131             throw new RepositoryMetadataResolutionException(
132                 "Unable to store local copy of metadata: " + e.getMessage(), e );
133         }
134         catch ( RepositoryMetadataReadException e )
135         {
136             throw new RepositoryMetadataResolutionException( "Unable to read local copy of metadata: " + e.getMessage(),
137                                                              e );
138         }
139     }
140
141     private void mergeMetadata( RepositoryMetadata metadata, List JavaDoc remoteRepositories,
142                                 ArtifactRepository localRepository )
143         throws RepositoryMetadataStoreException, RepositoryMetadataReadException
144     {
145         // TODO: currently this is first wins, but really we should take the latest by comparing either the
146
// snapshot timestamp, or some other timestamp later encoded into the metadata.
147
// TODO: this needs to be repeated here so the merging doesn't interfere with the written metadata
148
// - we'd be much better having a pristine input, and an ongoing metadata for merging instead
149

150         Map JavaDoc previousMetadata = new HashMap JavaDoc();
151         ArtifactRepository selected = null;
152         for ( Iterator JavaDoc i = remoteRepositories.iterator(); i.hasNext(); )
153         {
154             ArtifactRepository repository = (ArtifactRepository) i.next();
155
156             ArtifactRepositoryPolicy policy =
157                 metadata.isSnapshot() ? repository.getSnapshots() : repository.getReleases();
158
159             if ( policy.isEnabled() && !repository.isBlacklisted() )
160             {
161                 if ( loadMetadata( metadata, repository, localRepository, previousMetadata ) )
162                 {
163                     metadata.setRepository( repository );
164                     selected = repository;
165                 }
166             }
167         }
168         if ( loadMetadata( metadata, localRepository, localRepository, previousMetadata ) )
169         {
170             metadata.setRepository( null );
171             selected = localRepository;
172         }
173
174         updateSnapshotMetadata( metadata, previousMetadata, selected, localRepository );
175     }
176
177     private void updateSnapshotMetadata( RepositoryMetadata metadata, Map JavaDoc previousMetadata, ArtifactRepository selected,
178                                          ArtifactRepository localRepository )
179         throws RepositoryMetadataStoreException
180     {
181         // TODO: this could be a lot nicer... should really be in the snapshot transformation?
182
if ( metadata.isSnapshot() )
183         {
184             Metadata prevMetadata = metadata.getMetadata();
185
186             for ( Iterator JavaDoc i = previousMetadata.keySet().iterator(); i.hasNext(); )
187             {
188                 ArtifactRepository repository = (ArtifactRepository) i.next();
189                 Metadata m = (Metadata) previousMetadata.get( repository );
190                 if ( repository.equals( selected ) )
191                 {
192                     if ( m.getVersioning() == null )
193                     {
194                         m.setVersioning( new Versioning() );
195                     }
196
197                     if ( m.getVersioning().getSnapshot() == null )
198                     {
199                         m.getVersioning().setSnapshot( new Snapshot() );
200                     }
201
202                     if ( !m.getVersioning().getSnapshot().isLocalCopy() )
203                     {
204                         m.getVersioning().getSnapshot().setLocalCopy( true );
205                         metadata.setMetadata( m );
206                         metadata.storeInLocalRepository( localRepository, repository );
207                     }
208                 }
209                 else
210                 {
211                     if ( m.getVersioning() != null && m.getVersioning().getSnapshot() != null &&
212                         m.getVersioning().getSnapshot().isLocalCopy() )
213                     {
214                         m.getVersioning().getSnapshot().setLocalCopy( false );
215                         metadata.setMetadata( m );
216                         metadata.storeInLocalRepository( localRepository, repository );
217                     }
218                 }
219             }
220
221             metadata.setMetadata( prevMetadata );
222         }
223     }
224
225     private boolean loadMetadata( RepositoryMetadata repoMetadata, ArtifactRepository remoteRepository,
226                                   ArtifactRepository localRepository, Map JavaDoc previousMetadata )
227         throws RepositoryMetadataReadException
228     {
229         boolean setRepository = false;
230
231         File JavaDoc metadataFile = new File JavaDoc( localRepository.getBasedir(),
232                                       localRepository.pathOfLocalRepositoryMetadata( repoMetadata, remoteRepository ) );
233
234         if ( metadataFile.exists() )
235         {
236             Metadata metadata = readMetadata( metadataFile );
237
238             if ( repoMetadata.isSnapshot() && previousMetadata != null )
239             {
240                 previousMetadata.put( remoteRepository, metadata );
241             }
242
243             if ( repoMetadata.getMetadata() != null )
244             {
245                 setRepository = repoMetadata.getMetadata().merge( metadata );
246             }
247             else
248             {
249                 repoMetadata.setMetadata( metadata );
250                 setRepository = true;
251             }
252         }
253         return setRepository;
254     }
255
256     /**
257      * @todo share with DefaultPluginMappingManager.
258      */

259     protected static Metadata readMetadata( File JavaDoc mappingFile )
260         throws RepositoryMetadataReadException
261     {
262         Metadata result;
263
264         Reader fileReader = null;
265         try
266         {
267             fileReader = new FileReader JavaDoc( mappingFile );
268
269             MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
270
271             result = mappingReader.read( fileReader, false );
272         }
273         catch ( FileNotFoundException JavaDoc e )
274         {
275             throw new RepositoryMetadataReadException( "Cannot read metadata from '" + mappingFile + "'", e );
276         }
277         catch ( IOException JavaDoc e )
278         {
279             throw new RepositoryMetadataReadException(
280                 "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e );
281         }
282         catch ( XmlPullParserException e )
283         {
284             throw new RepositoryMetadataReadException(
285                 "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e );
286         }
287         finally
288         {
289             IOUtil.close( fileReader );
290         }
291         return result;
292     }
293
294     public void resolveAlways( RepositoryMetadata metadata, ArtifactRepository localRepository,
295                                ArtifactRepository remoteRepository )
296         throws RepositoryMetadataResolutionException
297     {
298         if ( !wagonManager.isOnline() )
299         {
300             // metadata is required for deployment, can't be offline
301
throw new RepositoryMetadataResolutionException(
302                 "System is offline. Cannot resolve required metadata:\n" + metadata.extendedToString() );
303         }
304
305         File JavaDoc file = new File JavaDoc( localRepository.getBasedir(),
306                               localRepository.pathOfLocalRepositoryMetadata( metadata, remoteRepository ) );
307
308         try
309         {
310             resolveAlways( metadata, remoteRepository, file, ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN, false );
311         }
312         catch ( TransferFailedException e )
313         {
314             // TODO: [jc; 08-Nov-2005] revisit this for 2.1
315
// suppressing logging to avoid logging this error twice.
316
// We don't want to interrupt program flow here. Just allow empty metadata instead.
317
// rethrowing this would change behavior.
318
}
319
320         try
321         {
322             if ( file.exists() )
323             {
324                 Metadata prevMetadata = readMetadata( file );
325                 metadata.setMetadata( prevMetadata );
326             }
327         }
328         catch ( RepositoryMetadataReadException e )
329         {
330             throw new RepositoryMetadataResolutionException( e.getMessage(), e );
331         }
332     }
333
334     private void resolveAlways( ArtifactMetadata metadata, ArtifactRepository repository, File JavaDoc file,
335                                 String JavaDoc checksumPolicy, boolean allowBlacklisting )
336         throws RepositoryMetadataResolutionException, TransferFailedException
337     {
338         if ( !wagonManager.isOnline() )
339         {
340             if ( allowBlacklisting )
341             {
342                 getLogger().debug(
343                     "System is offline. Cannot resolve metadata:\n" + metadata.extendedToString() + "\n\n" );
344                 return;
345             }
346             else
347             {
348                 // metadata is required for deployment, can't be offline
349
throw new RepositoryMetadataResolutionException(
350                     "System is offline. Cannot resolve required metadata:\n" + metadata.extendedToString() );
351             }
352         }
353
354         try
355         {
356             wagonManager.getArtifactMetadata( metadata, repository, file, checksumPolicy );
357         }
358         catch ( ResourceDoesNotExistException e )
359         {
360             getLogger().debug( metadata + " could not be found on repository: " + repository.getId() );
361
362             // delete the local copy so the old details aren't used.
363
if ( file.exists() )
364             {
365                 file.delete();
366             }
367         }
368         catch ( TransferFailedException e )
369         {
370             getLogger().warn( metadata + " could not be retrieved from repository: " + repository.getId() +
371                 " due to an error: " + e.getMessage() );
372             getLogger().info( "Repository '" + repository.getId() + "' will be blacklisted" );
373             getLogger().debug( "Exception", e );
374             repository.setBlacklisted( allowBlacklisting );
375             
376             throw e;
377         }
378     }
379
380     private boolean alreadyResolved( ArtifactMetadata metadata )
381     {
382         return cachedMetadata.contains( metadata.getKey() );
383     }
384
385     public void deploy( ArtifactMetadata metadata, ArtifactRepository localRepository,
386                         ArtifactRepository deploymentRepository )
387         throws RepositoryMetadataDeploymentException
388     {
389         if ( !wagonManager.isOnline() )
390         {
391             // deployment shouldn't silently fail when offline
392
throw new RepositoryMetadataDeploymentException(
393                 "System is offline. Cannot deploy metadata:\n" + metadata.extendedToString() );
394         }
395
396         getLogger().info( "Retrieving previous metadata from " + deploymentRepository.getId() );
397
398         File JavaDoc file = new File JavaDoc( localRepository.getBasedir(),
399                               localRepository.pathOfLocalRepositoryMetadata( metadata, deploymentRepository ) );
400
401         try
402         {
403             resolveAlways( metadata, deploymentRepository, file, ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN, false );
404         }
405         catch ( RepositoryMetadataResolutionException e )
406         {
407             throw new RepositoryMetadataDeploymentException(
408                 "Unable to get previous metadata to update: " + e.getMessage(), e );
409         }
410         catch ( TransferFailedException e )
411         {
412             // TODO: [jc; 08-Nov-2005] revisit this for 2.1
413
// suppressing logging to avoid logging this error twice.
414
// We don't want to interrupt program flow here. Just allow empty metadata instead.
415
// rethrowing this would change behavior.
416
}
417
418         try
419         {
420             metadata.storeInLocalRepository( localRepository, deploymentRepository );
421         }
422         catch ( RepositoryMetadataStoreException e )
423         {
424             throw new RepositoryMetadataDeploymentException( "Error installing metadata: " + e.getMessage(), e );
425         }
426
427         try
428         {
429             wagonManager.putArtifactMetadata( file, metadata, deploymentRepository );
430         }
431         catch ( TransferFailedException e )
432         {
433             throw new RepositoryMetadataDeploymentException( "Error while deploying metadata: " + e.getMessage(), e );
434         }
435     }
436
437     public void install( ArtifactMetadata metadata, ArtifactRepository localRepository )
438         throws RepositoryMetadataInstallationException
439     {
440         try
441         {
442             metadata.storeInLocalRepository( localRepository, localRepository );
443         }
444         catch ( RepositoryMetadataStoreException e )
445         {
446             throw new RepositoryMetadataInstallationException( "Error installing metadata: " + e.getMessage(), e );
447         }
448     }
449 }
450
Popular Tags