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.project.artifact;
20  
21  import javax.inject.Named;
22  import javax.inject.Singleton;
23  
24  import java.io.File;
25  import java.util.ArrayList;
26  import java.util.Iterator;
27  import java.util.LinkedHashMap;
28  import java.util.LinkedHashSet;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Objects;
32  import java.util.Set;
33  import java.util.concurrent.ConcurrentHashMap;
34  
35  import org.apache.maven.artifact.Artifact;
36  import org.apache.maven.artifact.ArtifactUtils;
37  import org.apache.maven.artifact.metadata.ResolutionGroup;
38  import org.apache.maven.artifact.repository.ArtifactRepository;
39  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
40  
41  /**
42   * DefaultMavenMetadataCache
43   */
44  @Named
45  @Singleton
46  @Deprecated
47  public class DefaultMavenMetadataCache implements MavenMetadataCache {
48  
49      protected final Map<CacheKey, CacheRecord> cache = new ConcurrentHashMap<>();
50  
51      /**
52       * CacheKey
53       */
54      public static class CacheKey {
55          private final Artifact artifact;
56          private final long pomHash;
57          private final boolean resolveManagedVersions;
58          private final List<ArtifactRepository> repositories = new ArrayList<>();
59          private final int hashCode;
60  
61          public CacheKey(
62                  Artifact artifact,
63                  boolean resolveManagedVersions,
64                  ArtifactRepository localRepository,
65                  List<ArtifactRepository> remoteRepositories) {
66              File file = artifact.getFile();
67              this.artifact = ArtifactUtils.copyArtifact(artifact);
68              if ("pom".equals(artifact.getType()) && file != null) {
69                  pomHash = file.getPath().hashCode() + file.lastModified();
70              } else {
71                  pomHash = 0;
72              }
73              this.resolveManagedVersions = resolveManagedVersions;
74              this.repositories.add(localRepository);
75              this.repositories.addAll(remoteRepositories);
76  
77              int hash = 17;
78              hash = hash * 31 + artifactHashCode(artifact);
79              hash = hash * 31 + (resolveManagedVersions ? 1 : 2);
80              hash = hash * 31 + repositoriesHashCode(repositories);
81              this.hashCode = hash;
82          }
83  
84          @Override
85          public int hashCode() {
86              return hashCode;
87          }
88  
89          @Override
90          public boolean equals(Object o) {
91              if (o == this) {
92                  return true;
93              }
94  
95              if (!(o instanceof CacheKey)) {
96                  return false;
97              }
98  
99              CacheKey other = (CacheKey) o;
100 
101             return pomHash == other.pomHash
102                     && artifactEquals(artifact, other.artifact)
103                     && resolveManagedVersions == other.resolveManagedVersions
104                     && repositoriesEquals(repositories, other.repositories);
105         }
106     }
107 
108     private static int artifactHashCode(Artifact a) {
109         int result = 17;
110         result = 31 * result + a.getGroupId().hashCode();
111         result = 31 * result + a.getArtifactId().hashCode();
112         result = 31 * result + a.getType().hashCode();
113         if (a.getVersion() != null) {
114             result = 31 * result + a.getVersion().hashCode();
115         }
116         result = 31 * result + (a.getClassifier() != null ? a.getClassifier().hashCode() : 0);
117         result = 31 * result + (a.getScope() != null ? a.getScope().hashCode() : 0);
118         result = 31 * result
119                 + (a.getDependencyFilter() != null ? a.getDependencyFilter().hashCode() : 0);
120         result = 31 * result + (a.isOptional() ? 1 : 0);
121         return result;
122     }
123 
124     private static boolean artifactEquals(Artifact a1, Artifact a2) {
125         if (a1 == a2) {
126             return true;
127         }
128 
129         return Objects.equals(a1.getGroupId(), a2.getGroupId())
130                 && Objects.equals(a1.getArtifactId(), a2.getArtifactId())
131                 && Objects.equals(a1.getType(), a2.getType())
132                 && Objects.equals(a1.getVersion(), a2.getVersion())
133                 && Objects.equals(a1.getClassifier(), a2.getClassifier())
134                 && Objects.equals(a1.getScope(), a2.getScope())
135                 && Objects.equals(a1.getDependencyFilter(), a2.getDependencyFilter())
136                 && a1.isOptional() == a2.isOptional();
137     }
138 
139     private static int repositoryHashCode(ArtifactRepository repository) {
140         int result = 17;
141         result = 31 * result + (repository.getId() != null ? repository.getId().hashCode() : 0);
142         return result;
143     }
144 
145     private static int repositoriesHashCode(List<ArtifactRepository> repositories) {
146         int result = 17;
147         for (ArtifactRepository repository : repositories) {
148             result = 31 * result + repositoryHashCode(repository);
149         }
150         return result;
151     }
152 
153     private static boolean repositoryEquals(ArtifactRepository r1, ArtifactRepository r2) {
154         if (r1 == r2) {
155             return true;
156         }
157 
158         return Objects.equals(r1.getId(), r2.getId())
159                 && Objects.equals(r1.getUrl(), r2.getUrl())
160                 && repositoryPolicyEquals(r1.getReleases(), r2.getReleases())
161                 && repositoryPolicyEquals(r1.getSnapshots(), r2.getSnapshots());
162     }
163 
164     private static boolean repositoryPolicyEquals(ArtifactRepositoryPolicy p1, ArtifactRepositoryPolicy p2) {
165         if (p1 == p2) {
166             return true;
167         }
168 
169         return p1.isEnabled() == p2.isEnabled() && Objects.equals(p1.getUpdatePolicy(), p2.getUpdatePolicy());
170     }
171 
172     private static boolean repositoriesEquals(List<ArtifactRepository> r1, List<ArtifactRepository> r2) {
173         if (r1.size() != r2.size()) {
174             return false;
175         }
176 
177         for (Iterator<ArtifactRepository> it1 = r1.iterator(), it2 = r2.iterator(); it1.hasNext(); ) {
178             if (!repositoryEquals(it1.next(), it2.next())) {
179                 return false;
180             }
181         }
182 
183         return true;
184     }
185 
186     /**
187      * CacheRecord
188      */
189     public class CacheRecord {
190         private Artifact pomArtifact;
191         private Artifact relocatedArtifact;
192         private List<Artifact> artifacts;
193         private Map<String, Artifact> managedVersions;
194         private List<ArtifactRepository> remoteRepositories;
195 
196         private long length;
197         private long timestamp;
198 
199         CacheRecord(
200                 Artifact pomArtifact,
201                 Artifact relocatedArtifact,
202                 Set<Artifact> artifacts,
203                 Map<String, Artifact> managedVersions,
204                 List<ArtifactRepository> remoteRepositories) {
205             this.pomArtifact = ArtifactUtils.copyArtifact(pomArtifact);
206             this.relocatedArtifact = ArtifactUtils.copyArtifactSafe(relocatedArtifact);
207             this.artifacts = ArtifactUtils.copyArtifacts(artifacts, new ArrayList<>());
208             this.remoteRepositories = new ArrayList<>(remoteRepositories);
209 
210             this.managedVersions = managedVersions;
211             if (managedVersions != null) {
212                 this.managedVersions = ArtifactUtils.copyArtifacts(managedVersions, new LinkedHashMap<>());
213             }
214 
215             File pomFile = pomArtifact.getFile();
216             if (pomFile != null && pomFile.canRead()) {
217                 this.length = pomFile.length();
218                 this.timestamp = pomFile.lastModified();
219             } else {
220                 this.length = -1;
221                 this.timestamp = -1;
222             }
223         }
224 
225         public Artifact getArtifact() {
226             return pomArtifact;
227         }
228 
229         public Artifact getRelocatedArtifact() {
230             return relocatedArtifact;
231         }
232 
233         public List<Artifact> getArtifacts() {
234             return artifacts;
235         }
236 
237         public Map<String, Artifact> getManagedVersions() {
238             return managedVersions;
239         }
240 
241         public List<ArtifactRepository> getRemoteRepositories() {
242             return remoteRepositories;
243         }
244 
245         public boolean isStale() {
246             File pomFile = pomArtifact.getFile();
247             if (pomFile != null) {
248                 if (pomFile.canRead()) {
249                     return length != pomFile.length() || timestamp != pomFile.lastModified();
250                 } else {
251                     // if the POM didn't exist, retry if any repo is configured to always update
252                     boolean snapshot = pomArtifact.isSnapshot();
253                     for (ArtifactRepository repository : remoteRepositories) {
254                         ArtifactRepositoryPolicy policy =
255                                 snapshot ? repository.getSnapshots() : repository.getReleases();
256                         if (ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS.equals(policy.getUpdatePolicy())) {
257                             return true;
258                         }
259                     }
260                 }
261             }
262 
263             return length != -1 || timestamp != -1;
264         }
265     }
266 
267     public ResolutionGroup get(
268             Artifact artifact,
269             boolean resolveManagedVersions,
270             ArtifactRepository localRepository,
271             List<ArtifactRepository> remoteRepositories) {
272         CacheKey cacheKey = newCacheKey(artifact, resolveManagedVersions, localRepository, remoteRepositories);
273 
274         CacheRecord cacheRecord = cache.get(cacheKey);
275 
276         if (cacheRecord != null && !cacheRecord.isStale()) {
277             Artifact pomArtifact = ArtifactUtils.copyArtifact(cacheRecord.getArtifact());
278             Artifact relocatedArtifact = ArtifactUtils.copyArtifactSafe(cacheRecord.getRelocatedArtifact());
279             Set<Artifact> artifacts = ArtifactUtils.copyArtifacts(cacheRecord.getArtifacts(), new LinkedHashSet<>());
280             Map<String, Artifact> managedVersions = cacheRecord.getManagedVersions();
281             if (managedVersions != null) {
282                 managedVersions = ArtifactUtils.copyArtifacts(managedVersions, new LinkedHashMap<>());
283             }
284             return new ResolutionGroup(
285                     pomArtifact, relocatedArtifact, artifacts, managedVersions, cacheRecord.getRemoteRepositories());
286         }
287 
288         cache.remove(cacheKey);
289 
290         return null;
291     }
292 
293     public void put(
294             Artifact artifact,
295             boolean resolveManagedVersions,
296             ArtifactRepository localRepository,
297             List<ArtifactRepository> remoteRepositories,
298             ResolutionGroup result) {
299         put(newCacheKey(artifact, resolveManagedVersions, localRepository, remoteRepositories), result);
300     }
301 
302     protected CacheKey newCacheKey(
303             Artifact artifact,
304             boolean resolveManagedVersions,
305             ArtifactRepository localRepository,
306             List<ArtifactRepository> remoteRepositories) {
307         return new CacheKey(artifact, resolveManagedVersions, localRepository, remoteRepositories);
308     }
309 
310     protected void put(CacheKey cacheKey, ResolutionGroup result) {
311         CacheRecord cacheRecord = new CacheRecord(
312                 result.getPomArtifact(),
313                 result.getRelocatedArtifact(),
314                 result.getArtifacts(),
315                 result.getManagedVersions(),
316                 result.getResolutionRepositories());
317 
318         cache.put(cacheKey, cacheRecord);
319     }
320 
321     public void flush() {
322         cache.clear();
323     }
324 }