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