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}