View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.util.graph.manager;
20  
21  import java.util.*;
22  
23  import org.eclipse.aether.SystemScopeHandler;
24  import org.eclipse.aether.artifact.Artifact;
25  import org.eclipse.aether.collection.DependencyCollectionContext;
26  import org.eclipse.aether.collection.DependencyManagement;
27  import org.eclipse.aether.collection.DependencyManager;
28  import org.eclipse.aether.graph.Dependency;
29  import org.eclipse.aether.graph.Exclusion;
30  
31  import static java.util.Objects.requireNonNull;
32  
33  /**
34   * A dependency manager support class.
35   *
36   * @since 2.0.0
37   */
38  public abstract class AbstractDependencyManager implements DependencyManager {
39      /**
40       * This predicate is here ONLY to support deprecated constructors.
41       *
42       * @deprecated To be removed when deprecated constructors are removed.
43       */
44      @Deprecated
45      protected static final SystemScopeHandler SYSTEM_SCOPE_HANDLER = SystemScopeHandler.LEGACY;
46  
47      protected final int depth;
48  
49      protected final int deriveUntil;
50  
51      protected final int applyFrom;
52  
53      protected final Map<Object, String> managedVersions;
54  
55      protected final Map<Object, String> managedScopes;
56  
57      protected final Map<Object, Boolean> managedOptionals;
58  
59      protected final Map<Object, String> managedLocalPaths;
60  
61      protected final Map<Object, Collection<Exclusion>> managedExclusions;
62  
63      protected final SystemScopeHandler systemScopeHandler;
64  
65      private final int hashCode;
66  
67      protected AbstractDependencyManager(int deriveUntil, int applyFrom, SystemScopeHandler systemScopeHandler) {
68          this(
69                  0,
70                  deriveUntil,
71                  applyFrom,
72                  Collections.emptyMap(),
73                  Collections.emptyMap(),
74                  Collections.emptyMap(),
75                  Collections.emptyMap(),
76                  Collections.emptyMap(),
77                  systemScopeHandler);
78      }
79  
80      @SuppressWarnings("checkstyle:ParameterNumber")
81      protected AbstractDependencyManager(
82              int depth,
83              int deriveUntil,
84              int applyFrom,
85              Map<Object, String> managedVersions,
86              Map<Object, String> managedScopes,
87              Map<Object, Boolean> managedOptionals,
88              Map<Object, String> managedLocalPaths,
89              Map<Object, Collection<Exclusion>> managedExclusions,
90              SystemScopeHandler systemScopeHandler) {
91          this.depth = depth;
92          this.deriveUntil = deriveUntil;
93          this.applyFrom = applyFrom;
94          this.managedVersions = requireNonNull(managedVersions);
95          this.managedScopes = requireNonNull(managedScopes);
96          this.managedOptionals = requireNonNull(managedOptionals);
97          this.managedLocalPaths = requireNonNull(managedLocalPaths);
98          this.managedExclusions = requireNonNull(managedExclusions);
99          this.systemScopeHandler = requireNonNull(systemScopeHandler);
100 
101         this.hashCode = Objects.hash(
102                 depth,
103                 deriveUntil,
104                 applyFrom,
105                 managedVersions,
106                 managedScopes,
107                 managedOptionals,
108                 managedLocalPaths,
109                 managedExclusions);
110     }
111 
112     protected abstract DependencyManager newInstance(
113             Map<Object, String> managedVersions,
114             Map<Object, String> managedScopes,
115             Map<Object, Boolean> managedOptionals,
116             Map<Object, String> managedLocalPaths,
117             Map<Object, Collection<Exclusion>> managedExclusions);
118 
119     @Override
120     public DependencyManager deriveChildManager(DependencyCollectionContext context) {
121         requireNonNull(context, "context cannot be null");
122         if (depth >= deriveUntil) {
123             return this;
124         }
125 
126         Map<Object, String> managedVersions = this.managedVersions;
127         Map<Object, String> managedScopes = this.managedScopes;
128         Map<Object, Boolean> managedOptionals = this.managedOptionals;
129         Map<Object, String> managedLocalPaths = this.managedLocalPaths;
130         Map<Object, Collection<Exclusion>> managedExclusions = this.managedExclusions;
131 
132         for (Dependency managedDependency : context.getManagedDependencies()) {
133             Artifact artifact = managedDependency.getArtifact();
134             Object key = new Key(artifact);
135 
136             String version = artifact.getVersion();
137             if (!version.isEmpty() && !managedVersions.containsKey(key)) {
138                 if (managedVersions == this.managedVersions) {
139                     managedVersions = new HashMap<>(this.managedVersions);
140                 }
141                 managedVersions.put(key, version);
142             }
143 
144             String scope = managedDependency.getScope();
145             if (!scope.isEmpty() && !managedScopes.containsKey(key)) {
146                 if (managedScopes == this.managedScopes) {
147                     managedScopes = new HashMap<>(this.managedScopes);
148                 }
149                 managedScopes.put(key, scope);
150             }
151 
152             Boolean optional = managedDependency.getOptional();
153             if (optional != null && !managedOptionals.containsKey(key)) {
154                 if (managedOptionals == this.managedOptionals) {
155                     managedOptionals = new HashMap<>(this.managedOptionals);
156                 }
157                 managedOptionals.put(key, optional);
158             }
159 
160             String localPath = systemScopeHandler.getSystemPath(managedDependency.getArtifact());
161             if (localPath != null && !managedLocalPaths.containsKey(key)) {
162                 if (managedLocalPaths == this.managedLocalPaths) {
163                     managedLocalPaths = new HashMap<>(this.managedLocalPaths);
164                 }
165                 managedLocalPaths.put(key, localPath);
166             }
167 
168             Collection<Exclusion> exclusions = managedDependency.getExclusions();
169             if (!exclusions.isEmpty()) {
170                 if (managedExclusions == this.managedExclusions) {
171                     managedExclusions = new HashMap<>(this.managedExclusions);
172                 }
173                 Collection<Exclusion> managed = managedExclusions.computeIfAbsent(key, k -> new LinkedHashSet<>());
174                 managed.addAll(exclusions);
175             }
176         }
177 
178         return newInstance(managedVersions, managedScopes, managedOptionals, managedLocalPaths, managedExclusions);
179     }
180 
181     @Override
182     public DependencyManagement manageDependency(Dependency dependency) {
183         requireNonNull(dependency, "dependency cannot be null");
184         DependencyManagement management = null;
185         Object key = new Key(dependency.getArtifact());
186 
187         if (depth >= applyFrom) {
188             String version = managedVersions.get(key);
189             if (version != null) {
190                 management = new DependencyManagement();
191                 management.setVersion(version);
192             }
193 
194             String scope = managedScopes.get(key);
195             if (scope != null) {
196                 if (management == null) {
197                     management = new DependencyManagement();
198                 }
199                 management.setScope(scope);
200 
201                 if (!systemScopeHandler.isSystemScope(scope)
202                         && systemScopeHandler.getSystemPath(dependency.getArtifact()) != null) {
203                     Map<String, String> properties =
204                             new HashMap<>(dependency.getArtifact().getProperties());
205                     systemScopeHandler.setSystemPath(properties, null);
206                     management.setProperties(properties);
207                 }
208             }
209 
210             if ((systemScopeHandler.isSystemScope(scope))
211                     || (scope == null && systemScopeHandler.isSystemScope(dependency.getScope()))) {
212                 String localPath = managedLocalPaths.get(key);
213                 if (localPath != null) {
214                     if (management == null) {
215                         management = new DependencyManagement();
216                     }
217                     Map<String, String> properties =
218                             new HashMap<>(dependency.getArtifact().getProperties());
219                     systemScopeHandler.setSystemPath(properties, localPath);
220                     management.setProperties(properties);
221                 }
222             }
223 
224             Boolean optional = managedOptionals.get(key);
225             if (optional != null) {
226                 if (management == null) {
227                     management = new DependencyManagement();
228                 }
229                 management.setOptional(optional);
230             }
231         }
232 
233         Collection<Exclusion> exclusions = managedExclusions.get(key);
234         if (exclusions != null) {
235             if (management == null) {
236                 management = new DependencyManagement();
237             }
238             Collection<Exclusion> result = new LinkedHashSet<>(dependency.getExclusions());
239             result.addAll(exclusions);
240             management.setExclusions(result);
241         }
242 
243         return management;
244     }
245 
246     @Override
247     public boolean equals(Object obj) {
248         if (this == obj) {
249             return true;
250         } else if (null == obj || !getClass().equals(obj.getClass())) {
251             return false;
252         }
253 
254         AbstractDependencyManager that = (AbstractDependencyManager) obj;
255         return depth == that.depth
256                 && deriveUntil == that.deriveUntil
257                 && applyFrom == that.applyFrom
258                 && managedVersions.equals(that.managedVersions)
259                 && managedScopes.equals(that.managedScopes)
260                 && managedOptionals.equals(that.managedOptionals)
261                 && managedExclusions.equals(that.managedExclusions);
262     }
263 
264     @Override
265     public int hashCode() {
266         return hashCode;
267     }
268 
269     protected static class Key {
270 
271         private final Artifact artifact;
272 
273         private final int hashCode;
274 
275         Key(Artifact artifact) {
276             this.artifact = artifact;
277             this.hashCode = Objects.hash(artifact.getGroupId(), artifact.getArtifactId());
278         }
279 
280         @Override
281         public boolean equals(Object obj) {
282             if (obj == this) {
283                 return true;
284             } else if (!(obj instanceof Key)) {
285                 return false;
286             }
287             Key that = (Key) obj;
288             return artifact.getArtifactId().equals(that.artifact.getArtifactId())
289                     && artifact.getGroupId().equals(that.artifact.getGroupId())
290                     && artifact.getExtension().equals(that.artifact.getExtension())
291                     && artifact.getClassifier().equals(that.artifact.getClassifier());
292         }
293 
294         @Override
295         public int hashCode() {
296             return hashCode;
297         }
298 
299         @Override
300         public String toString() {
301             return String.valueOf(artifact);
302         }
303     }
304 }