001package org.eclipse.aether.util.graph.manager; 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.util.Collection; 023import java.util.Collections; 024import java.util.HashMap; 025import java.util.LinkedHashSet; 026import java.util.Map; 027 028import org.eclipse.aether.artifact.Artifact; 029import org.eclipse.aether.artifact.ArtifactProperties; 030import org.eclipse.aether.collection.DependencyCollectionContext; 031import org.eclipse.aether.collection.DependencyManagement; 032import org.eclipse.aether.collection.DependencyManager; 033import org.eclipse.aether.graph.Dependency; 034import org.eclipse.aether.graph.Exclusion; 035import org.eclipse.aether.util.artifact.JavaScopes; 036 037/** 038 * A dependency manager that mimics the way Maven 2.x works. 039 */ 040public final class ClassicDependencyManager 041 implements DependencyManager 042{ 043 044 private final int depth; 045 046 private final Map<Object, String> managedVersions; 047 048 private final Map<Object, String> managedScopes; 049 050 private final Map<Object, Boolean> managedOptionals; 051 052 private final Map<Object, String> managedLocalPaths; 053 054 private final Map<Object, Collection<Exclusion>> managedExclusions; 055 056 private int hashCode; 057 058 /** 059 * Creates a new dependency manager without any management information. 060 */ 061 public ClassicDependencyManager() 062 { 063 this( 0, Collections.<Object, String>emptyMap(), Collections.<Object, String>emptyMap(), 064 Collections.<Object, Boolean>emptyMap(), Collections.<Object, String>emptyMap(), 065 Collections.<Object, Collection<Exclusion>>emptyMap() ); 066 } 067 068 private ClassicDependencyManager( int depth, Map<Object, String> managedVersions, 069 Map<Object, String> managedScopes, Map<Object, Boolean> managedOptionals, 070 Map<Object, String> managedLocalPaths, 071 Map<Object, Collection<Exclusion>> managedExclusions ) 072 { 073 this.depth = depth; 074 this.managedVersions = managedVersions; 075 this.managedScopes = managedScopes; 076 this.managedOptionals = managedOptionals; 077 this.managedLocalPaths = managedLocalPaths; 078 this.managedExclusions = managedExclusions; 079 } 080 081 public DependencyManager deriveChildManager( DependencyCollectionContext context ) 082 { 083 if ( depth >= 2 ) 084 { 085 return this; 086 } 087 else if ( depth == 1 ) 088 { 089 return new ClassicDependencyManager( depth + 1, managedVersions, managedScopes, managedOptionals, 090 managedLocalPaths, managedExclusions ); 091 } 092 093 Map<Object, String> managedVersions = this.managedVersions; 094 Map<Object, String> managedScopes = this.managedScopes; 095 Map<Object, Boolean> managedOptionals = this.managedOptionals; 096 Map<Object, String> managedLocalPaths = this.managedLocalPaths; 097 Map<Object, Collection<Exclusion>> managedExclusions = this.managedExclusions; 098 099 for ( Dependency managedDependency : context.getManagedDependencies() ) 100 { 101 Artifact artifact = managedDependency.getArtifact(); 102 Object key = getKey( artifact ); 103 104 String version = artifact.getVersion(); 105 if ( version.length() > 0 && !managedVersions.containsKey( key ) ) 106 { 107 if ( managedVersions == this.managedVersions ) 108 { 109 managedVersions = new HashMap<Object, String>( this.managedVersions ); 110 } 111 managedVersions.put( key, version ); 112 } 113 114 String scope = managedDependency.getScope(); 115 if ( scope.length() > 0 && !managedScopes.containsKey( key ) ) 116 { 117 if ( managedScopes == this.managedScopes ) 118 { 119 managedScopes = new HashMap<Object, String>( this.managedScopes ); 120 } 121 managedScopes.put( key, scope ); 122 } 123 124 Boolean optional = managedDependency.getOptional(); 125 if ( optional != null && !managedOptionals.containsKey( key ) ) 126 { 127 if ( managedOptionals == this.managedOptionals ) 128 { 129 managedOptionals = new HashMap<Object, Boolean>( this.managedOptionals ); 130 } 131 managedOptionals.put( key, optional ); 132 } 133 134 String localPath = managedDependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ); 135 if ( localPath != null && !managedLocalPaths.containsKey( key ) ) 136 { 137 if ( managedLocalPaths == this.managedLocalPaths ) 138 { 139 managedLocalPaths = new HashMap<Object, String>( this.managedLocalPaths ); 140 } 141 managedLocalPaths.put( key, localPath ); 142 } 143 144 Collection<Exclusion> exclusions = managedDependency.getExclusions(); 145 if ( !exclusions.isEmpty() ) 146 { 147 if ( managedExclusions == this.managedExclusions ) 148 { 149 managedExclusions = new HashMap<Object, Collection<Exclusion>>( this.managedExclusions ); 150 } 151 Collection<Exclusion> managed = managedExclusions.get( key ); 152 if ( managed == null ) 153 { 154 managed = new LinkedHashSet<Exclusion>(); 155 managedExclusions.put( key, managed ); 156 } 157 managed.addAll( exclusions ); 158 } 159 } 160 161 return new ClassicDependencyManager( depth + 1, managedVersions, managedScopes, managedOptionals, 162 managedLocalPaths, managedExclusions ); 163 } 164 165 public DependencyManagement manageDependency( Dependency dependency ) 166 { 167 DependencyManagement management = null; 168 169 Object key = getKey( dependency.getArtifact() ); 170 171 if ( depth >= 2 ) 172 { 173 String version = managedVersions.get( key ); 174 if ( version != null ) 175 { 176 if ( management == null ) 177 { 178 management = new DependencyManagement(); 179 } 180 management.setVersion( version ); 181 } 182 183 String scope = managedScopes.get( key ); 184 if ( scope != null ) 185 { 186 if ( management == null ) 187 { 188 management = new DependencyManagement(); 189 } 190 management.setScope( scope ); 191 192 if ( !JavaScopes.SYSTEM.equals( scope ) 193 && dependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) != null ) 194 { 195 Map<String, String> properties = 196 new HashMap<String, String>( dependency.getArtifact().getProperties() ); 197 properties.remove( ArtifactProperties.LOCAL_PATH ); 198 management.setProperties( properties ); 199 } 200 } 201 202 if ( ( scope != null && JavaScopes.SYSTEM.equals( scope ) ) 203 || ( scope == null && JavaScopes.SYSTEM.equals( dependency.getScope() ) ) ) 204 { 205 String localPath = managedLocalPaths.get( key ); 206 if ( localPath != null ) 207 { 208 if ( management == null ) 209 { 210 management = new DependencyManagement(); 211 } 212 Map<String, String> properties = 213 new HashMap<String, String>( dependency.getArtifact().getProperties() ); 214 properties.put( ArtifactProperties.LOCAL_PATH, localPath ); 215 management.setProperties( properties ); 216 } 217 } 218 219 Boolean optional = managedOptionals.get( key ); 220 if ( optional != null ) 221 { 222 if ( management == null ) 223 { 224 management = new DependencyManagement(); 225 } 226 management.setOptional( optional ); 227 } 228 } 229 230 Collection<Exclusion> exclusions = managedExclusions.get( key ); 231 if ( exclusions != null ) 232 { 233 if ( management == null ) 234 { 235 management = new DependencyManagement(); 236 } 237 Collection<Exclusion> result = new LinkedHashSet<Exclusion>( dependency.getExclusions() ); 238 result.addAll( exclusions ); 239 management.setExclusions( result ); 240 } 241 242 return management; 243 } 244 245 private Object getKey( Artifact a ) 246 { 247 return new Key( a ); 248 } 249 250 @Override 251 public boolean equals( Object obj ) 252 { 253 if ( this == obj ) 254 { 255 return true; 256 } 257 else if ( null == obj || !getClass().equals( obj.getClass() ) ) 258 { 259 return false; 260 } 261 262 ClassicDependencyManager that = (ClassicDependencyManager) obj; 263 return depth == that.depth && managedVersions.equals( that.managedVersions ) 264 && managedScopes.equals( that.managedScopes ) && managedOptionals.equals( that.managedOptionals ) 265 && managedExclusions.equals( that.managedExclusions ); 266 } 267 268 @Override 269 public int hashCode() 270 { 271 if ( hashCode == 0 ) 272 { 273 int hash = 17; 274 hash = hash * 31 + depth; 275 hash = hash * 31 + managedVersions.hashCode(); 276 hash = hash * 31 + managedScopes.hashCode(); 277 hash = hash * 31 + managedOptionals.hashCode(); 278 hash = hash * 31 + managedExclusions.hashCode(); 279 hashCode = hash; 280 } 281 return hashCode; 282 } 283 284 static class Key 285 { 286 287 private final Artifact artifact; 288 289 private final int hashCode; 290 291 Key( Artifact artifact ) 292 { 293 this.artifact = artifact; 294 295 int hash = 17; 296 hash = hash * 31 + artifact.getGroupId().hashCode(); 297 hash = hash * 31 + artifact.getArtifactId().hashCode(); 298 hashCode = hash; 299 } 300 301 @Override 302 public boolean equals( Object obj ) 303 { 304 if ( obj == this ) 305 { 306 return true; 307 } 308 else if ( !( obj instanceof Key ) ) 309 { 310 return false; 311 } 312 Key that = (Key) obj; 313 return artifact.getArtifactId().equals( that.artifact.getArtifactId() ) 314 && artifact.getGroupId().equals( that.artifact.getGroupId() ) 315 && artifact.getExtension().equals( that.artifact.getExtension() ) 316 && artifact.getClassifier().equals( that.artifact.getClassifier() ); 317 } 318 319 @Override 320 public int hashCode() 321 { 322 return hashCode; 323 } 324 325 } 326 327}