| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.ivy.plugins.conflict; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.apache.ivy.core.module.descriptor.DependencyDescriptor; |
| import org.apache.ivy.core.module.id.ModuleRevisionId; |
| import org.apache.ivy.core.resolve.IvyNode; |
| import org.apache.ivy.plugins.latest.ArtifactInfo; |
| import org.apache.ivy.plugins.latest.LatestStrategy; |
| import org.apache.ivy.util.Message; |
| |
| public class LatestConflictManager extends AbstractConflictManager { |
| @SuppressWarnings("serial") |
| public static class NoConflictResolvedYetException extends RuntimeException { |
| } |
| |
| protected static final class IvyNodeArtifactInfo implements ArtifactInfo { |
| private final IvyNode node; |
| |
| private IvyNodeArtifactInfo(IvyNode dep) { |
| node = dep; |
| } |
| |
| public long getLastModified() { |
| long lastModified = node.getLastModified(); |
| if (lastModified == 0) { |
| // if the last modified timestamp is unknown, we can't resolve |
| // the conflicts now, and trigger an exception which will be caught |
| // in the main resolveConflicts method |
| throw new NoConflictResolvedYetException(); |
| } else { |
| return lastModified; |
| } |
| } |
| |
| public String getRevision() { |
| return node.getResolvedId().getRevision(); |
| } |
| |
| public IvyNode getNode() { |
| return node; |
| } |
| } |
| |
| private LatestStrategy strategy; |
| |
| private String strategyName; |
| |
| public LatestConflictManager() { |
| } |
| |
| public LatestConflictManager(LatestStrategy strategy) { |
| this.strategy = strategy; |
| } |
| |
| public LatestConflictManager(String name, LatestStrategy strategy) { |
| setName(name); |
| this.strategy = strategy; |
| } |
| |
| public Collection<IvyNode> resolveConflicts(IvyNode parent, Collection<IvyNode> conflicts) { |
| if (conflicts.size() < 2) { |
| return conflicts; |
| } |
| for (IvyNode node : conflicts) { |
| DependencyDescriptor dd = node.getDependencyDescriptor(parent); |
| if (dd != null && dd.isForce() |
| && parent.getResolvedId().equals(dd.getParentRevisionId())) { |
| return Collections.singleton(node); |
| } |
| } |
| |
| /* |
| * If the list of conflicts contains dynamic revisions, delay the conflict calculation until |
| * they are resolved. TODO: we probably could already evict some of the dynamic revisions! |
| */ |
| for (IvyNode node : conflicts) { |
| ModuleRevisionId modRev = node.getResolvedId(); |
| if (getSettings().getVersionMatcher().isDynamic(modRev)) { |
| return null; |
| } |
| } |
| |
| List<IvyNode> unevicted = new ArrayList<>(); |
| for (IvyNode node : conflicts) { |
| if (!node.isCompletelyEvicted()) { |
| unevicted.add(node); |
| } |
| } |
| if (unevicted.size() > 0) { |
| conflicts = unevicted; |
| } |
| |
| try { |
| IvyNodeArtifactInfo latest = (IvyNodeArtifactInfo) getStrategy().findLatest( |
| toArtifactInfo(conflicts), null); |
| if (latest != null) { |
| return Collections.singleton(latest.getNode()); |
| } else { |
| return conflicts; |
| } |
| } catch (NoConflictResolvedYetException ex) { |
| // we have not enough information in the nodes to resolve conflict |
| // according to the resolveConflicts contract, we must return null |
| return null; |
| } |
| } |
| |
| protected ArtifactInfo[] toArtifactInfo(Collection<IvyNode> conflicts) { |
| List<ArtifactInfo> artifacts = new ArrayList<>(conflicts.size()); |
| for (IvyNode node : conflicts) { |
| artifacts.add(new IvyNodeArtifactInfo(node)); |
| } |
| return artifacts.toArray(new ArtifactInfo[artifacts.size()]); |
| } |
| |
| public LatestStrategy getStrategy() { |
| if (strategy == null) { |
| if (strategyName != null) { |
| strategy = getSettings().getLatestStrategy(strategyName); |
| if (strategy == null) { |
| Message.error("unknown latest strategy: " + strategyName); |
| strategy = getSettings().getDefaultLatestStrategy(); |
| } |
| } else { |
| strategy = getSettings().getDefaultLatestStrategy(); |
| } |
| } |
| return strategy; |
| } |
| |
| /** |
| * To conform to configurator API |
| * |
| * @param strategyName ditto |
| */ |
| public void setLatest(String strategyName) { |
| this.strategyName = strategyName; |
| } |
| |
| public void setStrategy(LatestStrategy strategy) { |
| this.strategy = strategy; |
| } |
| |
| @Override |
| public String toString() { |
| return strategy != null ? String.valueOf(strategy) : strategyName; |
| } |
| } |