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.api.cli;
20  
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.nio.file.Path;
24  import java.util.Arrays;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Optional;
28  
29  import org.apache.maven.api.annotations.Experimental;
30  import org.apache.maven.api.annotations.Immutable;
31  import org.apache.maven.api.annotations.Nonnull;
32  import org.apache.maven.api.annotations.Nullable;
33  import org.apache.maven.api.services.Lookup;
34  import org.apache.maven.api.services.LookupException;
35  import org.apache.maven.api.services.MessageBuilderFactory;
36  
37  import static java.util.Objects.requireNonNull;
38  
39  /**
40   * Represents a request to parse Maven command-line arguments.
41   * This interface encapsulates all the necessary information needed to parse
42   * Maven commands and arguments into an {@link InvokerRequest}.
43   *
44   * @since 4.0.0
45   */
46  @Immutable
47  @Experimental
48  public interface ParserRequest {
49      String MVN_CMD = "mvn";
50      String MVN_NAME = "Maven";
51  
52      String MVNENC_CMD = "mvnenc";
53      String MVNENC_NAME = "Maven Password Encrypting Tool";
54  
55      /**
56       * Returns the Maven command to be executed. This command is used in some invokers (ie forked) but also to
57       * present help to user.
58       *
59       * @return the command string
60       */
61      @Nonnull
62      String command();
63  
64      /**
65       * Returns the Maven command name (ie "Maven"). This string is used in some invokers to complete error messages.
66       *
67       * @return the command (human) name
68       */
69      String commandName();
70  
71      /**
72       * Returns the logger to be used during the parsing process.
73       *
74       * @return the logger instance
75       */
76      @Nonnull
77      Logger logger();
78  
79      /**
80       * Returns the factory for creating message builders.
81       *
82       * @return the message builder factory
83       */
84      @Nonnull
85      MessageBuilderFactory messageBuilderFactory();
86  
87      /**
88       * Returns the command-line arguments to be parsed.
89       *
90       * @return a list of argument strings
91       */
92      @Nonnull
93      List<String> args();
94  
95      /**
96       * Per-request {@link Lookup} for customization.
97       *
98       * @return a lookup possibly with custom components
99       */
100     @Nonnull
101     Lookup lookup();
102 
103     /**
104      * Returns the current working directory for the Maven execution.
105      * If not explicitly set, this value will be detected during parsing.
106      *
107      * @return the current working directory path, or null if not set
108      */
109     @Nullable
110     Path cwd();
111 
112     /**
113      * Returns the Maven home directory.
114      * If not explicitly set, this value will be detected during parsing.
115      *
116      * @return the Maven home directory path, or null if not set
117      */
118     @Nullable
119     Path mavenHome();
120 
121     /**
122      * Returns the user's home directory.
123      * If not explicitly set, this value will be detected during parsing.
124      *
125      * @return the user's home directory path, or null if not set
126      */
127     @Nullable
128     Path userHome();
129 
130     /**
131      * Returns the input stream to be used for the Maven execution.
132      * If not set, System.in will be used by default.
133      *
134      * @return the input stream, or null if not set
135      */
136     @Nullable
137     InputStream in();
138 
139     /**
140      * Returns the output stream to be used for the Maven execution.
141      * If not set, System.out will be used by default.
142      *
143      * @return the output stream, or null if not set
144      */
145     @Nullable
146     OutputStream out();
147 
148     /**
149      * Returns the error stream to be used for the Maven execution.
150      * If not set, System.err will be used by default.
151      *
152      * @return the error stream, or null if not set
153      */
154     @Nullable
155     OutputStream err();
156 
157     /**
158      * Creates a new Builder instance for constructing a Maven ParserRequest.
159      *
160      * @param args the command-line arguments
161      * @param logger the logger to be used during parsing
162      * @param messageBuilderFactory the factory for creating message builders
163      * @return a new Builder instance
164      */
165     @Nonnull
166     static Builder mvn(
167             @Nonnull String[] args, @Nonnull Logger logger, @Nonnull MessageBuilderFactory messageBuilderFactory) {
168         return mvn(Arrays.asList(args), logger, messageBuilderFactory);
169     }
170 
171     /**
172      * Creates a new Builder instance for constructing a Maven ParserRequest.
173      *
174      * @param args the command-line arguments
175      * @param logger the logger to be used during parsing
176      * @param messageBuilderFactory the factory for creating message builders
177      * @return a new Builder instance
178      */
179     @Nonnull
180     static Builder mvn(
181             @Nonnull List<String> args, @Nonnull Logger logger, @Nonnull MessageBuilderFactory messageBuilderFactory) {
182         return builder(MVN_CMD, MVN_NAME, args, logger, messageBuilderFactory);
183     }
184 
185     /**
186      * Creates a new Builder instance for constructing a Maven Encrypting Tool ParserRequest.
187      *
188      * @param args the command-line arguments
189      * @param logger the logger to be used during parsing
190      * @param messageBuilderFactory the factory for creating message builders
191      * @return a new Builder instance
192      */
193     @Nonnull
194     static Builder mvnenc(
195             @Nonnull String[] args, @Nonnull Logger logger, @Nonnull MessageBuilderFactory messageBuilderFactory) {
196         return mvnenc(Arrays.asList(args), logger, messageBuilderFactory);
197     }
198 
199     /**
200      * Creates a new Builder instance for constructing a Maven Encrypting Tool ParserRequest.
201      *
202      * @param args the command-line arguments
203      * @param logger the logger to be used during parsing
204      * @param messageBuilderFactory the factory for creating message builders
205      * @return a new Builder instance
206      */
207     @Nonnull
208     static Builder mvnenc(
209             @Nonnull List<String> args, @Nonnull Logger logger, @Nonnull MessageBuilderFactory messageBuilderFactory) {
210         return builder(MVNENC_CMD, MVNENC_NAME, args, logger, messageBuilderFactory);
211     }
212 
213     /**
214      * Creates a new Builder instance for constructing a ParserRequest.
215      *
216      * @param command the Maven command to be executed
217      * @param commandName the Maven command Name to be executed
218      * @param args the command-line arguments
219      * @param logger the logger to be used during parsing
220      * @param messageBuilderFactory the factory for creating message builders
221      * @return a new Builder instance
222      */
223     @Nonnull
224     static Builder builder(
225             @Nonnull String command,
226             @Nonnull String commandName,
227             @Nonnull List<String> args,
228             @Nonnull Logger logger,
229             @Nonnull MessageBuilderFactory messageBuilderFactory) {
230         return new Builder(command, commandName, args, logger, messageBuilderFactory);
231     }
232 
233     class Builder {
234         private final String command;
235         private final String commandName;
236         private final List<String> args;
237         private final Logger logger;
238         private final MessageBuilderFactory messageBuilderFactory;
239         private Lookup lookup = EMPTY_LOOKUP;
240         private Path cwd;
241         private Path mavenHome;
242         private Path userHome;
243         private InputStream in;
244         private OutputStream out;
245         private OutputStream err;
246 
247         private Builder(
248                 String command,
249                 String commandName,
250                 List<String> args,
251                 Logger logger,
252                 MessageBuilderFactory messageBuilderFactory) {
253             this.command = requireNonNull(command, "command");
254             this.commandName = requireNonNull(commandName, "commandName");
255             this.args = requireNonNull(args, "args");
256             this.logger = requireNonNull(logger, "logger");
257             this.messageBuilderFactory = requireNonNull(messageBuilderFactory, "messageBuilderFactory");
258         }
259 
260         public Builder lookup(@Nonnull Lookup lookup) {
261             this.lookup = requireNonNull(lookup);
262             return this;
263         }
264 
265         public Builder cwd(Path cwd) {
266             this.cwd = cwd;
267             return this;
268         }
269 
270         public Builder mavenHome(Path mavenHome) {
271             this.mavenHome = mavenHome;
272             return this;
273         }
274 
275         public Builder userHome(Path userHome) {
276             this.userHome = userHome;
277             return this;
278         }
279 
280         public Builder in(InputStream in) {
281             this.in = in;
282             return this;
283         }
284 
285         public Builder out(OutputStream out) {
286             this.out = out;
287             return this;
288         }
289 
290         public Builder err(OutputStream err) {
291             this.err = err;
292             return this;
293         }
294 
295         public ParserRequest build() {
296             return new ParserRequestImpl(
297                     command,
298                     commandName,
299                     args,
300                     logger,
301                     messageBuilderFactory,
302                     lookup,
303                     cwd,
304                     mavenHome,
305                     userHome,
306                     in,
307                     out,
308                     err);
309         }
310 
311         @SuppressWarnings("ParameterNumber")
312         private static class ParserRequestImpl implements ParserRequest {
313             private final String command;
314             private final String commandName;
315             private final Logger logger;
316             private final MessageBuilderFactory messageBuilderFactory;
317             private final List<String> args;
318             private final Lookup lookup;
319             private final Path cwd;
320             private final Path mavenHome;
321             private final Path userHome;
322             private final InputStream in;
323             private final OutputStream out;
324             private final OutputStream err;
325 
326             private ParserRequestImpl(
327                     String command,
328                     String commandName,
329                     List<String> args,
330                     Logger logger,
331                     MessageBuilderFactory messageBuilderFactory,
332                     Lookup lookup,
333                     Path cwd,
334                     Path mavenHome,
335                     Path userHome,
336                     InputStream in,
337                     OutputStream out,
338                     OutputStream err) {
339                 this.command = requireNonNull(command, "command");
340                 this.commandName = requireNonNull(commandName, "commandName");
341                 this.args = List.copyOf(requireNonNull(args, "args"));
342                 this.logger = requireNonNull(logger, "logger");
343                 this.messageBuilderFactory = requireNonNull(messageBuilderFactory, "messageBuilderFactory");
344                 this.lookup = requireNonNull(lookup, "lookup");
345                 this.cwd = cwd;
346                 this.mavenHome = mavenHome;
347                 this.userHome = userHome;
348                 this.in = in;
349                 this.out = out;
350                 this.err = err;
351             }
352 
353             @Override
354             public String command() {
355                 return command;
356             }
357 
358             @Override
359             public String commandName() {
360                 return commandName;
361             }
362 
363             @Override
364             public Logger logger() {
365                 return logger;
366             }
367 
368             @Override
369             public MessageBuilderFactory messageBuilderFactory() {
370                 return messageBuilderFactory;
371             }
372 
373             @Override
374             public List<String> args() {
375                 return args;
376             }
377 
378             @Override
379             public Lookup lookup() {
380                 return lookup;
381             }
382 
383             @Override
384             public Path cwd() {
385                 return cwd;
386             }
387 
388             @Override
389             public Path mavenHome() {
390                 return mavenHome;
391             }
392 
393             @Override
394             public Path userHome() {
395                 return userHome;
396             }
397 
398             @Override
399             public InputStream in() {
400                 return in;
401             }
402 
403             @Override
404             public OutputStream out() {
405                 return out;
406             }
407 
408             @Override
409             public OutputStream err() {
410                 return err;
411             }
412         }
413 
414         private static final Lookup EMPTY_LOOKUP = new Lookup() {
415             @Override
416             public <T> T lookup(Class<T> type) {
417                 throw new LookupException("empty lookup");
418             }
419 
420             @Override
421             public <T> T lookup(Class<T> type, String name) {
422                 throw new LookupException("empty lookup");
423             }
424 
425             @Override
426             public <T> Optional<T> lookupOptional(Class<T> type) {
427                 return Optional.empty();
428             }
429 
430             @Override
431             public <T> Optional<T> lookupOptional(Class<T> type, String name) {
432                 return Optional.empty();
433             }
434 
435             @Override
436             public <T> List<T> lookupList(Class<T> type) {
437                 return List.of();
438             }
439 
440             @Override
441             public <T> Map<String, T> lookupMap(Class<T> type) {
442                 return Map.of();
443             }
444         };
445     }
446 }