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.plugin;
20  
21  import javax.inject.Named;
22  import javax.inject.Singleton;
23  
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Objects;
29  import java.util.concurrent.ConcurrentHashMap;
30  
31  import org.apache.maven.RepositoryUtils;
32  import org.apache.maven.artifact.Artifact;
33  import org.apache.maven.model.Plugin;
34  import org.apache.maven.project.MavenProject;
35  import org.eclipse.aether.RepositorySystemSession;
36  import org.eclipse.aether.graph.DependencyFilter;
37  import org.eclipse.aether.repository.LocalRepository;
38  import org.eclipse.aether.repository.RemoteRepository;
39  import org.eclipse.aether.repository.WorkspaceRepository;
40  
41  /**
42   * @author Igor Fedorenko
43   * @author Benjamin Bentmann
44   */
45  @Named
46  @Singleton
47  public class DefaultPluginArtifactsCache implements PluginArtifactsCache {
48      /**
49       * CacheKey
50       */
51      protected static class CacheKey implements Key {
52          private final Plugin plugin;
53  
54          private final WorkspaceRepository workspace;
55  
56          private final LocalRepository localRepo;
57  
58          private final List<RemoteRepository> repositories;
59  
60          private final DependencyFilter filter;
61  
62          private final int hashCode;
63  
64          public CacheKey(
65                  Plugin plugin,
66                  DependencyFilter extensionFilter,
67                  List<RemoteRepository> repositories,
68                  RepositorySystemSession session) {
69              this.plugin = plugin.clone();
70              workspace = RepositoryUtils.getWorkspace(session);
71              this.localRepo = session.getLocalRepository();
72              this.repositories = new ArrayList<>(repositories.size());
73              for (RemoteRepository repository : repositories) {
74                  if (repository.isRepositoryManager()) {
75                      this.repositories.addAll(repository.getMirroredRepositories());
76                  } else {
77                      this.repositories.add(repository);
78                  }
79              }
80              this.filter = extensionFilter;
81  
82              int hash = 17;
83              hash = hash * 31 + CacheUtils.pluginHashCode(plugin);
84              hash = hash * 31 + Objects.hashCode(workspace);
85              hash = hash * 31 + Objects.hashCode(localRepo);
86              hash = hash * 31 + RepositoryUtils.repositoriesHashCode(repositories);
87              hash = hash * 31 + Objects.hashCode(extensionFilter);
88              this.hashCode = hash;
89          }
90  
91          @Override
92          public String toString() {
93              return plugin.getId();
94          }
95  
96          @Override
97          public int hashCode() {
98              return hashCode;
99          }
100 
101         @Override
102         public boolean equals(Object o) {
103             if (o == this) {
104                 return true;
105             }
106 
107             if (!(o instanceof CacheKey)) {
108                 return false;
109             }
110 
111             CacheKey that = (CacheKey) o;
112 
113             return CacheUtils.pluginEquals(plugin, that.plugin)
114                     && Objects.equals(workspace, that.workspace)
115                     && Objects.equals(localRepo, that.localRepo)
116                     && RepositoryUtils.repositoriesEquals(repositories, that.repositories)
117                     && Objects.equals(filter, that.filter);
118         }
119     }
120 
121     protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<>();
122 
123     public Key createKey(
124             Plugin plugin,
125             DependencyFilter extensionFilter,
126             List<RemoteRepository> repositories,
127             RepositorySystemSession session) {
128         return new CacheKey(plugin, extensionFilter, repositories, session);
129     }
130 
131     public CacheRecord get(Key key) throws PluginResolutionException {
132         CacheRecord cacheRecord = cache.get(key);
133 
134         if (cacheRecord != null && cacheRecord.getException() != null) {
135             throw cacheRecord.getException();
136         }
137 
138         return cacheRecord;
139     }
140 
141     public CacheRecord put(Key key, List<Artifact> pluginArtifacts) {
142         Objects.requireNonNull(pluginArtifacts, "pluginArtifacts cannot be null");
143 
144         assertUniqueKey(key);
145 
146         CacheRecord record = new CacheRecord(Collections.unmodifiableList(new ArrayList<>(pluginArtifacts)));
147 
148         cache.put(key, record);
149 
150         return record;
151     }
152 
153     protected void assertUniqueKey(Key key) {
154         if (cache.containsKey(key)) {
155             throw new IllegalStateException("Duplicate artifact resolution result for plugin " + key);
156         }
157     }
158 
159     public CacheRecord put(Key key, PluginResolutionException exception) {
160         Objects.requireNonNull(exception, "exception cannot be null");
161 
162         assertUniqueKey(key);
163 
164         CacheRecord record = new CacheRecord(exception);
165 
166         cache.put(key, record);
167 
168         return record;
169     }
170 
171     public void flush() {
172         cache.clear();
173     }
174 
175     protected static int pluginHashCode(Plugin plugin) {
176         return CacheUtils.pluginHashCode(plugin);
177     }
178 
179     protected static boolean pluginEquals(Plugin a, Plugin b) {
180         return CacheUtils.pluginEquals(a, b);
181     }
182 
183     public void register(MavenProject project, Key cacheKey, CacheRecord record) {
184         // default cache does not track record usage
185     }
186 }