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.internal.impl.scope;
20  
21  import org.eclipse.aether.impl.scope.InternalScopeManager;
22  import org.eclipse.aether.scope.DependencyScope;
23  import org.eclipse.aether.scope.ScopeManager;
24  import org.eclipse.aether.util.graph.transformer.ConflictResolver;
25  import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeContext;
26  import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeDeriver;
27  
28  import static java.util.Objects.requireNonNull;
29  
30  /**
31   * A scope deriver for use with {@link ConflictResolver} that supports the scopes from {@link ScopeManager}. It basically
32   * chooses "narrowest" scope, based on parent and child scopes.
33   * <p>
34   * This class also "bridges" between {@link DependencyScope} and Resolver that uses plain string labels for scopes.
35   *
36   * @since 4.0.0
37   */
38  public final class ManagedScopeDeriver extends ScopeDeriver {
39      private final InternalScopeManager scopeManager;
40      private final DependencyScope systemScope;
41  
42      public ManagedScopeDeriver(InternalScopeManager scopeManager) {
43          this.scopeManager = requireNonNull(scopeManager, "scopeManager");
44          this.systemScope = scopeManager.getSystemDependencyScope().orElse(null);
45      }
46  
47      @Override
48      public void deriveScope(ScopeContext context) {
49          context.setDerivedScope(getDerivedScope(context.getParentScope(), context.getChildScope()));
50      }
51  
52      /**
53       * Visible for testing. It chooses "narrowest" scope out of parent or child, unless child is system scope.
54       */
55      public String getDerivedScope(String parentScope, String childScope) {
56          // ask parent scope (nullable)
57          DependencyScope parent = parentScope != null
58                  ? scopeManager.getDependencyScope(parentScope).orElse(null)
59                  : null;
60          // ask child scope (non-nullable, but may be unknown scope to manager)
61          DependencyScope child = scopeManager.getDependencyScope(childScope).orElse(null);
62  
63          // if system scope exists and child is system scope: system
64          if (systemScope != null && systemScope == child) {
65              return systemScope.getId();
66          }
67          // if no parent (i.e. is root): child scope as-is
68          if (parent == null) {
69              return child != null ? child.getId() : "";
70          }
71          if (child == null) {
72              return parent.getId();
73          }
74          // otherwise the narrowest out of parent or child
75          int parentWidth = scopeManager.getDependencyScopeWidth(parent);
76          int childWidth = scopeManager.getDependencyScopeWidth(child);
77          if (parentWidth < childWidth) {
78              return parent.getId();
79          } else {
80              return child.getId();
81          }
82      }
83  }