View Javadoc
1   package org.apache.maven.plugin;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.HashSet;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  import java.util.concurrent.ConcurrentHashMap;
30  
31  import org.apache.commons.lang3.Validate;
32  import org.apache.maven.artifact.Artifact;
33  import org.apache.maven.lifecycle.LifecycleExecutionException;
34  import org.apache.maven.model.Plugin;
35  import org.apache.maven.project.MavenProject;
36  import org.codehaus.plexus.component.annotations.Component;
37  import org.eclipse.aether.RepositorySystemSession;
38  import org.eclipse.aether.repository.LocalRepository;
39  import org.eclipse.aether.repository.RemoteRepository;
40  import org.eclipse.aether.repository.WorkspaceRepository;
41  
42  /**
43   * @author Igor Fedorenko
44   * @author Benjamin Bentmann
45   * @author Anton Tanasenko
46   */
47  @Component( role = ProjectArtifactsCache.class )
48  public class DefaultProjectArtifactsCache
49      implements ProjectArtifactsCache
50  {
51  
52      protected static class CacheKey
53          implements Key
54      {
55  
56          private final String groupId;
57          
58          private final String artifactId;
59          
60          private final String version;
61          
62          private final Set<String> dependencyArtifacts;
63  
64          private final WorkspaceRepository workspace;
65  
66          private final LocalRepository localRepo;
67  
68          private final List<RemoteRepository> repositories;
69          
70          private final Set<String> collect;
71          
72          private final Set<String> resolve;
73          
74          private boolean aggregating;
75  
76          private final int hashCode;
77  
78          public CacheKey( MavenProject project, List<RemoteRepository> repositories,
79              Collection<String> scopesToCollect, Collection<String> scopesToResolve, boolean aggregating,
80              RepositorySystemSession session )
81          {
82              
83              groupId = project.getGroupId();
84              artifactId = project.getArtifactId();
85              version = project.getVersion();
86              
87              Set<String> deps = new HashSet<>();
88              if ( project.getDependencyArtifacts() != null )
89              {
90                for ( Artifact dep: project.getDependencyArtifacts() )
91                {
92                  deps.add( dep.toString() );
93                }
94              }
95              dependencyArtifacts = Collections.unmodifiableSet( deps );
96              
97              workspace = CacheUtils.getWorkspace( session );
98              this.localRepo = session.getLocalRepository();
99              this.repositories = new ArrayList<>( repositories.size() );
100             for ( RemoteRepository repository : repositories )
101             {
102                 if ( repository.isRepositoryManager() )
103                 {
104                     this.repositories.addAll( repository.getMirroredRepositories() );
105                 }
106                 else
107                 {
108                     this.repositories.add( repository );
109                 }
110             }
111             collect = scopesToCollect == null
112                 ? Collections.<String>emptySet() 
113                 : Collections.unmodifiableSet( new HashSet<>( scopesToCollect ) );
114             resolve = scopesToResolve == null 
115                 ? Collections.<String>emptySet() 
116                 : Collections.unmodifiableSet( new HashSet<>( scopesToResolve ) );
117             this.aggregating = aggregating;
118 
119             int hash = 17;
120             hash = hash * 31 + hash( groupId );
121             hash = hash * 31 + hash( artifactId );
122             hash = hash * 31 + hash( version );
123             hash = hash * 31 + hash( dependencyArtifacts );
124             hash = hash * 31 + hash( workspace );
125             hash = hash * 31 + hash( localRepo );
126             hash = hash * 31 + CacheUtils.repositoriesHashCode( repositories );
127             hash = hash * 31 + hash( collect );
128             hash = hash * 31 + hash( resolve );
129             hash = hash * 31 + hash( aggregating );
130             this.hashCode = hash;
131         }
132 
133         @Override
134         public String toString()
135         {
136             return groupId + ":" + artifactId + ":" + version;
137         }
138 
139         @Override
140         public int hashCode()
141         {
142             return hashCode;
143         }
144 
145         private static int hash( Object obj )
146         {
147             return obj != null ? obj.hashCode() : 0;
148         }
149 
150         @Override
151         public boolean equals( Object o )
152         {
153             if ( o == this )
154             {
155                 return true;
156             }
157 
158             if ( !( o instanceof CacheKey ) )
159             {
160                 return false;
161             }
162 
163             CacheKey that = (CacheKey) o;
164 
165             return eq( groupId, that.groupId ) && eq( artifactId, that.artifactId ) && eq( version, that.version ) 
166                 && eq( dependencyArtifacts, that.dependencyArtifacts )
167                 && eq( workspace, that.workspace ) && eq( localRepo, that.localRepo ) 
168                 && CacheUtils.repositoriesEquals( repositories, that.repositories ) && eq( collect, that.collect ) 
169                 && eq( resolve, that.resolve ) && aggregating == that.aggregating;
170         }
171 
172         private static <T> boolean eq( T s1, T s2 )
173         {
174             return s1 != null ? s1.equals( s2 ) : s2 == null;
175         }
176 
177     }
178 
179     protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<>();
180 
181     public Key createKey( MavenProject project, Collection<String> scopesToCollect,
182         Collection<String> scopesToResolve, boolean aggregating, RepositorySystemSession session )
183     {
184         return new CacheKey( project, project.getRemoteProjectRepositories(), scopesToCollect, scopesToResolve, 
185             aggregating, session );
186     }
187 
188     public CacheRecord get( Key key )
189         throws LifecycleExecutionException
190     {
191         CacheRecord cacheRecord = cache.get( key );
192 
193         if ( cacheRecord != null && cacheRecord.exception != null )
194         {
195             throw cacheRecord.exception;
196         }
197 
198         return cacheRecord;
199     }
200 
201     public CacheRecord put( Key key, Set<Artifact> projectArtifacts )
202     {
203         Validate.notNull( projectArtifacts, "projectArtifacts cannot be null" );
204 
205         assertUniqueKey( key );
206 
207         CacheRecord record =
208             new CacheRecord( Collections.unmodifiableSet( new HashSet<>( projectArtifacts ) ) );
209 
210         cache.put( key, record );
211 
212         return record;
213     }
214 
215     protected void assertUniqueKey( Key key )
216     {
217         if ( cache.containsKey( key ) )
218         {
219             throw new IllegalStateException( "Duplicate artifact resolution result for project " + key );
220         }
221     }
222 
223     public CacheRecord put( Key key, LifecycleExecutionException exception )
224     {
225         Validate.notNull( exception, "exception cannot be null" );
226 
227         assertUniqueKey( key );
228 
229         CacheRecord record = new CacheRecord( exception );
230 
231         cache.put( key, record );
232 
233         return record;
234     }
235 
236     public void flush()
237     {
238         cache.clear();
239     }
240 
241     protected static int pluginHashCode( Plugin plugin )
242     {
243         return CacheUtils.pluginHashCode( plugin );
244     }
245 
246     protected static boolean pluginEquals( Plugin a, Plugin b )
247     {
248         return CacheUtils.pluginEquals( a, b );
249     }
250 
251     public void register( MavenProject project, Key cacheKey, CacheRecord record )
252     {
253         // default cache does not track record usage
254     }
255 
256 }