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.apache.maven.plugins.assembly.utils;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.Collections;
24  import java.util.Iterator;
25  import java.util.LinkedHashSet;
26  import java.util.List;
27  import java.util.Set;
28  
29  import org.apache.maven.artifact.Artifact;
30  import org.apache.maven.project.MavenProject;
31  import org.slf4j.Logger;
32  
33  /**
34   *
35   */
36  public final class ProjectUtils {
37  
38      private ProjectUtils() {}
39  
40      public static String getClassifier(Artifact artifact) {
41          String classifier = artifact.getClassifier();
42          if (classifier != null && classifier.length() == 0) {
43              classifier = null;
44          }
45          return classifier;
46      }
47  
48      public static Set<MavenProject> getProjectModules(
49              final MavenProject project,
50              final List<MavenProject> reactorProjects,
51              final boolean includeSubModules,
52              final Logger logger)
53              throws IOException {
54          final Set<MavenProject> singleParentSet = Collections.singleton(project);
55  
56          final Set<MavenProject> moduleCandidates = new LinkedHashSet<>(reactorProjects);
57  
58          final Set<MavenProject> modules = new LinkedHashSet<>();
59  
60          // we temporarily add the master project to the modules set, since this
61          // set is pulling double duty as a set of
62          // potential module parents in the tree rooted at the master
63          // project...this allows us to use the same looping
64          // algorithm below to discover both direct modules of the master project
65          // AND modules of those direct modules.
66          modules.add(project);
67  
68          int changed;
69  
70          do {
71              changed = 0;
72  
73              for (final Iterator<MavenProject> candidateIterator = moduleCandidates.iterator();
74                      candidateIterator.hasNext(); ) {
75                  final MavenProject moduleCandidate = candidateIterator.next();
76  
77                  if (moduleCandidate.getFile() == null) {
78                      logger.warn("Cannot compute whether " + moduleCandidate.getId() + " is a module of: "
79                              + project.getId() + "; it does not have an associated POM file on the local filesystem.");
80                      continue;
81                  }
82  
83                  Set<MavenProject> currentPotentialParents;
84                  if (includeSubModules) {
85                      currentPotentialParents = new LinkedHashSet<>(modules);
86                  } else {
87                      currentPotentialParents = singleParentSet;
88                  }
89  
90                  for (final MavenProject potentialParent : currentPotentialParents) {
91                      if (potentialParent.getFile() == null) {
92                          logger.warn("Cannot use: " + moduleCandidate.getId()
93                                  + " as a potential module-parent while computing the module set for: "
94                                  + project.getId()
95                                  + "; it does not have an associated POM file on the local filesystem.");
96                          continue;
97                      }
98  
99                      // if this parent has an entry for the module candidate in
100                     // the path adjustments map, it's a direct
101                     // module of that parent.
102                     if (projectContainsModule(potentialParent, moduleCandidate)) {
103                         // add the candidate to the list of modules (and
104                         // potential parents)
105                         modules.add(moduleCandidate);
106 
107                         // remove the candidate from the candidate pool, because
108                         // it's been verified.
109                         candidateIterator.remove();
110 
111                         // increment the change counter, to show that we
112                         // verified a new module on this pass.
113                         changed++;
114 
115                         // We need to move on to the next candidate since this one was just verified
116                         break;
117                     }
118                 }
119             }
120         } while (changed != 0);
121 
122         // remove the master project from the modules set, now that we're done
123         // using it as a set of potential module
124         // parents...
125         modules.remove(project);
126 
127         return modules;
128     }
129 
130     private static boolean projectContainsModule(final MavenProject mainProject, final MavenProject moduleProject)
131             throws IOException {
132         final List<String> modules = mainProject.getModules();
133         final File basedir = mainProject.getBasedir();
134 
135         final File moduleFile = moduleProject.getFile().getCanonicalFile();
136 
137         File moduleBasedir = moduleProject.getBasedir();
138 
139         if (moduleBasedir == null) {
140             moduleBasedir = moduleFile.getParentFile();
141 
142             if (moduleBasedir == null) {
143                 moduleBasedir = new File(".");
144             }
145         }
146 
147         moduleBasedir = moduleBasedir.getCanonicalFile();
148 
149         for (final String moduleSubpath : modules) {
150             final File moduleDir = new File(basedir, moduleSubpath).getCanonicalFile();
151 
152             if (moduleDir.equals(moduleFile) || moduleDir.equals(moduleBasedir)) {
153                 return true;
154             }
155         }
156 
157         return false;
158     }
159 }