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.executor.internal;
20  
21  import java.nio.file.Path;
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.Map;
25  import java.util.concurrent.ConcurrentHashMap;
26  
27  import org.apache.maven.api.annotations.Nullable;
28  import org.apache.maven.api.cli.Executor;
29  import org.apache.maven.api.cli.ExecutorException;
30  import org.apache.maven.api.cli.ExecutorRequest;
31  import org.apache.maven.cling.executor.ExecutorHelper;
32  import org.apache.maven.cling.executor.ExecutorTool;
33  
34  import static java.util.Objects.requireNonNull;
35  
36  /**
37   * Simple router to executors, and delegate to executor tool.
38   */
39  public class HelperImpl implements ExecutorHelper {
40      private final Mode defaultMode;
41      private final Path installationDirectory;
42      private final ExecutorTool executorTool;
43      private final HashMap<Mode, Executor> executors;
44  
45      private final ConcurrentHashMap<String, String> cache;
46  
47      public HelperImpl(Mode defaultMode, @Nullable Path installationDirectory, Executor embedded, Executor forked) {
48          this.defaultMode = requireNonNull(defaultMode);
49          this.installationDirectory = installationDirectory != null
50                  ? ExecutorRequest.getCanonicalPath(installationDirectory)
51                  : ExecutorRequest.discoverMavenHome();
52          this.executorTool = new ToolboxTool(this);
53          this.executors = new HashMap<>();
54  
55          this.executors.put(Mode.EMBEDDED, requireNonNull(embedded, "embedded"));
56          this.executors.put(Mode.FORKED, requireNonNull(forked, "forked"));
57          this.cache = new ConcurrentHashMap<>();
58      }
59  
60      @Override
61      public Mode getDefaultMode() {
62          return defaultMode;
63      }
64  
65      @Override
66      public ExecutorRequest.Builder executorRequest() {
67          return ExecutorRequest.mavenBuilder(installationDirectory);
68      }
69  
70      @Override
71      public int execute(Mode mode, ExecutorRequest executorRequest) throws ExecutorException {
72          return getExecutor(mode, executorRequest).execute(executorRequest);
73      }
74  
75      @Override
76      public String mavenVersion() {
77          return cache.computeIfAbsent("maven.version", k -> {
78              ExecutorRequest request = executorRequest().build();
79              return getExecutor(Mode.AUTO, request).mavenVersion(request);
80          });
81      }
82  
83      @Override
84      public Map<String, String> dump(ExecutorRequest.Builder request) throws ExecutorException {
85          return executorTool.dump(request);
86      }
87  
88      @Override
89      public String localRepository(ExecutorRequest.Builder request) throws ExecutorException {
90          return executorTool.localRepository(request);
91      }
92  
93      @Override
94      public String artifactPath(ExecutorRequest.Builder request, String gav, String repositoryId)
95              throws ExecutorException {
96          return executorTool.artifactPath(request, gav, repositoryId);
97      }
98  
99      @Override
100     public String metadataPath(ExecutorRequest.Builder request, String gav, String repositoryId)
101             throws ExecutorException {
102         return executorTool.metadataPath(request, gav, repositoryId);
103     }
104 
105     protected Executor getExecutor(Mode mode, ExecutorRequest request) throws ExecutorException {
106         return switch (mode) {
107             case AUTO -> getExecutorByRequest(request);
108             case EMBEDDED -> executors.get(Mode.EMBEDDED);
109             case FORKED -> executors.get(Mode.FORKED);
110         };
111     }
112 
113     private Executor getExecutorByRequest(ExecutorRequest request) {
114         if (request.environmentVariables().orElse(Collections.emptyMap()).isEmpty()
115                 && request.jvmArguments().orElse(Collections.emptyList()).isEmpty()) {
116             return getExecutor(Mode.EMBEDDED, request);
117         } else {
118             return getExecutor(Mode.FORKED, request);
119         }
120     }
121 }