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