View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.artifact.repository.metadata;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.Reader;
24  import java.io.Writer;
25  import org.apache.maven.artifact.Artifact;
26  import org.apache.maven.artifact.metadata.ArtifactMetadata;
27  import org.apache.maven.artifact.repository.ArtifactRepository;
28  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
29  import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
30  import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
31  import org.codehaus.plexus.util.ReaderFactory;
32  import org.codehaus.plexus.util.WriterFactory;
33  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
34  
35  /**
36   * Shared methods of the repository metadata handling.
37   *
38   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
39   */
40  public abstract class AbstractRepositoryMetadata implements RepositoryMetadata {
41      private static final String LS = System.lineSeparator();
42  
43      private Metadata metadata;
44  
45      protected AbstractRepositoryMetadata(Metadata metadata) {
46          this.metadata = metadata;
47      }
48  
49      public String getRemoteFilename() {
50          return "maven-metadata.xml";
51      }
52  
53      public String getLocalFilename(ArtifactRepository repository) {
54          return "maven-metadata-" + repository.getKey() + ".xml";
55      }
56  
57      public void storeInLocalRepository(ArtifactRepository localRepository, ArtifactRepository remoteRepository)
58              throws RepositoryMetadataStoreException {
59          try {
60              updateRepositoryMetadata(localRepository, remoteRepository);
61          } catch (IOException | XmlPullParserException e) {
62              throw new RepositoryMetadataStoreException("Error updating group repository metadata", e);
63          }
64      }
65  
66      protected void updateRepositoryMetadata(ArtifactRepository localRepository, ArtifactRepository remoteRepository)
67              throws IOException, XmlPullParserException {
68          MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
69  
70          Metadata metadata = null;
71  
72          File metadataFile = new File(
73                  localRepository.getBasedir(), localRepository.pathOfLocalRepositoryMetadata(this, remoteRepository));
74  
75          if (metadataFile.length() == 0) {
76              if (!metadataFile.delete()) {
77                  // sleep for 10ms just in case this is windows holding a file lock
78                  try {
79                      Thread.sleep(10);
80                  } catch (InterruptedException e) {
81                      // ignore
82                  }
83                  metadataFile.delete(); // if this fails, forget about it, we'll try to overwrite it anyway so no need
84                  // to delete on exit
85              }
86          } else if (metadataFile.exists()) {
87              try (Reader reader = ReaderFactory.newXmlReader(metadataFile)) {
88                  metadata = mappingReader.read(reader, false);
89              }
90          }
91  
92          boolean changed;
93  
94          // If file could not be found or was not valid, start from scratch
95          if (metadata == null) {
96              metadata = this.metadata;
97  
98              changed = true;
99          } else {
100             changed = metadata.merge(this.metadata);
101         }
102 
103         // beware meta-versions!
104         String version = metadata.getVersion();
105         if (Artifact.LATEST_VERSION.equals(version) || Artifact.RELEASE_VERSION.equals(version)) {
106             // meta-versions are not valid <version/> values...don't write them.
107             metadata.setVersion(null);
108         }
109 
110         if (changed || !metadataFile.exists()) {
111             metadataFile.getParentFile().mkdirs();
112             try (Writer writer = WriterFactory.newXmlWriter(metadataFile)) {
113                 MetadataXpp3Writer mappingWriter = new MetadataXpp3Writer();
114 
115                 mappingWriter.write(writer, metadata);
116             }
117         } else {
118             metadataFile.setLastModified(System.currentTimeMillis());
119         }
120     }
121 
122     public String toString() {
123         return "repository metadata for: '" + getKey() + "'";
124     }
125 
126     protected static Metadata createMetadata(Artifact artifact, Versioning versioning) {
127         Metadata metadata = new Metadata();
128         metadata.setGroupId(artifact.getGroupId());
129         metadata.setArtifactId(artifact.getArtifactId());
130         metadata.setVersion(artifact.getVersion());
131         metadata.setVersioning(versioning);
132         return metadata;
133     }
134 
135     protected static Versioning createVersioning(Snapshot snapshot) {
136         Versioning versioning = new Versioning();
137         versioning.setSnapshot(snapshot);
138         return versioning;
139     }
140 
141     public void setMetadata(Metadata metadata) {
142         this.metadata = metadata;
143     }
144 
145     public Metadata getMetadata() {
146         return metadata;
147     }
148 
149     public void merge(org.apache.maven.repository.legacy.metadata.ArtifactMetadata metadata) {
150         // TODO not sure that it should assume this, maybe the calls to addMetadata should pre-merge, then artifact
151         // replaces?
152         AbstractRepositoryMetadata repoMetadata = (AbstractRepositoryMetadata) metadata;
153         this.metadata.merge(repoMetadata.getMetadata());
154     }
155 
156     public void merge(ArtifactMetadata metadata) {
157         // TODO not sure that it should assume this, maybe the calls to addMetadata should pre-merge, then artifact
158         // replaces?
159         AbstractRepositoryMetadata repoMetadata = (AbstractRepositoryMetadata) metadata;
160         this.metadata.merge(repoMetadata.getMetadata());
161     }
162 
163     public String extendedToString() {
164         StringBuilder buffer = new StringBuilder(256);
165 
166         buffer.append(LS).append("Repository Metadata").append(LS).append("--------------------------");
167         buffer.append(LS).append("GroupId: ").append(getGroupId());
168         buffer.append(LS).append("ArtifactId: ").append(getArtifactId());
169         buffer.append(LS).append("Metadata Type: ").append(getClass().getName());
170 
171         return buffer.toString();
172     }
173 
174     public int getNature() {
175         return RELEASE;
176     }
177 
178     public ArtifactRepositoryPolicy getPolicy(ArtifactRepository repository) {
179         int nature = getNature();
180         if ((nature & RepositoryMetadata.RELEASE_OR_SNAPSHOT) == RepositoryMetadata.RELEASE_OR_SNAPSHOT) {
181             ArtifactRepositoryPolicy policy = new ArtifactRepositoryPolicy(repository.getReleases());
182             policy.merge(repository.getSnapshots());
183             return policy;
184         } else if ((nature & RepositoryMetadata.SNAPSHOT) != 0) {
185             return repository.getSnapshots();
186         } else {
187             return repository.getReleases();
188         }
189     }
190 }