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.cling.invoker.mvn;
20  
21  import java.io.IOException;
22  import java.nio.charset.Charset;
23  import java.nio.file.Files;
24  import java.nio.file.Path;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.stream.Stream;
28  
29  import org.apache.commons.cli.ParseException;
30  import org.apache.maven.api.cli.Options;
31  import org.apache.maven.api.cli.mvn.MavenOptions;
32  import org.apache.maven.cling.invoker.BaseParser;
33  
34  public class MavenParser extends BaseParser {
35      @Override
36      protected Options parseCliOptions(LocalContext context) {
37          ArrayList<MavenOptions> result = new ArrayList<>();
38          // CLI args
39          MavenOptions cliOptions = parseMavenCliOptions(context.parserRequest.args());
40          result.add(cliOptions);
41          // atFile option
42          if (cliOptions.atFile().isPresent()) {
43              Path file = context.cwd.resolve(cliOptions.atFile().orElseThrow());
44              if (Files.isRegularFile(file)) {
45                  result.add(parseMavenAtFileOptions(file));
46              } else {
47                  throw new IllegalArgumentException("Specified file does not exists (" + file + ")");
48              }
49          }
50          // maven.config; if exists
51          Path mavenConfig = context.rootDirectory != null ? context.rootDirectory.resolve(".mvn/maven.config") : null;
52          if (mavenConfig != null && Files.isRegularFile(mavenConfig)) {
53              result.add(parseMavenConfigOptions(mavenConfig));
54          }
55          return LayeredMavenOptions.layerMavenOptions(result);
56      }
57  
58      protected MavenOptions parseMavenCliOptions(List<String> args) {
59          try {
60              return parseArgs(Options.SOURCE_CLI, args);
61          } catch (ParseException e) {
62              throw new IllegalArgumentException("Failed to parse CLI arguments: " + e.getMessage(), e.getCause());
63          }
64      }
65  
66      protected MavenOptions parseMavenAtFileOptions(Path atFile) {
67          try (Stream<String> lines = Files.lines(atFile, Charset.defaultCharset())) {
68              List<String> args =
69                      lines.filter(arg -> !arg.isEmpty() && !arg.startsWith("#")).toList();
70              return parseArgs("atFile", args);
71          } catch (ParseException e) {
72              throw new IllegalArgumentException(
73                      "Failed to parse arguments from file (" + atFile + "): " + e.getMessage(), e.getCause());
74          } catch (IOException e) {
75              throw new IllegalStateException("Error reading config file: " + atFile, e);
76          }
77      }
78  
79      protected MavenOptions parseMavenConfigOptions(Path configFile) {
80          try (Stream<String> lines = Files.lines(configFile, Charset.defaultCharset())) {
81              List<String> args =
82                      lines.filter(arg -> !arg.isEmpty() && !arg.startsWith("#")).toList();
83              MavenOptions options = parseArgs("maven.config", args);
84              if (options.goals().isPresent()) {
85                  // This file can only contain options, not args (goals or phases)
86                  throw new IllegalArgumentException("Unrecognized entries in maven.config (" + configFile + ") file: "
87                          + options.goals().get());
88              }
89              return options;
90          } catch (ParseException e) {
91              throw new IllegalArgumentException(
92                      "Failed to parse arguments from maven.config file (" + configFile + "): " + e.getMessage(),
93                      e.getCause());
94          } catch (IOException e) {
95              throw new IllegalStateException("Error reading config file: " + configFile, e);
96          }
97      }
98  
99      protected MavenOptions parseArgs(String source, List<String> args) throws ParseException {
100         return CommonsCliMavenOptions.parse(source, args.toArray(new String[0]));
101     }
102 }