View Javadoc
1   package org.eclipse.aether.util.graph.manager;
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.Collection;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.LinkedHashSet;
26  import java.util.Map;
27  import java.util.Objects;
28  
29  import org.eclipse.aether.artifact.Artifact;
30  import org.eclipse.aether.artifact.ArtifactProperties;
31  import org.eclipse.aether.collection.DependencyCollectionContext;
32  import org.eclipse.aether.collection.DependencyManagement;
33  import org.eclipse.aether.collection.DependencyManager;
34  import org.eclipse.aether.graph.Dependency;
35  import org.eclipse.aether.graph.Exclusion;
36  import org.eclipse.aether.util.artifact.JavaScopes;
37  
38  /**
39   * A dependency manager managing dependencies on all levels supporting transitive dependency management.
40   * <p>
41   * <b>Note:</b>Unlike the {@code ClassicDependencyManager} and the {@code TransitiveDependencyManager} this
42   * implementation applies management also on the first level. This is considered the resolver's default behaviour.
43   * It ignores all management overrides supported by the {@code MavenModelBuilder}.
44   * </p>
45   *
46   * @author Christian Schulte
47   * @since 1.4.0
48   */
49  public final class DefaultDependencyManager
50      implements DependencyManager
51  {
52  
53      private final Map<Object, String> managedVersions;
54  
55      private final Map<Object, String> managedScopes;
56  
57      private final Map<Object, Boolean> managedOptionals;
58  
59      private final Map<Object, String> managedLocalPaths;
60  
61      private final Map<Object, Collection<Exclusion>> managedExclusions;
62  
63      private int hashCode;
64  
65      /**
66       * Creates a new dependency manager without any management information.
67       */
68      public DefaultDependencyManager()
69      {
70          this( Collections.<Object, String>emptyMap(), Collections.<Object, String>emptyMap(),
71                Collections.<Object, Boolean>emptyMap(), Collections.<Object, String>emptyMap(),
72                Collections.<Object, Collection<Exclusion>>emptyMap() );
73      }
74  
75      private DefaultDependencyManager( final Map<Object, String> managedVersions,
76                                        final Map<Object, String> managedScopes,
77                                        final Map<Object, Boolean> managedOptionals,
78                                        final Map<Object, String> managedLocalPaths,
79                                        final Map<Object, Collection<Exclusion>> managedExclusions )
80      {
81          super();
82          this.managedVersions = managedVersions;
83          this.managedScopes = managedScopes;
84          this.managedOptionals = managedOptionals;
85          this.managedLocalPaths = managedLocalPaths;
86          this.managedExclusions = managedExclusions;
87      }
88  
89      public DependencyManager deriveChildManager( final DependencyCollectionContext context )
90      {
91          Map<Object, String> versions = this.managedVersions;
92          Map<Object, String> scopes = this.managedScopes;
93          Map<Object, Boolean> optionals = this.managedOptionals;
94          Map<Object, String> localPaths = this.managedLocalPaths;
95          Map<Object, Collection<Exclusion>> exclusions = this.managedExclusions;
96  
97          for ( Dependency managedDependency : context.getManagedDependencies() )
98          {
99              Artifact artifact = managedDependency.getArtifact();
100             Object key = getKey( artifact );
101 
102             String version = artifact.getVersion();
103             if ( version.length() > 0 && !versions.containsKey( key ) )
104             {
105                 if ( versions == this.managedVersions )
106                 {
107                     versions = new HashMap<>( this.managedVersions );
108                 }
109                 versions.put( key, version );
110             }
111 
112             String scope = managedDependency.getScope();
113             if ( scope.length() > 0 && !scopes.containsKey( key ) )
114             {
115                 if ( scopes == this.managedScopes )
116                 {
117                     scopes = new HashMap<>( this.managedScopes );
118                 }
119                 scopes.put( key, scope );
120             }
121 
122             Boolean optional = managedDependency.getOptional();
123             if ( optional != null && !optionals.containsKey( key ) )
124             {
125                 if ( optionals == this.managedOptionals )
126                 {
127                     optionals = new HashMap<>( this.managedOptionals );
128                 }
129                 optionals.put( key, optional );
130             }
131 
132             String localPath = managedDependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null );
133             if ( localPath != null && !localPaths.containsKey( key ) )
134             {
135                 if ( localPaths == this.managedLocalPaths )
136                 {
137                     localPaths = new HashMap<>( this.managedLocalPaths );
138                 }
139                 localPaths.put( key, localPath );
140             }
141 
142             if ( !managedDependency.getExclusions().isEmpty() )
143             {
144                 if ( exclusions == this.managedExclusions )
145                 {
146                     exclusions = new HashMap<>( this.managedExclusions );
147                 }
148                 Collection<Exclusion> managed = exclusions.get( key );
149                 if ( managed == null )
150                 {
151                     managed = new LinkedHashSet<>();
152                     exclusions.put( key, managed );
153                 }
154                 managed.addAll( managedDependency.getExclusions() );
155             }
156         }
157 
158         return new DefaultDependencyManager( versions, scopes, optionals, localPaths, exclusions );
159     }
160 
161     public DependencyManagement manageDependency( Dependency dependency )
162     {
163         DependencyManagement management = null;
164 
165         Object key = getKey( dependency.getArtifact() );
166 
167         String version = managedVersions.get( key );
168         if ( version != null )
169         {
170             if ( management == null )
171             {
172                 management = new DependencyManagement();
173             }
174             management.setVersion( version );
175         }
176 
177         String scope = managedScopes.get( key );
178         if ( scope != null )
179         {
180             if ( management == null )
181             {
182                 management = new DependencyManagement();
183             }
184             management.setScope( scope );
185 
186             if ( !JavaScopes.SYSTEM.equals( scope )
187                      && dependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) != null )
188             {
189                 Map<String, String> properties =
190                     new HashMap<>( dependency.getArtifact().getProperties() );
191 
192                 properties.remove( ArtifactProperties.LOCAL_PATH );
193                 management.setProperties( properties );
194             }
195         }
196 
197         if ( ( scope != null && JavaScopes.SYSTEM.equals( scope ) )
198                  || ( scope == null && JavaScopes.SYSTEM.equals( dependency.getScope() ) ) )
199         {
200             String localPath = managedLocalPaths.get( key );
201             if ( localPath != null )
202             {
203                 if ( management == null )
204                 {
205                     management = new DependencyManagement();
206                 }
207 
208                 Map<String, String> properties =
209                     new HashMap<>( dependency.getArtifact().getProperties() );
210 
211                 properties.put( ArtifactProperties.LOCAL_PATH, localPath );
212                 management.setProperties( properties );
213             }
214         }
215 
216         Boolean optional = managedOptionals.get( key );
217         if ( optional != null )
218         {
219             if ( management == null )
220             {
221                 management = new DependencyManagement();
222             }
223             management.setOptional( optional );
224         }
225 
226         Collection<Exclusion> exclusions = managedExclusions.get( key );
227         if ( exclusions != null )
228         {
229             if ( management == null )
230             {
231                 management = new DependencyManagement();
232             }
233             Collection<Exclusion> result = new LinkedHashSet<>( dependency.getExclusions() );
234             result.addAll( exclusions );
235             management.setExclusions( result );
236         }
237 
238         return management;
239     }
240 
241     private Object getKey( Artifact a )
242     {
243         return new Key( a );
244     }
245 
246     @Override
247     public boolean equals( final Object obj )
248     {
249         boolean equal = obj instanceof DefaultDependencyManager;
250 
251         if ( equal )
252         {
253             final DefaultDependencyManager that = (DefaultDependencyManager) obj;
254             equal = Objects.equals( managedVersions, that.managedVersions )
255                         && Objects.equals( managedScopes, that.managedScopes )
256                         && Objects.equals( managedOptionals, that.managedOptionals )
257                         && Objects.equals( managedExclusions, that.managedExclusions );
258 
259         }
260 
261         return equal;
262     }
263 
264     @Override
265     public int hashCode()
266     {
267         if ( hashCode == 0 )
268         {
269             hashCode = Objects.hash( managedVersions, managedScopes, managedOptionals, managedExclusions );
270         }
271         return hashCode;
272     }
273 
274     static class Key
275     {
276 
277         private final Artifact artifact;
278 
279         private final int hashCode;
280 
281         Key( final Artifact artifact )
282         {
283             this.artifact = artifact;
284             this.hashCode = Objects.hash( artifact.getGroupId(), artifact.getArtifactId() );
285         }
286 
287         @Override
288         public boolean equals( final Object obj )
289         {
290             boolean equal = obj instanceof Key;
291 
292             if ( equal )
293             {
294                 final Key that = (Key) obj;
295                 return Objects.equals( artifact.getArtifactId(), that.artifact.getArtifactId() )
296                            && Objects.equals( artifact.getGroupId(), that.artifact.getGroupId() )
297                            && Objects.equals( artifact.getExtension(), that.artifact.getExtension() )
298                            && Objects.equals( artifact.getClassifier(), that.artifact.getClassifier() );
299 
300             }
301 
302             return equal;
303         }
304 
305         @Override
306         public int hashCode()
307         {
308             return this.hashCode;
309         }
310 
311     }
312 
313 }