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