View Javadoc
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.Artifact;
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.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
28  import org.codehaus.plexus.util.ReaderFactory;
29  import org.codehaus.plexus.util.WriterFactory;
30  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
31  
32  import java.io.File;
33  import java.io.IOException;
34  import java.io.Reader;
35  import java.io.Writer;
36  
37  /**
38   * Shared methods of the repository metadata handling.
39   *
40   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
41   */
42  public abstract class AbstractRepositoryMetadata
43      implements RepositoryMetadata
44  {
45      private static final String LS = System.lineSeparator();
46  
47      private Metadata metadata;
48  
49      protected AbstractRepositoryMetadata( Metadata metadata )
50      {
51          this.metadata = metadata;
52      }
53  
54      public String getRemoteFilename()
55      {
56          return "maven-metadata.xml";
57      }
58  
59      public String getLocalFilename( ArtifactRepository repository )
60      {
61          return "maven-metadata-" + repository.getKey() + ".xml";
62      }
63  
64      public void storeInLocalRepository( ArtifactRepository localRepository, ArtifactRepository remoteRepository )
65          throws RepositoryMetadataStoreException
66      {
67          try
68          {
69              updateRepositoryMetadata( localRepository, remoteRepository );
70          }
71          catch ( IOException | XmlPullParserException e )
72          {
73              throw new RepositoryMetadataStoreException( "Error updating group repository metadata", e );
74          }
75      }
76  
77      protected void updateRepositoryMetadata( ArtifactRepository localRepository, ArtifactRepository remoteRepository )
78          throws IOException, XmlPullParserException
79      {
80          MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
81  
82          Metadata metadata = null;
83  
84          File metadataFile = new File( localRepository.getBasedir(),
85                                        localRepository.pathOfLocalRepositoryMetadata( this, remoteRepository ) );
86  
87          if ( metadataFile.length() == 0 )
88          {
89              if ( !metadataFile.delete() )
90              {
91                  // sleep for 10ms just in case this is windows holding a file lock
92                  try
93                  {
94                      Thread.sleep( 10 );
95                  }
96                  catch ( InterruptedException e )
97                  {
98                      // ignore
99                  }
100                 metadataFile.delete(); // if this fails, forget about it, we'll try to overwrite it anyway so no need
101                 // to delete on exit
102             }
103         }
104         else if ( metadataFile.exists() )
105         {
106             try ( Reader reader = ReaderFactory.newXmlReader( metadataFile ) )
107             {
108                 metadata = mappingReader.read( reader, false );
109             }
110         }
111 
112         boolean changed;
113 
114         // If file could not be found or was not valid, start from scratch
115         if ( metadata == null )
116         {
117             metadata = this.metadata;
118 
119             changed = true;
120         }
121         else
122         {
123             changed = metadata.merge( this.metadata );
124         }
125 
126         // beware meta-versions!
127         String version = metadata.getVersion();
128         if ( Artifact.LATEST_VERSION.equals( version ) || Artifact.RELEASE_VERSION.equals( version ) )
129         {
130             // meta-versions are not valid <version/> values...don't write them.
131             metadata.setVersion( null );
132         }
133 
134         if ( changed || !metadataFile.exists() )
135         {
136             metadataFile.getParentFile().mkdirs();
137             try ( Writer writer = WriterFactory.newXmlWriter( metadataFile ) )
138             {
139                 MetadataXpp3Writer mappingWriter = new MetadataXpp3Writer();
140 
141                 mappingWriter.write( writer, metadata );
142             }
143         }
144         else
145         {
146             metadataFile.setLastModified( System.currentTimeMillis() );
147         }
148     }
149 
150     public String toString()
151     {
152         return "repository metadata for: '" + getKey() + "'";
153     }
154 
155     protected static Metadata createMetadata( Artifact artifact, Versioning versioning )
156     {
157         Metadata metadata = new Metadata();
158         metadata.setGroupId( artifact.getGroupId() );
159         metadata.setArtifactId( artifact.getArtifactId() );
160         metadata.setVersion( artifact.getVersion() );
161         metadata.setVersioning( versioning );
162         return metadata;
163     }
164 
165     protected static Versioning createVersioning( Snapshot snapshot )
166     {
167         Versioning versioning = new Versioning();
168         versioning.setSnapshot( snapshot );
169         return versioning;
170     }
171 
172     public void setMetadata( Metadata metadata )
173     {
174         this.metadata = metadata;
175     }
176 
177     public Metadata getMetadata()
178     {
179         return metadata;
180     }
181 
182     public void merge( org.apache.maven.repository.legacy.metadata.ArtifactMetadata metadata )
183     {
184         // TODO not sure that it should assume this, maybe the calls to addMetadata should pre-merge, then artifact
185         // replaces?
186         AbstractRepositoryMetadata repoMetadata = (AbstractRepositoryMetadata) metadata;
187         this.metadata.merge( repoMetadata.getMetadata() );
188     }
189 
190     public void merge( ArtifactMetadata metadata )
191     {
192         // TODO not sure that it should assume this, maybe the calls to addMetadata should pre-merge, then artifact
193         // replaces?
194         AbstractRepositoryMetadata repoMetadata = (AbstractRepositoryMetadata) metadata;
195         this.metadata.merge( repoMetadata.getMetadata() );
196     }
197 
198     public String extendedToString()
199     {
200         StringBuilder buffer = new StringBuilder( 256 );
201 
202         buffer.append( LS ).append( "Repository Metadata" ).append( LS ).append( "--------------------------" );
203         buffer.append( LS ).append( "GroupId: " ).append( getGroupId() );
204         buffer.append( LS ).append( "ArtifactId: " ).append( getArtifactId() );
205         buffer.append( LS ).append( "Metadata Type: " ).append( getClass().getName() );
206 
207         return buffer.toString();
208     }
209 
210     public int getNature()
211     {
212         return RELEASE;
213     }
214 
215     public ArtifactRepositoryPolicy getPolicy( ArtifactRepository repository )
216     {
217         int nature = getNature();
218         if ( ( nature & RepositoryMetadata.RELEASE_OR_SNAPSHOT ) == RepositoryMetadata.RELEASE_OR_SNAPSHOT )
219         {
220             ArtifactRepositoryPolicy policy = new ArtifactRepositoryPolicy( repository.getReleases() );
221             policy.merge( repository.getSnapshots() );
222             return policy;
223         }
224         else if ( ( nature & RepositoryMetadata.SNAPSHOT ) != 0 )
225         {
226             return repository.getSnapshots();
227         }
228         else
229         {
230             return repository.getReleases();
231         }
232     }
233 
234 }