001package org.eclipse.aether.internal.impl.collect;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 * 
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 * 
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.lang.ref.WeakReference;
023import java.util.Collection;
024import java.util.Collections;
025import java.util.HashMap;
026import java.util.Iterator;
027import java.util.List;
028import java.util.Map;
029import java.util.Objects;
030import java.util.WeakHashMap;
031
032import org.eclipse.aether.RepositoryCache;
033import org.eclipse.aether.RepositorySystemSession;
034import org.eclipse.aether.artifact.Artifact;
035import org.eclipse.aether.collection.DependencyManager;
036import org.eclipse.aether.collection.DependencySelector;
037import org.eclipse.aether.collection.DependencyTraverser;
038import org.eclipse.aether.collection.VersionFilter;
039import org.eclipse.aether.graph.Dependency;
040import org.eclipse.aether.graph.DependencyNode;
041import org.eclipse.aether.repository.ArtifactRepository;
042import org.eclipse.aether.repository.RemoteRepository;
043import org.eclipse.aether.resolution.ArtifactDescriptorException;
044import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
045import org.eclipse.aether.resolution.ArtifactDescriptorResult;
046import org.eclipse.aether.resolution.VersionRangeRequest;
047import org.eclipse.aether.resolution.VersionRangeResult;
048import org.eclipse.aether.version.Version;
049import org.eclipse.aether.version.VersionConstraint;
050
051/**
052 * Internal helper class for collector implementations.
053 */
054public final class DataPool
055{
056
057    private static final String ARTIFACT_POOL = DataPool.class.getName() + "$Artifact";
058
059    private static final String DEPENDENCY_POOL = DataPool.class.getName() + "$Dependency";
060
061    private static final String DESCRIPTORS = DataPool.class.getName() + "$Descriptors";
062
063    public static final ArtifactDescriptorResult NO_DESCRIPTOR =
064        new ArtifactDescriptorResult( new ArtifactDescriptorRequest() );
065
066    private ObjectPool<Artifact> artifacts;
067
068    private ObjectPool<Dependency> dependencies;
069
070    private Map<Object, WeakReference<Descriptor>> descriptors;
071
072    private final Map<Object, Constraint> constraints = new HashMap<>();
073
074    private final Map<Object, List<DependencyNode>> nodes = new HashMap<>( 256 );
075
076    @SuppressWarnings( "unchecked" )
077    public DataPool( RepositorySystemSession session )
078    {
079        RepositoryCache cache = session.getCache();
080
081        if ( cache != null )
082        {
083            artifacts = (ObjectPool<Artifact>) cache.get( session, ARTIFACT_POOL );
084            dependencies = (ObjectPool<Dependency>) cache.get( session, DEPENDENCY_POOL );
085            descriptors = (Map<Object, WeakReference<Descriptor>>) cache.get( session, DESCRIPTORS );
086        }
087
088        if ( artifacts == null )
089        {
090            artifacts = new ObjectPool<>();
091            if ( cache != null )
092            {
093                cache.put( session, ARTIFACT_POOL, artifacts );
094            }
095        }
096
097        if ( dependencies == null )
098        {
099            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}