View Javadoc
1   package org.eclipse.aether.internal.impl.collect;
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.lang.ref.WeakReference;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Objects;
30  import java.util.WeakHashMap;
31  
32  import org.eclipse.aether.RepositoryCache;
33  import org.eclipse.aether.RepositorySystemSession;
34  import org.eclipse.aether.artifact.Artifact;
35  import org.eclipse.aether.collection.DependencyManager;
36  import org.eclipse.aether.collection.DependencySelector;
37  import org.eclipse.aether.collection.DependencyTraverser;
38  import org.eclipse.aether.collection.VersionFilter;
39  import org.eclipse.aether.graph.Dependency;
40  import org.eclipse.aether.graph.DependencyNode;
41  import org.eclipse.aether.repository.ArtifactRepository;
42  import org.eclipse.aether.repository.RemoteRepository;
43  import org.eclipse.aether.resolution.ArtifactDescriptorException;
44  import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
45  import org.eclipse.aether.resolution.ArtifactDescriptorResult;
46  import org.eclipse.aether.resolution.VersionRangeRequest;
47  import org.eclipse.aether.resolution.VersionRangeResult;
48  import org.eclipse.aether.version.Version;
49  import org.eclipse.aether.version.VersionConstraint;
50  
51  /**
52   * Internal helper class for collector implementations.
53   */
54  public final class DataPool
55  {
56  
57      private static final String ARTIFACT_POOL = DataPool.class.getName() + "$Artifact";
58  
59      private static final String DEPENDENCY_POOL = DataPool.class.getName() + "$Dependency";
60  
61      private static final String DESCRIPTORS = DataPool.class.getName() + "$Descriptors";
62  
63      public static final ArtifactDescriptorResult NO_DESCRIPTOR =
64          new ArtifactDescriptorResult( new ArtifactDescriptorRequest() );
65  
66      private ObjectPool<Artifact> artifacts;
67  
68      private ObjectPool<Dependency> dependencies;
69  
70      private Map<Object, WeakReference<Descriptor>> descriptors;
71  
72      private final Map<Object, Constraint> constraints = new HashMap<>();
73  
74      private final Map<Object, List<DependencyNode>> nodes = new HashMap<>( 256 );
75  
76      @SuppressWarnings( "unchecked" )
77      public DataPool( RepositorySystemSession session )
78      {
79          RepositoryCache cache = session.getCache();
80  
81          if ( cache != null )
82          {
83              artifacts = (ObjectPool<Artifact>) cache.get( session, ARTIFACT_POOL );
84              dependencies = (ObjectPool<Dependency>) cache.get( session, DEPENDENCY_POOL );
85              descriptors = (Map<Object, WeakReference<Descriptor>>) cache.get( session, DESCRIPTORS );
86          }
87  
88          if ( artifacts == null )
89          {
90              artifacts = new ObjectPool<>();
91              if ( cache != null )
92              {
93                  cache.put( session, ARTIFACT_POOL, artifacts );
94              }
95          }
96  
97          if ( dependencies == null )
98          {
99              dependencies = new ObjectPool<>();
100             if ( cache != null )
101             {
102                 cache.put( session, DEPENDENCY_POOL, dependencies );
103             }
104         }
105 
106         if ( descriptors == null )
107         {
108             descriptors = Collections.synchronizedMap( new WeakHashMap<>( 256 ) );
109             if ( cache != null )
110             {
111                 cache.put( session, DESCRIPTORS, descriptors );
112             }
113         }
114     }
115 
116     public Artifact intern( Artifact artifact )
117     {
118         return artifacts.intern( artifact );
119     }
120 
121     public Dependency intern( Dependency dependency )
122     {
123         return dependencies.intern( dependency );
124     }
125 
126     public Object toKey( ArtifactDescriptorRequest request )
127     {
128         return request.getArtifact();
129     }
130 
131     public ArtifactDescriptorResult getDescriptor( Object key, ArtifactDescriptorRequest request )
132     {
133         WeakReference<Descriptor> descriptorRef = descriptors.get( key );
134         Descriptor descriptor = descriptorRef != null ? descriptorRef.get() : null;
135         if ( descriptor != null )
136         {
137             return descriptor.toResult( request );
138         }
139         return null;
140     }
141 
142     public void putDescriptor( Object key, ArtifactDescriptorResult result )
143     {
144         descriptors.put( key, new WeakReference<>( new GoodDescriptor( result ) ) );
145     }
146 
147     public void putDescriptor( Object key, ArtifactDescriptorException e )
148     {
149         descriptors.put( key, new WeakReference<>( BadDescriptor.INSTANCE ) );
150     }
151 
152     public Object toKey( VersionRangeRequest request )
153     {
154         return new ConstraintKey( request );
155     }
156 
157     public VersionRangeResult getConstraint( Object key, VersionRangeRequest request )
158     {
159         Constraint constraint = constraints.get( key );
160         if ( constraint != null )
161         {
162             return constraint.toResult( request );
163         }
164         return null;
165     }
166 
167     public void putConstraint( Object key, VersionRangeResult result )
168     {
169         constraints.put( key, new Constraint( result ) );
170     }
171 
172     public Object toKey( Artifact artifact, List<RemoteRepository> repositories, DependencySelector selector,
173                          DependencyManager manager, DependencyTraverser traverser, VersionFilter filter )
174     {
175         return new GraphKey( artifact, repositories, selector, manager, traverser, filter );
176     }
177 
178     public List<DependencyNode> getChildren( Object key )
179     {
180         return nodes.get( key );
181     }
182 
183     public void putChildren( Object key, List<DependencyNode> children )
184     {
185         nodes.put( key, children );
186     }
187 
188     abstract static class Descriptor
189     {
190 
191         public abstract ArtifactDescriptorResult toResult( ArtifactDescriptorRequest request );
192 
193     }
194 
195     static final class GoodDescriptor
196         extends Descriptor
197     {
198 
199         final Artifact artifact;
200 
201         final List<Artifact> relocations;
202 
203         final Collection<Artifact> aliases;
204 
205         final List<RemoteRepository> repositories;
206 
207         final List<Dependency> dependencies;
208 
209         final List<Dependency> managedDependencies;
210 
211         GoodDescriptor( ArtifactDescriptorResult result )
212         {
213             artifact = result.getArtifact();
214             relocations = result.getRelocations();
215             aliases = result.getAliases();
216             dependencies = result.getDependencies();
217             managedDependencies = result.getManagedDependencies();
218             repositories = result.getRepositories();
219         }
220 
221         public ArtifactDescriptorResult toResult( ArtifactDescriptorRequest request )
222         {
223             ArtifactDescriptorResult result = new ArtifactDescriptorResult( request );
224             result.setArtifact( artifact );
225             result.setRelocations( relocations );
226             result.setAliases( aliases );
227             result.setDependencies( dependencies );
228             result.setManagedDependencies( managedDependencies );
229             result.setRepositories( repositories );
230             return result;
231         }
232 
233     }
234 
235     static final class BadDescriptor
236         extends Descriptor
237     {
238 
239         static final BadDescriptor INSTANCE = new BadDescriptor();
240 
241         public ArtifactDescriptorResult toResult( ArtifactDescriptorRequest request )
242         {
243             return NO_DESCRIPTOR;
244         }
245     }
246 
247     private static final class Constraint
248     {
249         final VersionRepo[] repositories;
250 
251         final VersionConstraint versionConstraint;
252 
253         Constraint( VersionRangeResult result )
254         {
255             versionConstraint = result.getVersionConstraint();
256             List<Version> versions = result.getVersions();
257             repositories = new VersionRepo[versions.size()];
258             int i = 0;
259             for ( Version version : versions )
260             {
261                 repositories[i++] = new VersionRepo( version, result.getRepository( version ) );
262             }
263         }
264 
265         VersionRangeResult toResult( VersionRangeRequest request )
266         {
267             VersionRangeResult result = new VersionRangeResult( request );
268             for ( VersionRepo vr : repositories )
269             {
270                 result.addVersion( vr.version );
271                 result.setRepository( vr.version, vr.repo );
272             }
273             result.setVersionConstraint( versionConstraint );
274             return result;
275         }
276 
277         static final class VersionRepo
278         {
279             final Version version;
280 
281             final ArtifactRepository repo;
282 
283             VersionRepo( Version version, ArtifactRepository repo )
284             {
285                 this.version = version;
286                 this.repo = repo;
287             }
288         }
289     }
290 
291     static final class ConstraintKey
292     {
293         private final Artifact artifact;
294 
295         private final List<RemoteRepository> repositories;
296 
297         private final int hashCode;
298 
299         ConstraintKey( VersionRangeRequest request )
300         {
301             artifact = request.getArtifact();
302             repositories = request.getRepositories();
303             hashCode = artifact.hashCode();
304         }
305 
306         @Override
307         public boolean equals( Object obj )
308         {
309             if ( obj == this )
310             {
311                 return true;
312             }
313             else if ( !( obj instanceof ConstraintKey ) )
314             {
315                 return false;
316             }
317             ConstraintKey that = (ConstraintKey) obj;
318             return artifact.equals( that.artifact ) && equals( repositories, that.repositories );
319         }
320 
321         private static boolean equals( List<RemoteRepository> repos1, List<RemoteRepository> repos2 )
322         {
323             if ( repos1.size() != repos2.size() )
324             {
325                 return false;
326             }
327             for ( Iterator<RemoteRepository> it1 = repos1.iterator(), it2 = repos2.iterator();
328                   it1.hasNext() && it2.hasNext(); )
329             {
330                 RemoteRepository repo1 = it1.next();
331                 RemoteRepository repo2 = it2.next();
332                 if ( repo1.isRepositoryManager() != repo2.isRepositoryManager() )
333                 {
334                     return false;
335                 }
336                 if ( repo1.isRepositoryManager() )
337                 {
338                     if ( !equals( repo1.getMirroredRepositories(), repo2.getMirroredRepositories() ) )
339                     {
340                         return false;
341                     }
342                 }
343                 else if ( !repo1.getUrl().equals( repo2.getUrl() ) )
344                 {
345                     return false;
346                 }
347                 else if ( repo1.getPolicy( true ).isEnabled() != repo2.getPolicy( true ).isEnabled() )
348                 {
349                     return false;
350                 }
351                 else if ( repo1.getPolicy( false ).isEnabled() != repo2.getPolicy( false ).isEnabled() )
352                 {
353                     return false;
354                 }
355             }
356             return true;
357         }
358 
359         @Override
360         public int hashCode()
361         {
362             return hashCode;
363         }
364     }
365 
366     static final class GraphKey
367     {
368         private final Artifact artifact;
369 
370         private final List<RemoteRepository> repositories;
371 
372         private final DependencySelector selector;
373 
374         private final DependencyManager manager;
375 
376         private final DependencyTraverser traverser;
377 
378         private final VersionFilter filter;
379 
380         private final int hashCode;
381 
382         GraphKey( Artifact artifact, List<RemoteRepository> repositories, DependencySelector selector,
383                   DependencyManager manager, DependencyTraverser traverser, VersionFilter filter )
384         {
385             this.artifact = artifact;
386             this.repositories = repositories;
387             this.selector = selector;
388             this.manager = manager;
389             this.traverser = traverser;
390             this.filter = filter;
391 
392             hashCode = Objects.hash( artifact, repositories, selector, manager, traverser, filter );
393         }
394 
395         @Override
396         public boolean equals( Object obj )
397         {
398             if ( obj == this )
399             {
400                 return true;
401             }
402             else if ( !( obj instanceof GraphKey ) )
403             {
404                 return false;
405             }
406             GraphKey that = (GraphKey) obj;
407             return Objects.equals( artifact, that.artifact ) && Objects.equals( repositories, that.repositories )
408                 && Objects.equals( selector, that.selector ) && Objects.equals( manager, that.manager )
409                 && Objects.equals( traverser, that.traverser ) && Objects.equals( filter, that.filter );
410         }
411 
412         @Override
413         public int hashCode()
414         {
415             return hashCode;
416         }
417     }
418 }