Save This Page
Home » maven-2.0.9-src » org.apache » maven » artifact » repository » metadata » [javadoc | source]
    1   package org.apache.maven.artifact.repository.metadata;
    2   
    3   /*
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
   10    * with the License.  You may obtain a copy of the License at
   11    *
   12    *  http://www.apache.org/licenses/LICENSE-2.0
   13    *
   14    * Unless required by applicable law or agreed to in writing,
   15    * software distributed under the License is distributed on an
   16    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   17    * KIND, either express or implied.  See the License for the
   18    * specific language governing permissions and limitations
   19    * under the License.
   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       // component requirement
   51       private WagonManager wagonManager;
   52   
   53       /**
   54        * @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.
   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                                   // delete the local copy so the old details aren't used.
  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                                   // TODO: [jc; 08-Nov-2005] revisit this for 2.1
  123                                   // suppressing logging to avoid logging this error twice.
  124                               }
  125                               if ( storeMetadata )
  126                               {
  127                                   // touch file so that this is not checked again until interval has passed
  128                                   if ( file.exists() )
  129                                   {
  130                                       file.setLastModified( System.currentTimeMillis() );
  131                                   }
  132                                   else
  133                                   {
  134                                       // this ensures that files are not continuously checked when they don't exist remotely
  135   
  136                                       // TODO: [jdcasey] If this happens as a result of ResourceDoesNotExistException, what effect will it have on subsequent runs?
  137                                       // Will the updateInterval come into play cleanly, or will this plug up the works??
  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               // TODO: [jdcasey] what happens here when the system is offline, or there is a TransferFailedException
  160               // ...and no metadata file is written?
  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           // TODO: currently this is first wins, but really we should take the latest by comparing either the
  185           // snapshot timestamp, or some other timestamp later encoded into the metadata.
  186           // TODO: this needs to be repeated here so the merging doesn't interfere with the written metadata
  187           //  - we'd be much better having a pristine input, and an ongoing metadata for merging instead
  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() && !repository.isBlacklisted() )
  199                   && ( loadMetadata( metadata, repository, localRepository, previousMetadata ) ) )
  200               {
  201                   metadata.setRepository( repository );
  202                   selected = repository;
  203               }
  204           }
  205           if ( loadMetadata( metadata, localRepository, localRepository, previousMetadata ) )
  206           {
  207               metadata.setRepository( null );
  208               selected = localRepository;
  209           }
  210   
  211           updateSnapshotMetadata( metadata, previousMetadata, selected, localRepository );
  212       }
  213   
  214       private void updateSnapshotMetadata( RepositoryMetadata metadata, Map previousMetadata, ArtifactRepository selected,
  215                                            ArtifactRepository localRepository )
  216           throws RepositoryMetadataStoreException
  217       {
  218           // TODO: this could be a lot nicer... should really be in the snapshot transformation?
  219           if ( metadata.isSnapshot() )
  220           {
  221               Metadata prevMetadata = metadata.getMetadata();
  222   
  223               for ( Iterator i = previousMetadata.keySet().iterator(); i.hasNext(); )
  224               {
  225                   ArtifactRepository repository = (ArtifactRepository) i.next();
  226                   Metadata m = (Metadata) previousMetadata.get( repository );
  227                   if ( repository.equals( selected ) )
  228                   {
  229                       if ( m.getVersioning() == null )
  230                       {
  231                           m.setVersioning( new Versioning() );
  232                       }
  233   
  234                       if ( m.getVersioning().getSnapshot() == null )
  235                       {
  236                           m.getVersioning().setSnapshot( new Snapshot() );
  237                       }
  238   /*
  239                       if ( !m.getVersioning().getSnapshot().isLocalCopy() )
  240                       {
  241                           // TODO: I think this is incorrect (it results in localCopy set in a remote profile). Probably
  242                           //   harmless so not removing at this point until full tests in place.
  243                           m.getVersioning().getSnapshot().setLocalCopy( true );
  244                           metadata.setMetadata( m );
  245                           metadata.storeInLocalRepository( localRepository, repository );
  246                       }
  247   */
  248                   }
  249                   else
  250                   {
  251                       if ( ( m.getVersioning() != null ) && ( m.getVersioning().getSnapshot() != null ) &&
  252                           m.getVersioning().getSnapshot().isLocalCopy() )
  253                       {
  254                           m.getVersioning().getSnapshot().setLocalCopy( false );
  255                           metadata.setMetadata( m );
  256                           metadata.storeInLocalRepository( localRepository, repository );
  257                       }
  258                   }
  259               }
  260   
  261               metadata.setMetadata( prevMetadata );
  262           }
  263       }
  264   
  265       private boolean loadMetadata( RepositoryMetadata repoMetadata, ArtifactRepository remoteRepository,
  266                                     ArtifactRepository localRepository, Map previousMetadata )
  267           throws RepositoryMetadataReadException
  268       {
  269           boolean setRepository = false;
  270   
  271           File metadataFile = new File( localRepository.getBasedir(),
  272                                         localRepository.pathOfLocalRepositoryMetadata( repoMetadata, remoteRepository ) );
  273   
  274           if ( metadataFile.exists() )
  275           {
  276               Metadata metadata = readMetadata( metadataFile );
  277   
  278               if ( repoMetadata.isSnapshot() && ( previousMetadata != null ) )
  279               {
  280                   previousMetadata.put( remoteRepository, metadata );
  281               }
  282   
  283               if ( repoMetadata.getMetadata() != null )
  284               {
  285                   setRepository = repoMetadata.getMetadata().merge( metadata );
  286               }
  287               else
  288               {
  289                   repoMetadata.setMetadata( metadata );
  290                   setRepository = true;
  291               }
  292           }
  293           return setRepository;
  294       }
  295   
  296       /**
  297        * @todo share with DefaultPluginMappingManager.
  298        */
  299       protected static Metadata readMetadata( File mappingFile )
  300           throws RepositoryMetadataReadException
  301       {
  302           Metadata result;
  303   
  304           Reader reader = null;
  305           try
  306           {
  307               reader = ReaderFactory.newXmlReader( mappingFile );
  308   
  309               MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
  310   
  311               result = mappingReader.read( reader, false );
  312           }
  313           catch ( FileNotFoundException e )
  314           {
  315               throw new RepositoryMetadataReadException( "Cannot read metadata from '" + mappingFile + "'", e );
  316           }
  317           catch ( IOException e )
  318           {
  319               throw new RepositoryMetadataReadException(
  320                   "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e );
  321           }
  322           catch ( XmlPullParserException e )
  323           {
  324               throw new RepositoryMetadataReadException(
  325                   "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e );
  326           }
  327           finally
  328           {
  329               IOUtil.close( reader );
  330           }
  331           return result;
  332       }
  333   
  334       public void resolveAlways( RepositoryMetadata metadata, ArtifactRepository localRepository,
  335                                  ArtifactRepository remoteRepository )
  336           throws RepositoryMetadataResolutionException
  337       {
  338           if ( !wagonManager.isOnline() )
  339           {
  340               // metadata is required for deployment, can't be offline
  341               throw new RepositoryMetadataResolutionException(
  342                   "System is offline. Cannot resolve required metadata:\n" + metadata.extendedToString() );
  343           }
  344   
  345           File file;
  346           try
  347           {
  348               file = getArtifactMetadataFromDeploymentRepository( metadata, localRepository, remoteRepository );
  349           }
  350           catch ( TransferFailedException e )
  351           {
  352               throw new RepositoryMetadataResolutionException( metadata + " could not be retrieved from repository: " +
  353                   remoteRepository.getId() + " due to an error: " + e.getMessage(), e );
  354           }
  355   
  356           try
  357           {
  358               if ( file.exists() )
  359               {
  360                   Metadata prevMetadata = readMetadata( file );
  361                   metadata.setMetadata( prevMetadata );
  362               }
  363           }
  364           catch ( RepositoryMetadataReadException e )
  365           {
  366               throw new RepositoryMetadataResolutionException( e.getMessage(), e );
  367           }
  368       }
  369   
  370       private File getArtifactMetadataFromDeploymentRepository( ArtifactMetadata metadata,
  371                                                                 ArtifactRepository localRepository,
  372                                                                 ArtifactRepository remoteRepository )
  373           throws TransferFailedException
  374       {
  375           File file = new File( localRepository.getBasedir(),
  376                                 localRepository.pathOfLocalRepositoryMetadata( metadata, remoteRepository ) );
  377   
  378           try
  379           {
  380               wagonManager.getArtifactMetadataFromDeploymentRepository( metadata, remoteRepository, file,
  381                                                                         ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
  382           }
  383           catch ( ResourceDoesNotExistException e )
  384           {
  385               getLogger().info(
  386                   metadata + " could not be found on repository: " + remoteRepository.getId() + ", so will be created" );
  387   
  388               // delete the local copy so the old details aren't used.
  389               if ( file.exists() )
  390               {
  391                   file.delete();
  392               }
  393           }
  394           return file;
  395       }
  396   
  397       private boolean alreadyResolved( ArtifactMetadata metadata )
  398       {
  399           return cachedMetadata.contains( metadata.getKey() );
  400       }
  401   
  402       public void deploy( ArtifactMetadata metadata, ArtifactRepository localRepository,
  403                           ArtifactRepository deploymentRepository )
  404           throws RepositoryMetadataDeploymentException
  405       {
  406           if ( !wagonManager.isOnline() )
  407           {
  408               // deployment shouldn't silently fail when offline
  409               throw new RepositoryMetadataDeploymentException(
  410                   "System is offline. Cannot deploy metadata:\n" + metadata.extendedToString() );
  411           }
  412   
  413           File file;
  414           if ( metadata instanceof RepositoryMetadata )
  415           {
  416               getLogger().info( "Retrieving previous metadata from " + deploymentRepository.getId() );
  417               try
  418               {
  419                   file = getArtifactMetadataFromDeploymentRepository( metadata, localRepository, deploymentRepository );
  420               }
  421               catch ( TransferFailedException e )
  422               {
  423                   throw new RepositoryMetadataDeploymentException( metadata +
  424                       " could not be retrieved from repository: " + deploymentRepository.getId() + " due to an error: " +
  425                       e.getMessage(), e );
  426               }
  427           }
  428           else
  429           {
  430               // It's a POM - we don't need to retrieve it first
  431               file = new File( localRepository.getBasedir(),
  432                                localRepository.pathOfLocalRepositoryMetadata( metadata, deploymentRepository ) );
  433           }
  434   
  435           try
  436           {
  437               metadata.storeInLocalRepository( localRepository, deploymentRepository );
  438           }
  439           catch ( RepositoryMetadataStoreException e )
  440           {
  441               throw new RepositoryMetadataDeploymentException( "Error installing metadata: " + e.getMessage(), e );
  442           }
  443   
  444           try
  445           {
  446               wagonManager.putArtifactMetadata( file, metadata, deploymentRepository );
  447           }
  448           catch ( TransferFailedException e )
  449           {
  450               throw new RepositoryMetadataDeploymentException( "Error while deploying metadata: " + e.getMessage(), e );
  451           }
  452       }
  453   
  454       public void install( ArtifactMetadata metadata, ArtifactRepository localRepository )
  455           throws RepositoryMetadataInstallationException
  456       {
  457           try
  458           {
  459               metadata.storeInLocalRepository( localRepository, localRepository );
  460           }
  461           catch ( RepositoryMetadataStoreException e )
  462           {
  463               throw new RepositoryMetadataInstallationException( "Error installing metadata: " + e.getMessage(), e );
  464           }
  465       }
  466   }

Save This Page
Home » maven-2.0.9-src » org.apache » maven » artifact » repository » metadata » [javadoc | source]