View Javadoc

1   /**
2    * Copyright 2011-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.maven.plugins.graph.sanitize;
17  
18  import static org.kuali.maven.plugins.graph.pojo.State.CONFLICT;
19  import static org.kuali.maven.plugins.graph.pojo.State.DUPLICATE;
20  
21  import java.util.List;
22  
23  import org.apache.maven.artifact.Artifact;
24  import org.apache.maven.shared.dependency.tree.DependencyNode;
25  import org.kuali.maven.plugins.graph.pojo.MavenContext;
26  import org.kuali.maven.plugins.graph.pojo.State;
27  import org.kuali.maven.plugins.graph.tree.Node;
28  import org.kuali.maven.plugins.graph.tree.TreeHelper;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  import org.springframework.util.Assert;
32  
33  /**
34   * <p>
35   * Nothing in this sanitizer takes into account the overall build tree. It only performs checks on individual nodes.
36   * </p>
37   *
38   * <p>
39   * Checks that nodes marked as <code>State.DUPLICATE</code> have 'related' artifacts identical to the main artifact
40   * stored at that node. Also checks to make sure nodes marked as <code>State.CONFLICT</code> have a 'related' artifact
41   * that is a different version from the main artifact stored at that node.
42   * </p>
43   *
44   * <p>
45   * Any <code>State.DUPLICATE</code> node that does not have an identical related artifact is switched to
46   * <code>State.CONFLICT</code>
47   * </p>
48   *
49   * <p>
50   * Any <code>State.CONFLICT</code> node that has an identical related artifact is switched to
51   * <code>State.DUPLICATE</code>
52   * </p>
53   *
54   * @author jeffcaddel
55   */
56  public class RelatedArtifactSanitizer implements NodeSanitizer<MavenContext> {
57      private static final Logger logger = LoggerFactory.getLogger(RelatedArtifactSanitizer.class);
58      TreeHelper helper = new TreeHelper();
59  
60      @Override
61      public void sanitize(Node<MavenContext> node) {
62          // Extract anything Maven has marked as a duplicate or conflict
63          List<MavenContext> contexts = helper.getList(node, DUPLICATE, CONFLICT);
64          for (MavenContext context : contexts) {
65              // Restore sanity
66              sanitize(context);
67  
68          }
69      }
70  
71      protected void sanitize(MavenContext context) {
72          DependencyNode dn = context.getDependencyNode();
73          // The validation logic assures that artifact and related are not null for conflicts and duplicates
74          Artifact artifact = dn.getArtifact();
75          Artifact related = dn.getRelatedArtifact();
76          State state = State.getState(dn.getState());
77  
78          // Test them to see if they are exactly the same or just similar
79          boolean equal = helper.equals(artifact, related);
80          boolean similar = helper.similar(artifact, related);
81  
82          // The validation logic assures that at least one is true, but no harm in double checking
83          Assert.isTrue(equal || similar, "Invalid state.");
84  
85          if (equal) {
86              // The main artifact and related artifact are exactly the same
87              if (state == CONFLICT) {
88                  // Maven told us this was a CONFLICT, yet the artifacts are exactly the same.
89                  // WTF is up with that? The only thing it is possible to do at this point is
90                  // switch this artifact out WITH THE EXACT SAME ARTIFACT!!! How is that a conflict?
91                  logger.info(CONFLICT + "->" + DUPLICATE + " " + artifact);
92              }
93              // Set state to duplicate and make sure replacement is nulled out
94              context.setState(DUPLICATE);
95              context.setReplacement(null);
96          } else if (similar) {
97              // The main artifact and related artifact are NOT exactly the same, but they differ only by version
98              if (state == DUPLICATE) {
99                  // Maven told us this was a DUPLICATE, yet the related artifact is a different version
100                 // We are going to assume the duplicate flag is a mistake and re-flag this as a conflict
101                 logger.info(DUPLICATE + "->" + CONFLICT + " " + artifact);
102             }
103             // Set state to conflict, and store the artifact Maven replaced it with
104             context.setState(CONFLICT);
105             context.setReplacement(related);
106         } else {
107             // Something has gone horribly wrong
108             Assert.isTrue(false, "Invalid state");
109         }
110     }
111 
112 }