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.internal.impl.model.rootlocator;
20  
21  import java.nio.file.Path;
22  import java.nio.file.Paths;
23  import java.util.List;
24  import java.util.Objects;
25  import java.util.Optional;
26  import java.util.ServiceLoader;
27  
28  import org.apache.maven.api.annotations.Nonnull;
29  import org.apache.maven.api.di.Named;
30  import org.apache.maven.api.services.model.RootDetector;
31  import org.apache.maven.api.services.model.RootLocator;
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  
35  import static java.util.Objects.requireNonNull;
36  
37  @Named
38  public class DefaultRootLocator implements RootLocator {
39      private final Logger logger = LoggerFactory.getLogger(getClass());
40  
41      private final List<RootDetector> rootDetectors;
42  
43      public DefaultRootLocator() {
44          this.rootDetectors = ServiceLoader.load(RootDetector.class).stream()
45                  .map(ServiceLoader.Provider::get)
46                  .toList();
47      }
48  
49      @Override
50      public Path findRoot(Path basedir) {
51          requireNonNull(basedir, getNoRootMessage());
52          Path rootDirectory = basedir;
53          while (rootDirectory != null && !isRootDirectory(rootDirectory)) {
54              rootDirectory = rootDirectory.getParent();
55          }
56          return rootDirectory;
57      }
58  
59      @Nonnull
60      public Path findMandatoryRoot(@Nonnull Path basedir) {
61          Path rootDirectory = findRoot(basedir);
62          Optional<Path> rdf = getRootDirectoryFallback();
63          if (rootDirectory == null) {
64              rootDirectory = rdf.orElseThrow(() -> new IllegalStateException(getNoRootMessage()));
65              logger.warn(getNoRootMessage());
66          } else {
67              if (rdf.isPresent() && !Objects.equals(rootDirectory, rdf.get())) {
68                  logger.warn("Project root directory and multiModuleProjectDirectory are not aligned");
69              }
70          }
71          return rootDirectory;
72      }
73  
74      protected boolean isRootDirectory(Path dir) {
75          requireNonNull(dir, "dir is null");
76          for (RootDetector rootDetector : rootDetectors) {
77              if (rootDetector.isRootDirectory(dir)) {
78                  return true;
79              }
80          }
81          return false;
82      }
83  
84      protected Optional<Path> getRootDirectoryFallback() {
85          String mmpd = System.getProperty("maven.multiModuleProjectDirectory");
86          if (mmpd != null) {
87              return Optional.of(Paths.get(mmpd));
88          }
89          return Optional.empty();
90      }
91  }